Activity 退出时的 RecyclerView 动画

Sin*_*ian 6 animation android android-animation android-recyclerview

我正在制作一个包含 recyclerview 的应用程序。Recyclerview 的项目在活动开始时从底部以动画方式显示(滑入)。单击某个项目时,它会导航到另一个活动。我希望这些项目在退出当前活动之前以动画方式消失(滑出)。就我而言,我希望项目下拉(滑出),然后新的活动开始。有没有办法在退出活动之前滑出物品?

编辑:如下所示:
在此输入图像描述

Mar*_*osP 1

布局动画控制器:

使用LayoutAnimationController中的构建,您可以使用从上到下的自定义动画幻灯片来实现滑出效果,动画顺序是LayoutAnimationController.ORDER_REVERSE从右下子项目视图开始动画。

res/anim/slide_from_top_to_bottom.xml1.)在滑出动画中声明:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="250">

    <translate
        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
        android:fromYDelta="0"
        android:toYDelta="100%p"/>

    <alpha
        android:fromAlpha="1"
        android:toAlpha="0"
        android:interpolator="@android:anim/accelerate_decelerate_interpolator"/>

</set>
Run Code Online (Sandbox Code Playgroud)

2.)使用以下帮助程序通过将以下方法LayoutAnimationController设置为启动上述动画:RecyclerViewsetLayoutAnimation()

private void slideOutRecyclerViewLayoutAnimation(final RecyclerView recyclerView)
{
    Animation animation = AnimationUtils.loadAnimation(this, R.anim.slide_from_top_to_bottom);
    animation.setFillAfter(true); //true if the animation should apply its transformation after it ends
    LayoutAnimationController lac = new LayoutAnimationController(animation);
    lac.setOrder(LayoutAnimationController.ORDER_REVERSE);
    lac.setDelay(0.15f);

    recyclerView.setLayoutAnimation(lac);
    recyclerView.getAdapter().notifyDataSetChanged();
    recyclerView.scheduleLayoutAnimation();

    //go to the next Activity after 1sec
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            //go to the next Activity
        }
    }, 1000);
}
Run Code Online (Sandbox Code Playgroud)

自定义项目动画器:

如果您希望使用不同的滑出顺序对每个子级的动画延迟进行更多自定义,例如 gif 中的内容,您可以使用自定义SimpleItemAnimator并使用public boolean animateRemove(RecyclerView.ViewHolder holder)在 RecyclerView 中的项目被删除时调用的 。当您仅删除一个项目(例如)notifyItemRemoved()或删除一系列项目(例如)时,它会调用notifyItemRangeRemoved()。

1.)创建CustomAnimator如下示例:

public class CustomAnimator extends SimpleItemAnimator {

    private final int columns;
    private final int rows;

    public CustomAnimator(int columns, int itemsCount){
        this.columns = columns;
        this.rows = (int) Math.ceil((double) itemsCount / (double)columns);
    }

    @Override
    public boolean animateRemove(RecyclerView.ViewHolder holder) {

        //to get the item view position set in RecyclerView.Adapter#onBindViewHolder the position to the item view like: itemView.setTag(position);
        int position = (int)holder.itemView.getTag();

        int x = position % columns;
        int y = position / columns;

        int yDiff = rows - y;
        long delay = 0;
        switch (x)
        {
            //column 0
            case 0:
                delay = yDiff * 60L;
                break;
            //column 1
            case 1:
                delay = yDiff * 50L;
                break;
            //column 2
            case 2:
                delay = yDiff * 40L;
                break;
            //column 3
            case 3:
                delay = yDiff * 30L;
                break;
        }

        int height = holder.itemView.getContext().getResources().getDisplayMetrics().heightPixels;
        holder.itemView.setTranslationY(0);
        holder.itemView.setAlpha(1);
        holder.itemView.animate()
                .translationY(height)
                .alpha(0)
                .setInterpolator(new LinearInterpolator())
                .setDuration(500)
                .setStartDelay(delay)
                .setListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        super.onAnimationEnd(animation);
                        dispatchRemoveFinished(holder);
                    }
                })
                .start();
        return false;
    }

    @Override
    public boolean animateAdd(RecyclerView.ViewHolder holder) {
        return false;
    }

    @Override
    public boolean animateMove(RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) {
        return false;
    }

    @Override
    public boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, int fromLeft, int fromTop, int toLeft, int toTop) {
        return false;
    }

    @Override
    public void runPendingAnimations() {

    }

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

    }

    @Override
    public void endAnimations() {

    }

    @Override
    public boolean isRunning() {
        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)

2.) 在您的RecyclerView.Adapter设置中将onBindViewHolder每个项目的位置设置为稍后检索的标签,如下所示CustomAnimator:

itemView.setTag(position);
Run Code Online (Sandbox Code Playgroud)

3.)在RecyclerView初始化期间设置ItemAnimator如下:

//set GridLayoutManager with 4 columns
recyclerView.setLayoutManager(new GridLayoutManager(this, 4));
//prepare some dummy items
List<Item> itemsList = new ArrayList<>();
for(int i =0; i<26; i++) {
    itemsList.add(new Item());
}
//initialize Adapter
itemsAdapter = new MyAdapter(itemsList);
//set recyclerView Adapter
recyclerView.setAdapter(itemsAdapter);
//set recyclerView CustomAnimator
recyclerView.setItemAnimator(new CustomAnimator(4, itemsAdapter.getItems().size()));
Run Code Online (Sandbox Code Playgroud)

4.)最后,当您单击某个项目时,调用以下助手来启动动画:

private void removeAllItems(){

    int itemsCount = itemsAdapter.getItems().size();
    itemsAdapter.getItems().clear();
    recyclerView.getAdapter().notifyItemRangeRemoved(0, itemsCount);

    //go to the next Activity after 1sec
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            //go to the next Activity after 1sec
        }
    }, 1000);
}
Run Code Online (Sandbox Code Playgroud)

结果:

动画3