Đơn giản là không cần sử dụng thư viện của bên thứ ba. Một chút tinh chỉnh trong phương pháp được trình bày trong Google I / O 2016 và Heisenberg về chủ đề này, thực hiện thủ thuật này.
Vì notifyDataSetChanged()
vẽ lại hoàn chỉnhRecyclerView
, notifyDataItemChanged()
là một lựa chọn tốt hơn (không phải là tốt nhất) bởi vì chúng tôi có vị trí và ViewHolder
theo ý của chúng tôi, và notifyDataItemChanged()
chỉ vẽ lại cụ thể ViewHolder
tại một vị trí nhất định .
Nhưng vấn đề là sự biến mất sớm của ViewHolder
khi nhấp và sự xuất hiện của nó không bị loại bỏ ngay cả khi notifyDataItemChanged()
được sử dụng.
Đoạn mã sau không dùng đến notifyDataSetChanged()
hoặc notifyDataItemChanged()
và được thử nghiệm trên API 23 và hoạt động như một nét quyến rũ khi được sử dụng trên RecyclerView trong đó mỗi ViewHolder có một CardView
phần tử gốc như:
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final boolean visibility = holder.details.getVisibility()==View.VISIBLE;
if (!visibility)
{
holder.itemView.setActivated(true);
holder.details.setVisibility(View.VISIBLE);
if (prev_expanded!=-1 && prev_expanded!=position)
{
recycler.findViewHolderForLayoutPosition(prev_expanded).itemView.setActivated(false);
recycler.findViewHolderForLayoutPosition(prev_expanded).itemView.findViewById(R.id.cpl_details).setVisibility(View.GONE);
}
prev_expanded = position;
}
else
{
holder.itemView.setActivated(false);
holder.details.setVisibility(View.GONE);
}
TransitionManager.beginDelayedTransition(recycler);
}
});
prev_position
là một số nguyên toàn cầu được khởi tạo thành -1.
details
là chế độ xem hoàn chỉnh được hiển thị khi mở rộng và che giấu khi thu gọn.
Như đã nói, phần tử gốc của ViewHolder
là a CardView
với foreground
và stateListAnimator
các thuộc tính được xác định chính xác như đã nói của Heisenberg về chủ đề này.
CẬP NHẬT: Trình diễn trên sẽ thu gọn mục được mở rộng phổ biến nếu một trong số chúng được mở rộng. Để sửa đổi hành vi này và giữ một mục được mở rộng như ngay cả khi một mục khác được mở rộng, bạn sẽ cần mã sau đây.
if (row.details.getVisibility()!=View.VISIBLE)
{
row.details.setVisibility(View.VISIBLE);
row.root.setActivated(true);
row.details.animate().alpha(1).setStartDelay(500);
}
else
{
row.root.setActivated(false);
row.details.setVisibility(View.GONE);
row.details.setAlpha(0);
}
TransitionManager.beginDelayedTransition(recycler);
CẬP NHẬT: Khi mở rộng các mục cuối cùng trong danh sách, nó có thể không được hiển thị đầy đủ vì phần mở rộng nằm bên dưới màn hình. Để có được mục đầy đủ trong màn hình, sử dụng mã sau đây.
LinearLayoutManager manager = (LinearLayoutManager) recycler.getLayoutManager();
int distance;
View first = recycler.getChildAt(0);
int height = first.getHeight();
int current = recycler.getChildAdapterPosition(first);
int p = Math.abs(position - current);
if (p > 5) distance = (p - (p - 5)) * height;
else distance = p * height;
manager.scrollToPositionWithOffset(position, distance);
QUAN TRỌNG: Để các trình diễn ở trên hoạt động, người ta phải giữ mã của họ một phiên bản của RecyclerView & it LayoutManager (sau này để linh hoạt)