需求:在其他item拖拽到当前文件夹item时,我的白色边框要隐藏,移除后白色边框显示
解决:通过字段hideBorder,来标记是否隐藏白色边框,更改hideBorder字段,再调用notifyItemChanged通知item更新UI
现象:使用notifyItemChanged更新item,item会出现闪烁的情况
如图
解决方法:
1. 使用 ItemAnimator
来避免闪烁
如果第一种方法没有完全解决问题,可以自定义 RecyclerView
的 ItemAnimator
。禁用默认的动画可以减少闪烁。
recyclerView.setItemAnimator(null);
结果说明:虽然解决了闪烁问题,但是因为我的item拖拽时会有放大和缩小的动画,使用这种方式,会导致我的动画效果出现问题。
为了在避免闪烁的同时保留移动时的动画效果,可以自定义 ItemAnimator
,只禁用更改动画而保留其他动画。下面是一个示例:
2. 自定义 ItemAnimator
创建一个自定义的 ItemAnimator
类,继承自 DefaultItemAnimator
并覆盖 animateChange
方法,以禁用更改动画。
public class CustomItemAnimator extends DefaultItemAnimator {
@Override
public boolean animateChange(@NonNull RecyclerView.ViewHolder oldHolder,
@NonNull RecyclerView.ViewHolder newHolder,
int fromLeft, int fromTop, int toLeft, int toTop) {
// Return false to indicate that no change animation should be performed
return false;
}
@Override
public boolean animateAdd(RecyclerView.ViewHolder holder) {
return super.animateAdd(holder);
}
@Override
public boolean animateRemove(RecyclerView.ViewHolder holder) {
return super.animateRemove(holder);
}
@Override
public boolean animateMove(RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) {
return super.animateMove(holder, fromX, fromY, toX, toY);
}
@Override
public void runPendingAnimations() {
super.runPendingAnimations();
}
@Override
public void endAnimation(RecyclerView.ViewHolder item) {
super.endAnimation(item);
}
@Override
public void endAnimations() {
super.endAnimations();
}
@Override
public boolean isRunning() {
return super.isRunning();
}
}
设置自定义 ItemAnimator
在你的 RecyclerView
中使用这个自定义的 ItemAnimator
。
recyclerView.setItemAnimator(new CustomItemAnimator());
结果说明:因为我的需求中,item有拖拽后置空的效果。这种方式会导致我的置空效果出现问题
最终选择方式
在使用 notifyItemChanged
时,RecyclerView 的 item 会闪烁,这是因为默认情况下,RecyclerView 会重新绑定整个 item 导致 UI 发生刷新。为了解决这个问题,可以采取以下方法:
1. 使用 notifyItemChanged(position, payload)
使用带有 payload 参数的 notifyItemChanged
方法。这样可以让 RecyclerView
只更新特定的部分,而不会重新绑定整个 item。
在你的 Adapter
中,重写 onBindViewHolder
方法,并处理 payload 参数。
@Override
public void onBindViewHolder(ViewHolder holder, int position, List<Object> payloads) {
if (payloads.isEmpty()) {
super.onBindViewHolder(holder, position, payloads);
} else {
// Handle the partial update here
for (Object payload : payloads) {
if (payload.equals("border")) {
// Update the border visibility without refreshing the whole item
holder.updateBorderVisibility();
}
}
}
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
// Bind the entire item if payload is empty
holder.bind(dataSet.get(position));
}
当你只需要更新边框显示和隐藏时,调用 notifyItemChanged
并传递一个自定义的 payload,比如 "border"
。
adapter.notifyItemChanged(position, "border");