Scorritore schede

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.

  1. Implementare un modello CardScrollAdapter per fornire schede al CardScrollView. Puoi creare personalmente una gerarchia di visualizzazioni standard oppure utilizzare CardBuilder .
  2. Crea un CardScrollView che utilizza CardScrollAdapter in qualità di fornitore delle carte.
  3. Imposta la visualizzazione dei contenuti dell'attività come CardScrollView o visualizzare CardScrollView: 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.

  1. Richiama l'eredità setOnItemClickListener() su CardScrollView.
  2. 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.

  1. Implementa un'azione di inserimento o eliminazione su una scheda in una posizione specificata nel set di schede.
  2. Chiama animate() e utilizza un valore dell'enumerazione CardScrollView.Animation.
  3. Per visualizzare un'animazione più fluida, rimuovi eventuali riferimenti a notifyDataSetChanged() La animate() 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 metodo onAttachedToWindow() 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 metodo isSelected() 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.

  1. 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;
            }
        }
    }
    
  2. Modifica il metodo onCreate nella tua attività per visualizzare il CardScrollView 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));
    }