Con Glass puoi creare interazioni avanzate con le tue schede, come lo scorrimento e animazioni.
Scorrimento di schede nelle attività
Il display Glass e il touchpad sono perfetti per mostrare schede scorrevoli,
come nella sequenza temporale di Glass. Se stai creando un'attività, puoi creare
lo stesso tipo di effetto
CardScrollView
widget.
- Implementare un modello
CardScrollAdapter
per fornire schede alCardScrollView
. Puoi creare personalmente una gerarchia di visualizzazioni standard oppure utilizzareCardBuilder
. - Crea un
CardScrollView
che utilizzaCardScrollAdapter
in qualità di fornitore delle carte. - Imposta la visualizzazione dei contenuti dell'attività come
CardScrollView
o visualizzareCardScrollView
: in un layout.
Di seguito è riportata una semplice implementazione che scorre fino a tre schede:
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);
}
}
}
Interazione con le schede scorrevoli
Dal giorno
CardScrollView
estende AdapterView
puoi implementare i listener Android standard.
- Richiama l'eredità
setOnItemClickListener()
suCardScrollView
. - Implementare un modello
onItemClick()
per l'evento tocco.
Ecco un'estensione dell'esempio precedente che riproduce il suono di un tocco quando tocchi una scheda:
@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);
}
});
}
Animazione delle schede a scorrimento
Sono disponibili tre animazioni per le schede a scorrimento: Navigazione, Inserimento ed Eliminazione.
- Implementa un'azione di inserimento o eliminazione su una scheda in una posizione specificata nel set di schede.
- Chiama
animate()
e utilizza un valore dell'enumerazioneCardScrollView.Animation
. Per visualizzare un'animazione più fluida, rimuovi eventuali riferimenti a
notifyDataSetChanged()
Laanimate()
gestisce l'aggiornamento della vista del set di dati.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); }
Suggerimenti sulle prestazioni e sull'implementazione per lo scorrimento delle schede
Durante la creazione, tieni presente le seguenti implicazioni a livello di design e prestazioni scorrimento delle schede.
Ciclo di vita della scheda
Per aumentare il rendimento, una CardScrollView
carica solo un sottoinsieme di schede
CardScrollAdapter
(in genere, quelli visibili all'utente e alcuni altri).
Per questo motivo, una carta può trovarsi in uno dei seguenti quattro stati generali:
- Scollegata: al momento la visualizzazione a scorrimento delle schede non richiede questa scheda.
Ricevi una notifica dall'icona
onDetachedToWindow()
della carta se una scheda è stata allegata e poi scollegata in precedenza. - Allegata: la visualizzazione scorrimento delle schede richiede la scheda dall'adattatore con
getView()
, perché la carta sta per essere "attivata". In questo caso, riceverai una notifica dal metodoonAttachedToWindow()
della carta. - Attivata: la scheda è parzialmente visibile all'utente, ma la scheda scorre
la visualizzazione non è "selezionata" la scheda da mostrare all'utente. La
Metodo 'isActivated()'
restituisce
true
in questo caso. - Selezionata. La carta sta occupando la
schermo intero. Se chiami
getSelectedView()
, viene restituita la carta attualmente selezionata. Il metodoisSelected()
restituisce "true" in questo caso.
Se stai animando la visualizzazione della scheda o stai eseguendo altre operazioni costose,
avviare e arrestare le operazioni
onAttachedToWindow()
e
onDetachedToWindow()
per risparmiare risorse.
Riciclo di carte
Quando una scheda passa da essere collegata a scollegata, l'oggetto view associato a la carta può essere riciclata e utilizzata utilizzando una carta che viene attaccata. Riciclare le visualizzazioni con informazioni aggiornate è molto più efficiente creando nuove viste.
Per usufruire del riciclo delle carte, implementa la
getItemViewType()
,
getViewTypeCount()
,
e getView()
i metodi di
CardScrollAdapter
. Puoi quindi utilizzare alcuni dei metodi disponibili in CardBuilder
per implementare il riciclo nel tuo CardScrollAdapter
,
come nell'esempio seguente:
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);
}
Implementazione di ID carta stabili
Quando una scheda è selezionata e mostrata agli utenti, potresti non
Vuoi che le modifiche all'adattatore sottostante influiscano sulla scheda visualizzata dagli utenti
in quel momento. Ad esempio, se un utente sta visualizzando una scheda selezionata e una
viene rimossa a sinistra di quella carta, la carta a cui l'utente
visualizzato può spostarsi potenzialmente a sinistra, in quanto
CardScrollAdapter
Per impostazione predefinita, riassegna gli ID al set di dati sottostante quando si verificano modifiche.
Se logicamente ha senso assegnare ID univoci alle schede, puoi mantenere
un ID coerente nel set di dati sottostante per evitare il problema sopra menzionato.
Per farlo, sostituisci
hasStableIds()
e restituisci true
. Questo specifica al sistema
CardScrollAdapter
e mantiene gli ID stabili in tutte le modifiche ai set di dati. Inoltre, implementa
getItemId()
per restituire l'ID univoco appropriato per le carte nell'adattatore.
L'implementazione predefinita restituisce l'indice di posizione della scheda nell'adattatore,
che è intrinsecamente instabile.
CardscrollAdapter vuoto
Se un set di dati è vuoto per gli adattatori, la visualizzazione predefinita mostra
una schermata nera. Se vuoi avere una visualizzazione diversa in questi casi,
non utilizzare setEmptyView()
.
Crea invece un'unica carta nel tuo CardScrollAdapter
.
Feedback tiro a volo orizzontale
Molte immersioni integrate in Glass permettono di "tollare" feedback quando scorri all'indietro non eseguono alcuna azione. Ad esempio, puoi vedere questo feedback quando scorrere dopo aver scattato una foto.
Se l'immersione non prevede gesti di scorrimento orizzontale
per applicazioni specifiche, fornisci questo effetto stratagendo eseguendo il wrapping
all'interno di un
CardScrollView
che contiene una scheda.
Copia la seguente classe helper nel tuo progetto:
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; } } }
Modifica il metodo
onCreate
nella tua attività per visualizzare ilCardScrollView
che contiene il tuo layout.@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // was: setContentView(R.layout.main_activity); setContentView(new TuggableView(this, R.layout.main_activity)); }