当前位置: 首页 > 知识库问答 >
问题:

回收站查看项目触摸助手轻扫删除动画

尹小云
2023-03-14

我有一个滑动删除,它绘制了一个背景(很像收件箱应用程序),由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首先删除我漂亮的绿色背景,然后将两个相邻的项目推到一起。

我希望它在这样做的时候保持背景(就像收件箱应用程序一样)。有什么办法吗?

共有3个答案

盛超
2023-03-14

只需更新适配器位置,然后删除动画

@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
     int position = viewHolder.getAdapterPosition();

     if (direction == ItemTouchHelper.LEFT) {
          remove(position);
     } else {
          mAdapter.notifyItemChanged(position);
     }
}
陆翰学
2023-03-14

我通过使用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;
}

解决了这个问题。

张英范
2023-03-14

我也有同样的问题,我不想仅仅为了解决它而引入一个新的库。< 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);