Với Glass, bạn có thể tạo nhiều tương tác phong phú với thẻ của mình, chẳng hạn như cuộn và ảnh động.
Cuộn thẻ trong hoạt động
Màn hình Glass và bàn di chuột rất phù hợp để hiển thị các thẻ có thể lướt,
như trong dòng thời gian của Google Glass. Nếu đang tạo một hoạt động, bạn có thể tạo
có cùng loại hiệu ứng với
CardScrollView
tiện ích.
- Triển khai một
CardScrollAdapter
để cung cấp thẻ choCardScrollView
. Bạn có thể tự xây dựng một hệ phân cấp khung hiển thị chuẩn hoặc sử dụngCardBuilder
. - Tạo một
CardScrollView
sử dụngCardScrollAdapter
nhà cung cấp thẻ. - Đặt chế độ xem nội dung của hoạt động thành
CardScrollView
hoặc hiển thịCardScrollView
trong một bố cục.
Dưới đây là cách triển khai đơn giản bằng cách cuộn qua 3 thẻ:
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);
}
}
}
Tương tác với thẻ cuộn
Từ
CardScrollView
mở rộng AdapterView
bạn có thể triển khai trình nghe Android chuẩn.
- Gọi hàm kế thừa
setOnItemClickListener()
trênCardScrollView
của bạn. - Triển khai một
onItemClick()
trình xử lý cho sự kiện nhấn.
Đây là một phần mở rộng của ví dụ trước có chức năng phát âm thanh khi nhấn khi bạn nhấn vào một thẻ:
@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);
}
});
}
Tạo ảnh động cho thẻ cuộn
Có 3 ảnh động có sẵn để cuộn thẻ: Điều hướng, Chèn và Xoá.
- Thực hiện thao tác chèn hoặc xoá đối với thẻ tại vị trí được chỉ định trong bộ thẻ.
- Gọi điện
animate()
và sử dụng một giá trị từ enumCardScrollView.Animation
. Để ảnh động xuất hiện mượt mà hơn, hãy xoá mọi tham chiếu đến
notifyDataSetChanged()
.animate()
xử lý việc cập nhật chế độ xem tập dữ liệu.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); }
Mẹo về hiệu suất và triển khai thẻ cuộn
Hãy lưu ý những ảnh hưởng sau đây về thiết kế và hiệu suất khi tạo trình cuộn thẻ.
Vòng đời của thẻ
Để tăng hiệu suất, CardScrollView
Chỉ tải một nhóm nhỏ thẻ mà
CardScrollAdapter
cung cấp (thường là những tiện ích bổ sung mà người dùng nhìn thấy và một vài tiện ích khác).
Do đó, thẻ có thể ở một trong 4 trạng thái chung sau đây:
- Tách riêng – Chế độ xem cuộn thẻ không cần thẻ này tại thời điểm hiện tại.
Bạn sẽ nhận được thông báo từ
onDetachedToWindow()
của thẻ nếu thẻ đã được đính kèm trước đó và sau đó được tách ra. - Đã đính kèm – Chế độ xem cuộn thẻ yêu cầu thẻ từ bộ chuyển đổi bằng
getView()
, vì thẻ sắp được "kích hoạt". Bạn sẽ nhận được thông báo bằng phương thứconAttachedToWindow()
của thẻ khi điều này xảy ra. - Đã kích hoạt – Người dùng chỉ nhìn thấy một phần thẻ, nhưng thẻ thì cuộn
chưa "chọn" chế độ xem thẻ hiển thị cho người dùng. Chiến lược phát hành đĩa đơn
Phương thức 'isKích hoạt()'
trả về
true
trong trường hợp này. - Đã chọn - Thẻ đang chiếm
toàn bộ màn hình. Nếu gọi
getSelectedView()
, bạn sẽ trả về thẻ hiện được chọn. Phương thứcisSelected()
trả về true trong trường hợp này.
Nếu bạn đang tạo ảnh động cho chế độ xem thẻ hoặc thực hiện các thao tác tốn kém khác,
bắt đầu và dừng hoạt động trong
onAttachedToWindow()
và
onDetachedToWindow()
để tiết kiệm tài nguyên.
Tái chế thẻ
Khi thẻ chuyển từ trạng thái được đính kèm sang trạng thái tách ra, đối tượng chế độ xem sẽ liên kết với Thẻ có thể được tái chế và sử dụng cho thẻ đang được gắn. Việc tái chế các thành phần hiển thị với thông tin cập nhật sẽ hiệu quả hơn nhiều so với tạo chế độ xem mới.
Để tận dụng việc tái chế thẻ, hãy triển khai
getItemViewType()
!
getViewTypeCount()
,
và getView()
của
CardScrollAdapter
. Sau đó, bạn có thể sử dụng một số phương thức tiện lợi trong CardBuilder
để triển khai việc tái chế trong CardScrollAdapter
,
như trong ví dụ sau:
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);
}
Triển khai mã thẻ ổn định
Khi một thẻ được chọn và hiển thị cho người dùng, bạn có thể không
muốn các thay đổi đối với bộ chuyển đổi cơ bản tác động đến thẻ mà người dùng thấy
tại thời điểm đó. Ví dụ: nếu người dùng đang xem một thẻ đã chọn và một thẻ
bị xoá ở bên trái của thẻ đó, là thẻ mà người dùng
đang xem có thể di chuyển sang trái vì
CardScrollAdapter
gán lại mã nhận dạng cho tập dữ liệu cơ bản khi có thay đổi theo mặc định.
Nếu việc chỉ định mã nhận dạng duy nhất cho thẻ của mình là hợp lý, bạn có thể duy trì
một mã nhận dạng nhất quán trong tập dữ liệu cơ bản để ngăn chặn sự cố nêu trên.
Để thực hiện việc này, hãy ghi đè
hasStableIds()
và trả về true
. Điều này chỉ rõ cho hệ thống rằng
CardScrollAdapter
duy trì mã nhận dạng ổn định qua các thay đổi của tập dữ liệu. Ngoài ra, hãy triển khai
getItemId()
để trả về mã nhận dạng duy nhất phù hợp cho các thẻ trong bộ chuyển đổi.
Phương thức triển khai mặc định sẽ trả về chỉ mục vị trí của thẻ trong bộ chuyển đổi,
vốn không ổn định.
CardScrollAdapter trống
Khi bạn có tập dữ liệu trống cho các bộ chuyển đổi, chế độ xem mặc định sẽ hiển thị
màn hình đen. Nếu bạn muốn hiển thị một chế độ xem khác trong những trường hợp này,
không sử dụng setEmptyView()
.
Thay vào đó, hãy tạo một thẻ duy nhất trong CardScrollAdapter
.
Phản hồi về tính năng kéo theo chiều ngang
Nhiều chế độ nhập vai tích hợp trên Glass mang đến khả năng "kéo" khi vuốt ngược lại. thì không thực hiện hành động. Ví dụ: bạn có thể thấy phản hồi này khi vuốt sau khi chụp ảnh.
Nếu bạn không thực hiện được các cử chỉ vuốt ngang để thực hiện,
các hàm dành riêng cho ứng dụng, hãy cung cấp hiệu ứng kéo này bằng cách gói
bố cục bên trong một
CardScrollView
chứa một thẻ.
Sao chép lớp trợ giúp sau đây vào dự án của bạn:
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; } } }
Sửa đổi phương thức
onCreate
trong hoạt động của bạn để hiển thịCardScrollView
chứa bố cục của bạn.@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // was: setContentView(R.layout.main_activity); setContentView(new TuggableView(this, R.layout.main_activity)); }