我有一个滑动删除,它绘制了一个背景(很像收件箱应用程序),由ItemTouchHelper实现,方法是覆盖onChilDraw方法并在提供的画布上绘制一个矩形:
ItemTouchHelper mIth = new ItemTouchHelper(
new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.RIGHT) {
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
remove(viewHolder.getAdapterPosition());
}
public boolean onMove(RecyclerView recyclerview, RecyclerView.ViewHolder v, RecyclerView.ViewHolder target) {
return false;
}
@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
View itemView = viewHolder.itemView;
Drawable d = ContextCompat.getDrawable(context, R.drawable.bg_swipe_item_right);
d.setBounds(itemView.getLeft(), itemView.getTop(), (int) dX, itemView.getBottom());
d.draw(c);
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
});
上面调用的删除方法位于适配器中:
public void remove(int position) {
items.remove(position);
notifyItemRemoved(position);
}
背景画得很好,但是当调用notefyItemRemved时(根据调试器先生的说法),RecyclerView首先删除我漂亮的绿色背景,然后将两个相邻的项目推到一起。
我希望它在这样做的时候保持背景(就像收件箱应用程序一样)。有什么办法吗?
只需更新适配器位置,然后删除动画
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
int position = viewHolder.getAdapterPosition();
if (direction == ItemTouchHelper.LEFT) {
remove(position);
} else {
mAdapter.notifyItemChanged(position);
}
}
我通过使用Wasabeefs的recyclerview-animators库设法让它工作起来。
“我的视图”现在扩展了库提供的动画查看器:
class MyViewHolder extends AnimateViewHolder {
TextView textView;
public MyViewHolder(View itemView) {
super(itemView);
this.textView = (TextView) itemView.findViewById(R.id.item_name);
}
@Override
public void animateAddImpl(ViewPropertyAnimatorListener listener) {
ViewCompat.animate(itemView)
.translationY(0)
.alpha(1)
.setDuration(300)
.setListener(listener)
.start();
}
@Override
public void preAnimateAddImpl() {
ViewCompat.setTranslationY(itemView, -itemView.getHeight() * 0.3f);
ViewCompat.setAlpha(itemView, 0);
}
@Override
public void animateRemoveImpl(ViewPropertyAnimatorListener listener) {
ViewCompat.animate(itemView)
.translationY(0)
.alpha(1)
.setDuration(300)
.setListener(listener)
.start();
}
}
被重写的函数实现与github上回收站视图动画师自述文件中的内容相同。
似乎也有必要将ItemAnimator更改为自定义的,并将removeDuration设置为0(或另一个较低的值——这是为了防止一些闪烁):
recyclerView.setItemAnimator(new SlideInLeftAnimator());
recyclerView.getItemAnimator().setRemoveDuration(0);
这不会导致任何问题,因为使用的正常(非轻扫)删除动画是 AnimateViewHolder 中的动画。
所有其他代码都与问题中的代码相同。我还没有时间弄清楚它的内部运作,但如果有人想这样做,请随时更新这个答案。
更新:设置回收器View.getItemAnimator().setRemoveDuration(0);
实际上破坏了轻扫的“重新绑定”动画。幸运的是,删除该行并在动画RemoveImpl中设置更长的持续时间(500适用于我)也可以解决闪烁问题。
更新2:原来ItemTouchHelper。SimpleCallback使用ItemAnimator的动画持续时间,这就是上面的setRemoveDuration(0)中断滑动动画的原因。只需将其方法getAnimationDuration重写为:
@Override
public long getAnimationDuration(RecyclerView recyclerView, int animationType, float animateDx, float animateDy) {
return animationType == ItemTouchHelper.ANIMATION_TYPE_DRAG ? DEFAULT_DRAG_ANIMATION_DURATION
: DEFAULT_SWIPE_ANIMATION_DURATION;
}
解决了这个问题。
我也有同样的问题,我不想仅仅为了解决它而引入一个新的库。< code > recycle view 并没有删除你漂亮的绿色背景,它只是重新绘制了它自己,而你的< code > itemctouchhelper 不再绘制了。实际上它是在绘制,但是< code>dX是0,并且是从< code>itemView.getLeft()(为0)绘制到< code>dX(为0),所以您什么也看不到。它画得太多了,但我等会儿再来看。
无论如何,当行被激活时回到背景:我不能在< code > itemctouchhelper 和< code>onChildDraw中这样做。最后,我不得不添加另一个项目装饰器来完成它。它是这样的:
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
if (parent.getItemAnimator().isRunning()) {
// find first child with translationY > 0
// draw from it's top to translationY whatever you want
int top = 0;
int bottom = 0;
int childCount = parent.getLayoutManager().getChildCount();
for (int i = 0; i < childCount; i++) {
View child = parent.getLayoutManager().getChildAt(i);
if (child.getTranslationY() != 0) {
top = child.getTop();
bottom = top + (int) child.getTranslationY();
break;
}
}
// draw whatever you want
super.onDraw(c, parent, state);
}
}
这段代码只考虑向上移动的行,但也应该考虑向下移动的行。如果您滑动删除最后一行,上面的行将向下移动到该空间。
当我说你的项目触控助手画得太多时,我的意思是:看起来项目触控助手
保留了已删除行的视图,
以防需要恢复它们。除了滑动VH之外,它还呼吁儿童绘制
这些VH。不确定此行为对内存管理的影响,但我需要在 onChildDraw
的开头进行额外的检查,以避免绘制“fantom”行。
if (viewHolder.getAdapterPosition() == -1) {
return;
}
在你的情况下,它是从 left=0 到 right=0 绘制的,所以你看不到任何东西,但开销就在那里。如果您开始看到以前滑动的行绘制其背景,这就是原因。
编辑:我尝试过这个,看这篇博文和这个github回购。
我正在从事一个自由职业者的android项目。我有一个问题,就是根据项目设计需要改变RecyclerView项目之间的利润率。我想显示屏幕上最后一个可见项目的一半,这样用户就可以猜测水平滚动。我尝试创建一个自定义的RecyclerView.itemEdition。当屏幕第一次打开时,一切正常,但当我开始在这个回收视图上水平滚动时,项目之间的间隔增加了,有时甚至减少了。我如何用一般方法解决这个问题。
在这里我有项目的列表在回收器视图这是取自Firebase.所以我试图改变其背景颜色当用户点击它.但是当我点击项目1然后项目4背景颜色也得到改变.如果点击项目2然后项目8颜色也.它给不恰当的结果。 视图持有者类
我很乐意为我的开源库启用触摸反馈。 我创建了一个和一个。包含具有不同操作的不同区域。现在,如果用户点击卡上的任何地方,我很想触发连锁反应,但我无法实现这种行为。 这是我的列表,你也可以在GitHub上找到:https://github.com/mikepenz/AboutLibraries/blob/master/library/src/main/res/layout/listitem_opens
所以,这就是我的问题。我的recyclerview项目在底部有一个视图,我最初将其设置为消失。现在,当它们被点击时,我想让它们再次可见。所以在onClick方法中,我将视图设置为Visible。一切正常,但是当我向下滚动和向上滚动时,视图又隐藏了。我想这和取景模式有关。我想保持现状,即开放。我该怎么做?谢了。 视图支架: 点击: 编辑:上传的代码。此外,我尝试在onClick中更新Item的布尔值
我想展开/折叠我的recyclerView项目,以显示更多信息。我想实现与SlideExpandableListView相同的效果。 基本上,在我的viewHolder中,我有一个不可见的视图,我想做一个平滑的展开/折叠动画,而不是将可见性设置为仅可见/消失。我一次只需要扩展一个项目,如果有一些提升来显示该项目已被选中,那就太酷了。 这与新的Android最近通话历史记录列表的效果相同。“回调”和
我是显示隐藏的视图后,刷了两个按钮“删除”和“取消”。在我的xml项目行中,我有2个内部关系 此处ItemTouchHelper实现 这里是观众 如果单击be more correct buttons但未在swipe后首次尝试更新,则在swipe模式下单击项目,并且日志显示前3次单击是swipe方向 在swipe log.d(“swipe”,“direction=”+direction);