Mit Glass können Sie umfassende Interaktionsmöglichkeiten mit Ihren Karten erstellen, z. B. Scrollen. und Animationen.
Scrollen von Karten in Aktivitäten
Das Glass-Display und das Touchpad eignen sich hervorragend zum Anzeigen von Karten,
wie in der Glass-Zeitachse. Wenn Sie eine Aktivität erstellen, können Sie
den gleichen Effekt haben.
CardScrollView
Widget.
- Implementieren Sie ein
CardScrollAdapter
um Karten für dieCardScrollView
Sie können selbst eine Standardansichtshierarchie erstellen oder die MethodeCardBuilder
. - Erstellen:
CardScrollView
mit demCardScrollAdapter
als Lieferant von Karten. - Lege die Inhaltsansicht deiner Aktivität als die
CardScrollView
oder dieCardScrollView
in einem Layout.
Hier sehen Sie eine einfache Implementierung, bei der durch drei Karten gescrollt wird:
public class CardScrollActivity extends Activity {
private List<CardBuilder> mCards;
private CardScrollView mCardScrollView;
private ExampleCardScrollAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
createCards();
mCardScrollView = new CardScrollView(this);
mAdapter = new ExampleCardScrollAdapter();
mCardScrollView.setAdapter(mAdapter);
mCardScrollView.activate();
setContentView(mCardScrollView);
}
private void createCards() {
mCards = new ArrayList<CardBuilder>();
mCards.add(new CardBuilder(this, CardBuilder.Layout.TEXT)
.setText("This card has a footer.")
.setFootnote("I'm the footer!"));
mCards.add(new CardBuilder(this, CardBuilder.Layout.CAPTION)
.setText("This card has a puppy background image.")
.setFootnote("How can you resist?")
.addImage(R.drawable.puppy_bg));
mCards.add(new CardBuilder(this, CardBuilder.Layout.COLUMNS)
.setText("This card has a mosaic of puppies.")
.setFootnote("Aren't they precious?")
.addImage(R.drawable.puppy_small_1);
.addImage(R.drawable.puppy_small_2);
.addImage(R.drawable.puppy_small_3));
}
private class ExampleCardScrollAdapter extends CardScrollAdapter {
@Override
public int getPosition(Object item) {
return mCards.indexOf(item);
}
@Override
public int getCount() {
return mCards.size();
}
@Override
public Object getItem(int position) {
return mCards.get(position);
}
@Override
public int getViewTypeCount() {
return CardBuilder.getViewTypeCount();
}
@Override
public int getItemViewType(int position){
return mCards.get(position).getItemViewType();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
return mCards.get(position).getView(convertView, parent);
}
}
}
Mit scrollbaren Karten interagieren
Seit
CardScrollView
erstreckt sich über AdapterView
können Sie die Android-Standard-Listener implementieren.
- Übernommene aufrufen
setOnItemClickListener()
aufCardScrollView
. - Implementieren eines
onItemClick()
Handler für das Tap-Ereignis.
Hier ist eine Erweiterung des vorherigen Beispiels, die einen Tippton wiedergibt wenn Sie auf eine Karte tippen:
@Override
protected void onCreate(Bundle savedInstanceState) {
...
setupClickListener();
setContentView(mCardScrollView);
}
private void setupClickListener() {
mCardScrollView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
am.playSoundEffect(Sounds.TAP);
}
});
}
Scrollende Karten animieren
Für das Scrollen von Karten stehen drei Animationen zur Verfügung: „Navigation“, „Insert“ (Einfügen) und „Deletion“ (Löschen).
- Implementieren Sie eine Einfüge- oder Löschaktion für eine Karte an einer bestimmten Position im Kartensatz.
- Anruf
animate()
und verwenden Sie einen Wert aus derCardScrollView.Animation
-Enum. Um eine flüssigere Animation anzuzeigen, entfernen Sie alle Verweise auf
notifyDataSetChanged()
Dieanimate()
die Aktualisierung der Dataset-Ansicht.private class ExampleCardScrollAdapter extends CardScrollAdapter { ... // Inserts a card into the adapter, without notifying. public void insertCardWithoutNotification(int position, CardBuilder card) { mCards.add(position, card); } } private void insertNewCard(int position, CardBuilder card) { // Insert new card in the adapter, but don't call // notifyDataSetChanged() yet. Instead, request proper animation // to inserted card from card scroller, which will notify the // adapter at the right time during the animation. mAdapter.insertCardWithoutNotification(position, card); mCardScrollView.animate(position, CardScrollView.Animation.INSERTION); }
Leistungs- und Implementierungstipps für scrollbare Karten
Berücksichtigen Sie beim Erstellen von Creatives die folgenden Auswirkungen auf Design und Leistung zum Scrollen der Karte.
Lebenszyklus der Karte
Zur Steigerung der Leistung kann ein CardScrollView
nur eine Teilmenge der Karten lädt,
CardScrollAdapter
(in der Regel die für den Nutzer sichtbaren und einige weitere).
Aus diesem Grund kann eine Karte einen der folgenden vier allgemeinen Status haben:
- Detached (Losgelöst): Für die Scroll-Ansicht der Karte wird diese Karte derzeit nicht benötigt.
Sie werden über die
onDetachedToWindow()
der Karte benachrichtigt , wenn zuvor eine Karte angehängt und dann getrennt wurde. - Angehängt: In der Scrollansicht wird die Karte vom Adapter angefordert,
getView()
, da die Karte kurz davor steht, „aktiviert“ zu werden. In diesem Fall werden Sie mit der MethodeonAttachedToWindow()
der Karte benachrichtigt. - Aktiviert: Die Karte ist für den Nutzer teilweise sichtbar, aber die Karte wird gescrollt.
Ansicht nicht "ausgewählt" ist die Karte, die dem Nutzer angezeigt wird. Die
Methode isActivated()'
gibt in diesem Fall
true
zurück. - Ausgewählt: Die Karte belegt die
auf dem gesamten Bildschirm. Wenn Sie
getSelectedView()
aufrufen, wird die aktuell ausgewählte Karte zurückgegeben. Die MethodeisSelected()
gibt in diesem Fall „true“.
Wenn Sie die Ansicht
Ihrer Karte animieren oder andere kostspielige Vorgänge ausführen,
die Vorgänge starten und beenden,
onAttachedToWindow()
und
onDetachedToWindow()
um Ressourcen zu sparen.
Kartenrecycling
Wenn eine Karte nicht mehr angehängt wird, wird das mit kann die Karte recycelt und durch eine angeschlossene Karte verwendet werden. Das Recycling von Ansichten mit aktualisierten Informationen ist viel effizienter als neue Datenansichten erstellen.
Wenn Sie die Vorteile des Kartenrecyclings nutzen möchten, implementieren Sie die
getItemViewType()
,
getViewTypeCount()
,
und getView()
Methoden der
CardScrollAdapter
.
. Anschließend verwenden Sie einige der praktischen Methoden in der CardBuilder
.
um das Recycling in CardScrollAdapter
zu implementieren,
wie im folgenden Beispiel:
private List<CardBuilder> mCards;
...
/**
* Returns the number of view types for the CardBuilder class. The
* CardBuilder class has a convenience method that returns this value for
* you.
*/
@Override
public int getViewTypeCount() {
return CardBuilder.getViewTypeCount();
}
/**
* Returns the view type of this card, so the system can figure out
* if it can be recycled. The CardBuilder.getItemViewType() method
* returns it's own type.
*/
@Override
public int getItemViewType(int position){
return mCards.get(position).getItemViewType();
}
/**
* When requesting a card from the adapter, recycle the view if possible.
* The CardBuilder.getView() method automatically recycles the convertView
* it receives, if possible, or creates a new view if convertView is null or
* of the wrong type.
*/
@Override
public View getView(int position, View convertView, ViewGroup parent) {
return mCards.get(position).getView(convertView, parent);
}
Stabile Karten-IDs implementieren
Wenn eine Karte ausgewählt ist und Nutzern angezeigt wird,
Sie möchten, dass sich Änderungen am zugrunde liegenden Adapter auf die Karte auswirken, die die Nutzer sehen.
in diesem Moment. Wenn ein Nutzer beispielsweise eine ausgewählte Karte
wird links neben dieser Karte entfernt, also die Karte,
nach links verschoben werden kann,
CardScrollAdapter
Dem zugrunde liegenden Datensatz werden bei Änderungen standardmäßig IDs neu zugewiesen.
Wenn es logisch erscheint, deinen Karten eindeutige IDs zuzuweisen, kannst du
eine konsistente ID im zugrunde liegenden Datensatz, um das oben genannte Problem zu vermeiden.
Dazu überschreiben Sie
hasStableIds()
und true
zurückgeben. Damit wird dem System mitgeteilt,
CardScrollAdapter
die IDs über alle Änderungen an Datensätzen hinweg beibehalten. Implementieren Sie darüber hinaus
getItemId()
um die entsprechende eindeutige ID für die Karten in Ihrem Adapter zurückzugeben.
Die Standardimplementierung gibt den Positionsindex der Karte im Adapter zurück.
was von Natur aus instabil ist.
Leerer CardScrollAdapter
Wenn Sie einen leeren Datensatz für Adapter haben, wird die Standardansicht angezeigt.
ein schwarzer Bildschirm. Wenn Sie in diesen Fällen eine andere
Ansicht verwenden möchten,
setEmptyView()
nicht verwenden.
Erstellen Sie stattdessen eine einzelne Karte in Ihrem CardScrollAdapter
.
Horizontales Ziehen-Feedback
Viele integrierte Immersion-Funktionen von Glass ermöglichen das Ziehen wenn Sie nach hinten wischen und keine Aktion ausführen. Dieses Feedback sehen Sie z. B., wenn nachdem Sie ein Foto aufgenommen haben.
Wenn das Immersion keine horizontalen Wischgesten für
diese Tugend-Effekt erzeugen, indem Sie Ihre
Layout in einem
CardScrollView
die eine Karte enthält.
Kopieren Sie die folgende Hilfsklasse in Ihr Projekt:
public class TuggableView extends CardScrollView { private final View mContentView; /** * Initializes a TuggableView that uses the specified layout * resource for its user interface. */ public TuggableView(Context context, int layoutResId) { this(context, LayoutInflater.from(context) .inflate(layoutResId, null)); } /** * Initializes a TuggableView that uses the specified view * for its user interface. */ public TuggableView(Context context, View view) { super(context); mContentView = view; setAdapter(new SingleCardAdapter()); activate(); } /** * Overridden to return false so that all motion events still * bubble up to the activity's onGenericMotionEvent() method after * they are handled by the card scroller. This allows the activity * to handle TAP gestures using a GestureDetector instead of the * card scroller's OnItemClickedListener. */ @Override protected boolean dispatchGenericFocusedEvent(MotionEvent event) { super.dispatchGenericFocusedEvent(event); return false; } /** Holds the single "card" inside the card scroll view. */ private class SingleCardAdapter extends CardScrollAdapter { @Override public int getPosition(Object item) { return 0; } @Override public int getCount() { return 1; } @Override public Object getItem(int position) { return mContentView; } @Override public View getView(int position, View recycleView, ViewGroup parent) { return mContentView; } } }
Ändern Sie die Methode
onCreate
in Ihrer Aktivität, um dieCardScrollView
anzuzeigen, die enthält Ihr Layout.@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // was: setContentView(R.layout.main_activity); setContentView(new TuggableView(this, R.layout.main_activity)); }