根本不需要使用第三方库。 对 Google I/O 2016 和 Heisenberg 就该主题演示的方法进行一点调整,就可以解决问题。
由于notifyDataSetChanged() 重绘了完整的RecyclerView,notifyDataItemChanged() 是一个更好的选择(不是最好的),因为我们有位置和ViewHolder 供我们使用,还有@987654325 @ only 在给定位置重绘特定的ViewHolder。
但问题是ViewHolder在点击时过早消失,即使使用notifyDataItemChanged()也没有消除它的出现。
以下代码不诉诸 notifyDataSetChanged() 或 notifyDataItemChanged(),并在 API 23 上进行了测试,并且在每个 ViewHolder 都有一个 CardView 的 RecyclerView 上使用时就像一个魅力根元素:
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 是一个全局整数,初始化为 -1。
details 是展开时显示,折叠时隐藏的完整视图。
如前所述,ViewHolder 的根元素是 CardView,其中 foreground 和 stateListAnimator 属性的定义与海森堡在此主题上所说的完全一致。
更新: 如果其中一个展开,上述演示将折叠先前展开的项目。要修改此行为并使展开后的项目即使在另一个项目已展开时也保持原样,您需要以下代码。
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);
更新:当展开列表中的最后一项时,由于展开的部分位于屏幕下方,因此可能无法完全显示。要获取屏幕中的完整项目,请使用以下代码。
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);
重要提示:要使上述演示生效,必须在其代码中保留一个 RecyclerView 的实例和它的 LayoutManager(后者是为了灵活性)