Dengan Glass, Anda dapat membangun interaksi yang beragam dengan kartu seperti men-scroll dan animasi.
Men-scroll kartu dalam aktivitas
Layar Glass dan touchpad sangat bagus untuk menampilkan kartu yang dapat digeser,
seperti di {i>timeline<i} Glass. Jika membangun aktivitas, Anda dapat membuat
jenis efek yang sama dengan
CardScrollView
.
- Mengimplementasikan
CardScrollAdapter
untuk menyediakan kartu keCardScrollView
. Anda bisa membangun sendiri hierarki tampilan standar atau menggunakanCardBuilder
. - Buat
CardScrollView
yang menggunakan atributCardScrollAdapter
sebagai pemasok kartu. - Setel tampilan konten aktivitas Anda menjadi
CardScrollView
atau menampilkanCardScrollView
dalam sebuah tata letak.
Berikut adalah implementasi sederhana yang men-scroll tiga kartu:
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);
}
}
}
Berinteraksi dengan kartu scroll
Sejak
CardScrollView
memperluas AdapterView
Anda dapat mengimplementasikan pemroses Android standar.
- Memanggil turunan
setOnItemClickListener()
diCardScrollView
Anda. - Mengimplementasikan
onItemClick()
untuk peristiwa ketuk.
Berikut ini adalah kepanjangan dari contoh sebelumnya yang memutar suara ketukan saat Anda mengetuk kartu:
@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);
}
});
}
Menganimasikan kartu scroll
Ada tiga animasi yang tersedia untuk kartu scroll: Navigasi, Penyisipan, dan Penghapusan.
- Mengimplementasikan tindakan penyisipan atau hapus pada kartu pada posisi yang ditentukan dalam kumpulan kartu.
- Telepon
animate()
dan gunakan nilai dari enumCardScrollView.Animation
. Untuk menampilkan animasi yang lebih halus, hapus semua referensi ke
notifyDataSetChanged()
animate()
menangani pembaruan tampilan set data Anda.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); }
Tips performa dan penerapan untuk kartu scroll
Perhatikan implikasi desain dan performa berikut saat membuat scroller kartu.
Siklus proses kartu
Untuk meningkatkan performa, CardScrollView
hanya memuat subset kartu yang
CardScrollAdapter
(umumnya, bisa dilihat oleh pengguna, dan banyak lagi).
Oleh karena itu, kartu dapat berada dalam salah satu dari empat status umum berikut:
- Terpisah - Tampilan scroll kartu tidak memerlukan kartu ini untuk saat ini.
Anda diberi tahu melalui
onDetachedToWindow()
kartu jika kartu sebelumnya terpasang, lalu dilepas. - Terpasang - Tampilan scroll kartu meminta kartu dari adaptor dengan
getView()
, karena kartu hampir "diaktifkan". Anda akan diberi tahu melalui metodeonAttachedToWindow()
kartu saat hal ini terjadi. - Diaktifkan - Kartu terlihat sebagian oleh pengguna, tetapi kartu ter-scroll
tampilan belum "dipilih" kartu untuk ditampilkan kepada pengguna. Tujuan
Metode 'isActivated()'
akan menampilkan
true
dalam kasus ini. - Dipilih - Kartu menggunakan
seluruh layar. Memanggil
getSelectedView()
akan menampilkan kartu yang saat ini dipilih. MetodeisSelected()
menampilkan benar dalam kasus ini.
Jika Anda menganimasikan tampilan kartu atau
melakukan operasi lain yang mahal,
memulai dan menghentikan operasi di
onAttachedToWindow()
dan
onDetachedToWindow()
untuk menghemat resource.
Daur ulang kartu
Jika kartu dilepas dari lampiran, objek tampilan yang terkait dengan kartu dapat didaur ulang dan digunakan oleh kartu yang terpasang. Mendaur ulang tampilan dengan informasi yang diperbarui jauh lebih efisien daripada membuat tampilan baru.
Untuk memanfaatkan daur ulang kartu, terapkan
getItemViewType()
,
getViewTypeCount()
,
dan getView()
metode-metode tersebut
CardScrollAdapter
. Kemudian, Anda menggunakan beberapa metode praktis di CardBuilder
untuk menerapkan daur ulang di CardScrollAdapter
,
seperti dalam contoh berikut:
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);
}
Menerapkan ID kartu stabil
Saat kartu dipilih dan ditampilkan kepada pengguna, Anda mungkin tidak
menginginkan perubahan pada adaptor yang mendasarinya memengaruhi kartu yang dilihat pengguna
pada saat itu. Misalnya, jika pengguna melihat kartu yang dipilih, dan kartu
kartu dihapus di sebelah kiri kartu tersebut, yaitu kartu yang
yang sedang dilihat berpotensi bergeser ke kiri, karena
CardScrollAdapter
menetapkan ulang ID ke set data pokok saat terjadi perubahan, secara default.
Jika menetapkan ID unik kartu secara logis masuk akal, Anda dapat mempertahankan
ID yang konsisten dalam {i>dataset<i} pokok untuk mencegah masalah yang disebutkan di atas.
Untuk melakukannya, ganti
hasStableIds()
dan menampilkan true
. Ini menentukan pada sistem bahwa
CardScrollAdapter
mempertahankan ID yang stabil di seluruh perubahan {i>dataset<i}. Selain itu, implementasikan
getItemId()
untuk mengembalikan ID unik yang sesuai
untuk kartu di adaptor Anda.
Implementasi default mengembalikan indeks posisi kartu di adaptor,
yang secara inheren tidak stabil.
CardScrollAdapter Kosong
Ketika Anda memiliki set data kosong untuk adaptor, tampilan defaultnya adalah
layar hitam. Jika Anda ingin menampilkan tampilan
yang berbeda dalam kasus ini,
jangan gunakan setEmptyView()
.
Sebagai gantinya, buat satu kartu di CardScrollAdapter
Anda.
Respons menarik secara horizontal
Banyak fitur imersif bawaan pada Glass memberikan kemampuan "menarik" masukan saat menggeser mundur dan maju tidak melakukan suatu tindakan. Misalnya, Anda dapat melihat masukan ini saat menggeser setelah mengambil foto.
Jika pengalaman imersif Anda tidak menggunakan gestur geser horizontal untuk melakukan
fungsi khusus aplikasi, berikan efek menarik ini dengan menggabungkan
di dalam
CardScrollView
yang berisi satu kartu.
Salin class helper berikut ke project Anda:
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; } } }
Ubah metode
onCreate
dalam aktivitas Anda untuk menampilkanCardScrollView
yang berisi tata letak Anda.@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // was: setContentView(R.layout.main_activity); setContentView(new TuggableView(this, R.layout.main_activity)); }