其他分享
首页 > 其他分享> > 更改和删除的动画不适用于RecyclerView

更改和删除的动画不适用于RecyclerView

作者:互联网

App有时会从服务器获取更新的数据集,并且需要显示更改的动画.我尝试使用RecyclerView和ItemAnimator,但无法正常工作:仅调用ItemAnimator的animateAdd方法,而不调用animateChange和animateRemove.

有什么主意吗?

我使用RecyclerView和数据集更改模拟器制作了简单的应用程序.

package com.tseglevskiy.recycleviewdevmo;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class MainActivity extends Activity {

    RecyclerView rv;

    List<DummyData> data;

    Handler handler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        handler = new Handler();

        rv = (RecyclerView)findViewById(R.id.list);
        rv.setItemAnimator(new MyAnimator());

        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        layoutManager.scrollToPosition(0);
        rv.setLayoutManager(layoutManager);

        data = new ArrayList<>();
        data.add(new DummyData(1, "foo"));
        data.add(new DummyData(2, "bar"));

        MyAdapter adapter = new MyAdapter(copycopy());
        adapter.setHasStableIds(true);
        rv.setAdapter(adapter);

        loop();
    }

    void loop() {
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                getNewDataset();
                loop();
            }
        }, 3000);
    }

    List<DummyData> copycopy() {
        List<DummyData> copy = new ArrayList<>();

        for (DummyData f: data) {
            copy.add(new DummyData(f.id, f.what));
        }

        return copy;
    }

    void getNewDataset() {
        long now = System.currentTimeMillis();
        Log.d("foo", "getNewDataset " + now);

        // sometimes remove first
        if (randInt(1, 10) > 7) {
            data.remove(0);
        }
        // remove random
        if (data.size() > 5) {
            data.remove(randInt(data.size()/2, data.size()-1));
        }
        // add a few
        int dummyId = (int)(now % Integer.MAX_VALUE);
        data.add(new DummyData(dummyId, "A" + randInt(0,1000000)));
        data.add(new DummyData(dummyId + 1, "B" + randInt(0, 1000000)));
        data.set(randInt(data.size()/2, data.size()-1),
                new DummyData(dummyId + 2, "C" + randInt(0, 1000000)));

        MyAdapter adapter = new MyAdapter(copycopy());
        adapter.setHasStableIds(true);

        rv.swapAdapter(adapter, false);
    }

    public static int randInt(int min, int max) {
        Random rand = new Random();
        int randomNum = rand.nextInt((max - min) + 1) + min;
        return randomNum;
    }

    public static class MyAdapter extends RecyclerView.Adapter<MyHolder> {
        private List<DummyData> items;

        public MyAdapter(List<DummyData> items) {
            this.items = items;
        }

        @Override
        public MyHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
            View v = LayoutInflater.from(viewGroup.getContext())
                    .inflate(android.R.layout.simple_expandable_list_item_1, viewGroup, false);
            return new MyHolder(v);

        }

        @Override
        public void onBindViewHolder(MyHolder myHolder, int position) {
            DummyData model = items.get(position);
            myHolder.text1.setText(model.what);
        }

        @Override
        public int getItemCount() {
            return items.size();
        }
    }

    public static class MyHolder extends RecyclerView.ViewHolder {
        TextView text1;

        public MyHolder(View itemView) {
            super(itemView);
            text1 = (TextView)itemView.findViewById(android.R.id.text1);
        }
    }

    public static class DummyData {
        public DummyData(int id, String what) {
            this.id = id;
            this.what = what;
        }

        public int id;
        public String what;

        @Override
        public String toString() {
            return what;
        }
    }

    public static class MyAnimator extends DefaultItemAnimator {
        @Override
        public boolean animateAdd(RecyclerView.ViewHolder holder) {
            Log.d("foo", "animateAdd");
            return super.animateAdd(holder);
        }

        @Override
        public boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, int fromX, int fromY, int toX, int toY) {
            Log.d("foo", "animateChange");
            return super.animateChange(oldHolder, newHolder, fromX, fromY, toX, toY);
        }

        @Override
        public boolean animateMove(RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) {
            Log.d("foo", "animateMove");
            return super.animateMove(holder, fromX, fromY, toX, toY);
        }

        @Override
        public boolean animateRemove(RecyclerView.ViewHolder holder) {
            Log.d("foo", "animateRemove");
            return super.animateRemove(holder);
        }
    }
}

解决方法:

每当使用setHasStableIds(true)时,都需要重写适配器的getItemId(position)方法.

它应该返回一个真正唯一的值,而不是仓位的直接函数.在您的示例中,它应该类似于:

@Override
public long getItemId(int position)
{
    return items.get(position).id;
}

当然,您还需要在数据更新时调用adapter.notifyDataSetChanged()

标签:android-recyclerview,material-design,android-animation,android
来源: https://codeday.me/bug/20191120/2044460.html