简体   繁体   English

Android RecyclerView 移除项目动画bug

[英]Android RecyclerView remove item animation bug

I'm trying to implement a ToDo list that contains a list and some other views below it on the activity page.我正在尝试实现一个 ToDo 列表,其中包含一个列表和活动页面上它下面的一些其他视图。

I am using a LinearLayout for the entire page and a RecyclerView for the list, alongside other views below the RecyclerView ( ImageView , Buttons ...etc.)我对整个页面使用LinearLayout ,对列表使用RecyclerView ,以及RecyclerView下方的其他视图( ImageViewButtons ...等)

Here's my final view hierarchy:这是我的最终视图层次结构:

<LinearLayout>
    <TextView />
    <RecyclerView />
    <Button />
    <EditText />
    <ImageView />
</LinearLayout>

I have implemented the RecyclerView where I can add and remove items.我已经实现了RecyclerView ,我可以在其中添加和删除项目。 I am using a LinearLayoutManager without specifying an ItemAnimator so DefaultItemAnimator is used.我正在使用LinearLayoutManager而不指定ItemAnimator因此使用DefaultItemAnimator

Adding items to the list works as expected.向列表中添加项目按预期工作。 My problem is that the page doesn't animate well when I remove an item from the RecyclerView (by removing it from the dataset first then using RecyclerViewAdapter.notifyItemRemoved ).我的问题是,当我RecyclerView删除项目时,页面动画效果不佳(首先从数据集中删除它,然后使用RecyclerViewAdapter.notifyItemRemoved )。

What happens is that the entire page snaps first to adapt to the new RecyclerView height, and then the RecyclerView item remove animation completes, which makes the behavior of the page look weird since all the views below the RecyclerView snap up while the deleted item fades out but hasn't lost its height yet, then the remaining RecyclerView items (below the deleted item) scroll up, looking like they're sliding up from under a wall.发生的情况是整个页面先对齐以适应新的RecyclerView高度,然后RecyclerView item remove 动画完成,这使得页面的行为看起来很奇怪,因为RecyclerView下面的所有视图都对齐了,而删除的 item 淡出但还没有失去它的高度,然后剩余的RecyclerView项目(在删除的项目下方)向上滚动,看起来它们是从墙下向上滑动的。

I tried to look for solutions on the web and couldn't find anything to solve my problem.我试图在网上寻找解决方案,但找不到任何可以解决我的问题的方法。

I have found this unanswered question describing the same problem.我发现这个未回答的问题描述了同样的问题。 Please refer to it in case my explanation wasn't clear enough.如果我的解释不够清楚,请参考它。

Anyone encountering the same issue?有人遇到同样的问题吗? Any suggestions?有什么建议?

Thanks.谢谢。

I had the same problem.我有同样的问题。 In my situation just this line helped:在我的情况下,这条线有帮助:

recyclerView.setHasFixedSize(true);

Try this one and check if it is working as your expectation:试试这个并检查它是否按您的期望工作:

recyclerView.setHasFixedSize(true);
recyclerView.setItemAnimator(new MyAnim());


public static class MyAnim extends RecyclerView.ItemAnimator {
        @Override
        public boolean animateDisappearance(@NonNull RecyclerView.ViewHolder viewHolder, @NonNull ItemHolderInfo preLayoutInfo, @Nullable ItemHolderInfo postLayoutInfo) {
            return false;
        }

        @Override
        public boolean animateAppearance(@NonNull RecyclerView.ViewHolder viewHolder, @Nullable ItemHolderInfo preLayoutInfo, @NonNull ItemHolderInfo postLayoutInfo) {
            return false;
        }

        @Override
        public boolean animatePersistence(@NonNull RecyclerView.ViewHolder viewHolder, @NonNull ItemHolderInfo preLayoutInfo, @NonNull ItemHolderInfo postLayoutInfo) {
            return false;
        }

        @Override
        public boolean animateChange(@NonNull RecyclerView.ViewHolder oldHolder, @NonNull RecyclerView.ViewHolder newHolder, @NonNull ItemHolderInfo preLayoutInfo, @NonNull ItemHolderInfo postLayoutInfo) {
            final float prevAlpha = ViewCompat.getAlpha(oldHolder.itemView);

            ViewCompat.setAlpha(oldHolder.itemView, prevAlpha);

            ViewCompat.setAlpha(newHolder.itemView, 0);

            return true;
        }

        @Override
        public void runPendingAnimations() {

        }

        @Override
        public void endAnimation(RecyclerView.ViewHolder item) {

        }

        @Override
        public void endAnimations() {

        }

        @Override
        public boolean isRunning() {
            return false;
        }
    }

Create subclass of RecyclerView and override onTouchEvent method like this:创建RecyclerView子类并像这样覆盖onTouchEvent方法:

@Override
public boolean onTouchEvent(MotionEvent e) {
    if (findChildViewUnder(e.getX(), e.getY()) == null) {
        return false;
    }
    return super.onTouchEvent(e);
}

Also, don't use wrap_content as RecyclerView height/width depending on your orientation.另外,不要根据您的方向使用wrap_content作为RecyclerView高度/宽度。

This way RecyclerView has fixed size and does not cut off items while removing them.这样RecyclerView具有固定的大小,并且在删除它们时不会切断项目。 Manipulation of onTouchEvent method assures that part of RecyclerView without items does not consumes click events and sends them to parent view of RecyclerView .onTouchEvent方法的操作确保RecyclerView没有项目的部分不会消耗点击事件并将它们发送到RecyclerView父视图。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM