Google Glass pozwala na tworzenie zaawansowanych interakcji z kartami, np. z przewijania i animacje.
Przewijanie kart w aktywnościach
Wyświetlacz i touchpad Glass świetnie nadają się do wyświetlania przesuwanych kart,
jak w przypadku osi czasu w Google Glass. Jeśli tworzysz aktywność, możesz
taki sam efekt w przypadku
CardScrollView
widżet.
- Zaimplementuj
CardScrollAdapter
aby zaopatrzyć się w kartyCardScrollView
Standardową hierarchię widoków możesz utworzyć samodzielnie lub za pomocąCardBuilder
zajęcia. - Utwórz
CardScrollView
który wykorzystujeCardScrollAdapter
dostawcy kart. - Ustaw widok treści aktywności na
CardScrollView
lub wyświetlCardScrollView
w układzie.
Oto prosta implementacja, która wyświetla się po 3 kartach:
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);
}
}
}
Interakcja z przewijanymi kartami
Od
CardScrollView
obejmuje AdapterView
możesz zastosować
standardowe detektory na Androida.
- Wywołaj metodę dziedziczone
setOnItemClickListener()
na urządzeniuCardScrollView
. - Zaimplementuj tag
onItemClick()
dla zdarzenia dotknięcia.
Oto rozszerzenie poprzedniego przykładu, w którym słychać dźwięk dotknięcia po dotknięciu karty:
@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);
}
});
}
Animowanie przewijanych kart
W przypadku kart przewijanych dostępne są 3 animacje: Nawigacja, Wstawianie i Usuwanie.
- Zaimplementuj funkcję wstawiania lub usuwania na karcie w określonym miejscu zestawu kart.
- Zadzwoń do nas
animate()
i użyj wartości z wyliczeniaCardScrollView.Animation
. Aby zapewnić płynniejszą animację, usuń wszelkie odniesienia do
notifyDataSetChanged()
animate()
obsługuje aktualizowanie widoku zbioru danych.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); }
Wskazówki dotyczące skuteczności i implementacji przewijanych kart
Pamiętaj o poniższych wpływach na wygląd i wydajność przewijających karty.
Cykl życia karty
Aby zwiększyć skuteczność, CardScrollView
wczytuje tylko podzbiór kart, które są
CardScrollAdapter
udostępnia (zwykle te, które są widoczne dla użytkownika i kilka innych).
Z tego powodu karta może mieć jeden z 4 ogólnych stanów:
- Odłączona – widok przewijania karty nie potrzebuje jej w danej chwili.
Otrzymasz powiadomienie
onDetachedToWindow()
karty jeśli karta została wcześniej podłączona, a następnie odłączona. - Dołączono – widok przewijania karty żąda karty od adaptera z parametrem
getView()
, ponieważ karta jest bliska aktywacji. Gdy tak się stanie, otrzymasz powiadomienie przy użyciu metodyonAttachedToWindow()
karty. - aktywowana – karta jest częściowo widoczna dla użytkownika, ale przewija się;
widok danych nie został „wybrany” kartę wyświetlaną użytkownikowi.
Metoda 'isActivated()'
w tym przypadku zwraca
true
. - Wybrane – karta zajmuje
całego ekranu. Połączenie z numerem
getSelectedView()
zwróci aktualnie wybraną kartę. MetodaisSelected()
zwraca w tym przypadku.
Jeśli animujesz widok karty lub wykonujesz inne kosztowne operacje,
rozpocznij i zatrzymaj operacje w
onAttachedToWindow()
oraz
onDetachedToWindow()
aby oszczędzać zasoby.
Recykling kart
Gdy karta zostaje odłączona, obiekt widoku danych powiązany z że karta może zostać poddana recyklingowi i służy do użycia z dołączoną kartą. Widoki recyklingu ze zaktualizowanymi informacjami są znacznie efektywniejsze niż tworzenie nowych widoków.
Aby wykorzystać możliwości recyklingu kart, zaimplementuj
getItemViewType()
getViewTypeCount()
,
i getView()
CardScrollAdapter
zajęcia. Następnie korzystasz z udogodnień opisanych w artykule CardBuilder
.
na temat wdrożenia recyklingu w: CardScrollAdapter
,
jak w tym przykładzie:
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);
}
Wdrażanie stabilnych identyfikatorów kart
Po wybraniu karty i wyświetlaniu jej użytkownikom możesz nie mieć możliwości
chcesz, aby zmiany na podstawie adaptera wpłynęły na kartę widoczną dla użytkowników
w danym momencie. Jeśli na przykład użytkownik wyświetla wybraną kartę,
jest usuwana z lewej strony karty,
może przesunąć się w lewo, ponieważ
CardScrollAdapter
domyślnie powoduje zmianę identyfikatorów do bazowego zbioru danych po wystąpieniu zmian.
Jeśli przypisanie unikalnych identyfikatorów ma sens, możesz zachować
spójny identyfikator w bazowym zbiorze danych, by zapobiec temu problemowi.
Aby to zrobić, zastąp
hasStableIds()
i zwróć true
. Określa to systemowi, że
CardScrollAdapter
zachowuje stabilne identyfikatory niezależnie od zmian w zbiorze danych. Dodatkowo zaimplementuj
getItemId()
, by zwracały odpowiedni, unikalny identyfikator kart w adapterze.
Domyślna implementacja zwraca indeks pozycji karty w adapterze,
co jest z natury niestabilne.
Pusta karta przewinięcia karty
Jeśli masz pusty zbiór danych adapterów, domyślnie wyświetlany jest widok
pojawi się czarny ekran. Jeśli w takim przypadku chcesz wyświetlić inny widok,
nie używaj setEmptyView()
.
Zamiast tego utwórz jedną kartę w CardScrollAdapter
.
Informacje o przeciąganiu w poziomie
Wiele wbudowanych zagłębień w Google Glass umożliwia „ciągnięcie” po przesunięciu palcem do tyłu nie wykonują żadnej czynności. Na przykład możesz zobaczyć tę informację, gdy przesuń palcem po zrobieniu zdjęcia.
Jeśli urządzenie nie używa gestów przesuwania w poziomie
dla konkretnych aplikacji, zapewnij ten efekt przeciągania przez opakowanie
układ wewnątrz
CardScrollView
który zawiera 1 kartę.
Skopiuj do projektu tę klasę pomocniczą:
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; } } }
Zmodyfikuj metodę
onCreate
w swojej aktywności, aby wyświetlać metodęCardScrollView
, która zawiera układ.@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // was: setContentView(R.layout.main_activity); setContentView(new TuggableView(this, R.layout.main_activity)); }