Android RecyclerView删除项目动画错误

时间:2017-03-08 06:58:07

标签: android android-layout animation android-recyclerview android-animation

我正在尝试在活动页面上实现一个包含列表和其下方的一些其他视图的ToDo列表。

我使用LinearLayout表示整个页面,RecyclerView表示该列表,以及RecyclerViewImageViewButtons下面的其他观点。 ..等。)

这是我的最终视图层次结构:

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

我已经实现了RecyclerView,我可以在其中添加和删除项目。 我使用LinearLayoutManager而未指定ItemAnimator,因此使用了DefaultItemAnimator

向列表中添加项目按预期工作。我的问题是,当RecyclerView 删除项目时,页面效果不佳(首先将其从数据集中移除然后使用{{1} }})。

发生的事情是整个页面首先捕捉以适应新的RecyclerViewAdapter.notifyItemRemoved高度,然后RecyclerView项目移除动画完成,这使得页面的行为看起来很奇怪,因为所有的视图如果已删除的项目淡出,但尚未丢失其高度,则RecyclerView以下的快照会向下,然后剩余的RecyclerView项目(在已删除的项目下方)向上滚动,看起来它们正在向上滑动在墙下。

我试图在网上寻找解决方案,找不到任何可以解决我问题的方法。

我发现this unanswered question描述了同样的问题。如果我的解释不够清楚,请参考它。

遇到同样问题的人?有什么建议吗?

感谢。

3 个答案:

答案 0 :(得分:1)

试试这个并检查它是否符合您的期望:

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;
        }
    }

答案 1 :(得分:1)

我遇到了同样的问题。在我的情况下,这一行有助于:

recyclerView.setHasFixedSize(true);

答案 2 :(得分:1)

创建 RecyclerView 的子类并像这样覆盖 onTouchEvent 方法:

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

此外,根据您的方向,不要将 wrap_content 用作 RecyclerView 的高度/宽度。

这种方式 RecyclerView 具有固定大小,并且在移除项目时不会切断项目。 onTouchEvent 方法的操作确保 RecyclerView 没有项目的部分不会消耗点击事件并将它们发送到 RecyclerView 的父视图。