Android 回收器视图添加项目动画设置器未设置动画

Android 回收器视图添加项目动画设置器未设置动画,android,android-studio,animation,android-recyclerview,android-animation,Android,Android Studio,Animation,Android Recyclerview,Android Animation,我正在尝试使用自定义项目动画制作工具在单击按钮后为项目视图制作动画。单击“添加”按钮后,新项目将出现,但所需的动画不会出现。它只是突然出现。我什么都试过了,请帮忙 viewholder\u add\u anim <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android">

我正在尝试使用自定义项目动画制作工具在单击按钮后为项目视图制作动画。单击“添加”按钮后,新项目将出现,但所需的动画不会出现。它只是突然出现。我什么都试过了,请帮忙

viewholder\u add\u anim

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <scale
        android:duration = "500"
        android:fromXScale="0%"
        android:fromYScale="0%"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toXScale="100%"
        android:toYScale="100%"/>
</set>
主要活动 公共类MainActivity扩展了AppCompatActivity{

    private RecyclerView recyclerViewBooks;
    private BookAdapter bookAdapter;
    private List<Book> mdata;
    private Button addButton;

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

        initViews();
        initmdataBooks();
        setUpBookAdapter();
    }

    private void initViews() {
        addButton = findViewById(R.id.add_btn);
        recyclerViewBooks = findViewById(R.id.recyclerView);
        recyclerViewBooks.setHasFixedSize(true);

        recyclerViewBooks.setItemAnimator(new CustomItemAnimator());

        addButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                addBook();
            }
        });
    }

    private void initmdataBooks() {
        mdata = new ArrayList<>();
        mdata.add(new Book(R.drawable.book1));
        mdata.add(new Book(R.drawable.book2));
        mdata.add(new Book(R.drawable.book3));
        mdata.add(new Book(R.drawable.book2));
        mdata.add(new Book(R.drawable.book4));
        mdata.add(new Book(R.drawable.book5));
        mdata.add(new Book(R.drawable.book1));
        mdata.add(new Book(R.drawable.book1));
        mdata.add(new Book(R.drawable.book5));
    }

    private void setUpBookAdapter() {
        bookAdapter = new BookAdapter(mdata);
        recyclerViewBooks.setAdapter(bookAdapter);
    }

    private void addBook() {
        Book book = new Book(R.drawable.book4);
        mdata.add(1, book);
        bookAdapter.notifyDataSetChanged();
    }
}
private recycleriew recycleriewbooks;
私人图书适配器;
私有列表数据;
私人按钮添加按钮;
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
initmdataBooks();
setUpBookAdapter();
}
私有void initViews(){
addButton=findViewById(R.id.add\u btn);
recyclerViewBooks=findViewById(R.id.recyclerView);
recyclerViewBooks.setHasFixedSize(true);
setItemAnimator(新的CustomItemAnimator());
addButton.setOnClickListener(新视图.OnClickListener(){
@凌驾
公共void onClick(视图){
addBook();
}
});
}
私有void initmdataBooks(){
mdata=newarraylist();
mdata.add(新书(R.drawable.book1));
mdata.add(新书(R.drawable.book2));
mdata.add(新书(R.drawable.book3));
mdata.add(新书(R.drawable.book2));
mdata.add(新书(R.drawable.book4));
mdata.add(新书(R.drawable.book5));
mdata.add(新书(R.drawable.book1));
mdata.add(新书(R.drawable.book1));
mdata.add(新书(R.drawable.book5));
}
私有void setUpBookAdapter(){
bookAdapter=新bookAdapter(mdata);
recyclerViewBooks.setAdapter(bookAdapter);
}
私有无效addBook(){
Book Book=新书(R.drawable.book4);
mdata.add(1,book);
bookAdapter.notifyDataSetChanged();
}
}

您必须正确填写
itemaniator
合同,而不是盲目覆盖
animateAdd

  • 不要调用super.animateAdd(holder)-您只会与默认的淡入动画冲突
  • 您必须跟踪此动画,并调用
    dispatchAddStarting(holder)
    /
    dispatchAddFinished(holder)
    通知超级实现当前动画状态
  • 您必须重写另外几个方法(在下面的代码中),这些方法必须知道动画是否正在运行,并提供取消选项
  • 示例
    DefaultItemAnimator
    已覆盖,以便在新添加的项目上运行放大动画:

    public class AddRecAnimator extends DefaultItemAnimator {
        private final static String TAG = "AddRecAnimator";
    
        // must keep track of all pending/ongoing animations.
        private final ArrayList<AddHolder> pending = new ArrayList<>();
        private final HashMap<RecyclerView.ViewHolder, AddHolder> additions = new HashMap<>();
    
        @Override
        public boolean animateAdd(RecyclerView.ViewHolder holder) {
            pending.add(new AddHolder(holder));
            return true;    // return true to receive call to runPendingAnimations
        }
    
        @Override
        public void runPendingAnimations() {
            for (AddHolder ah : pending) {
                ah.start();
            }
            pending.clear();
            super.runPendingAnimations();
        }
    
        @Override
        public void endAnimation(RecyclerView.ViewHolder item) {
            AddHolder ah = additions.get(item);
            if (ah != null) {
                ah.endAnimation();
            }
            super.endAnimation(item);
        }
    
        @Override
        public void endAnimations() {
            for (AddHolder ah : pending) {
                ah.resetViewHolderState();
                dispatchAddFinished(ah.holder);
            }
            for (AddHolder ah : additions.values()) {
                ah.resetViewHolderState();
                dispatchAddFinished(ah.holder);
            }
            pending.clear();
            additions.clear();
            super.endAnimations();
        }
    
        @Override
        public boolean isRunning() {
            return super.isRunning() &&
                    !pending.isEmpty() &&
                    !additions.isEmpty();
        }
    
        /**
         * This is container for addition animation. It's also end listener for it.
         */
        private final class AddHolder implements Animation.AnimationListener {
            private final RecyclerView.ViewHolder holder;
    
            private AddHolder(RecyclerView.ViewHolder holder) {
                this.holder = holder;
                Animation anim = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f,
                        ScaleAnimation.RELATIVE_TO_SELF, 0.5f,
                        ScaleAnimation.RELATIVE_TO_SELF, 0.5f);
                anim.setDuration(500);
                anim.setAnimationListener(this);
                holder.itemView.setAnimation(anim);
                dispatchAddStarting(holder);
            }
    
            void start() {
                View itemView = holder.itemView;
                Animation a = itemView.getAnimation();
                if (a != null) {
                    a.start();
                    additions.put(holder, this);
                } else {
                    endAnimation(); // invalid state, animation missing
                }
            }
    
            private void resetViewHolderState() {
                // reset state as if no animation was ran
                Animation a = holder.itemView.getAnimation();
                if (a != null) {
                    a.setAnimationListener(null);
                    a.cancel();
                    holder.itemView.clearAnimation();
                }
                holder.itemView.setScaleX(1f);
                holder.itemView.setScaleY(1f);
            }
    
            // called when animation ends or is manually cancelled
            protected void endAnimation(){
                additions.remove(holder);
                resetViewHolderState();
                dispatchAddFinished(holder);
                // if all animations in animator are done dispatch they're finished
                if (!isRunning()) dispatchAnimationsFinished();
            }
    
            @Override
            public void onAnimationStart(Animation animation) {
    
            }
    
            @Override
            public void onAnimationEnd(Animation animation) {
                endAnimation();
            }
    
            @Override
            public void onAnimationRepeat(Animation animation) {
    
            }
        }
    }
    
    公共类AddRecAnimator扩展了DefaultItemAnimator{
    私有最终静态字符串TAG=“AddRecAnimator”;
    //必须跟踪所有挂起/正在进行的动画。
    private final ArrayList pending=新建ArrayList();
    private final HashMap additions=新HashMap();
    @凌驾
    public boolean animateAdd(RecyclerView.ViewHolder){
    待定。添加(新添加持有人(持有人));
    return true;//返回true以接收对runPendingAnimations的调用
    }
    @凌驾
    public void runPendingAnimations(){
    对于(地址持有人ah:待定){
    啊,开始();
    }
    挂起。清除();
    super.runPendingAnimations();
    }
    @凌驾
    public void endAnimation(RecyclerView.ViewHolder项){
    AddHolder ah=添加项。获取(项);
    如果(啊!=null){
    啊.endAnimation();
    }
    super.endAnimation(项目);
    }
    @凌驾
    公共void endAnimations(){
    对于(地址持有人ah:待定){
    啊,resetViewHolderState();
    dispatchAddFinished(ah.持有人);
    }
    for(AddHolder ah:additions.values()){
    啊,resetViewHolderState();
    dispatchAddFinished(ah.持有人);
    }
    挂起。清除();
    添加。清除();
    super.endAnimations();
    }
    @凌驾
    公共布尔值正在运行(){
    返回super.isRunning()&&
    !pending.isEmpty()&&
    !additions.isEmpty();
    }
    /**
    *这是附加动画的容器。它也是附加动画的最终侦听器。
    */
    私有最终类AddHolder实现Animation.AnimationListener{
    私人最终回收视图持有人;
    private AddHolder(RecyclerView.ViewHolder){
    这个.holder=holder;
    动画动画=新缩放动画(0.0f、1.0f、0.0f、1.0f、,
    ScaleAnimation.RELATIVE_TO_SELF,0.5f,
    标度形象。相对于自身,0.5f);
    动画设定持续时间(500);
    anim.setAnimationListener(此);
    holder.itemView.setAnimation(动画);
    dispatchAddStarting(持有人);
    }
    void start(){
    View itemView=holder.itemView;
    动画a=itemView.getAnimation();
    如果(a!=null){
    a、 start();
    添加。放置(支架,本);
    }否则{
    endAnimation();//状态无效,缺少动画
    }
    }
    私有void resetViewHolderState(){
    //重置状态,如同未运行动画一样
    动画a=holder.itemView.getAnimation();
    如果(a!=null){
    a、 setAnimationListener(空);
    a、 取消();
    holder.itemView.clearAnimation();
    }
    支架.项目视图.设置刻度(1f);
    支架.项目视图.设置刻度(1f);
    }
    //动画结束或手动取消时调用
    受保护的void endAnimation(){
    添加。移除(支架);
    重置ViewHolderState();
    dispatchAddFinished(持有人);
    //如果所有动画都在
    
    public class AddRecAnimator extends DefaultItemAnimator {
        private final static String TAG = "AddRecAnimator";
    
        // must keep track of all pending/ongoing animations.
        private final ArrayList<AddHolder> pending = new ArrayList<>();
        private final HashMap<RecyclerView.ViewHolder, AddHolder> additions = new HashMap<>();
    
        @Override
        public boolean animateAdd(RecyclerView.ViewHolder holder) {
            pending.add(new AddHolder(holder));
            return true;    // return true to receive call to runPendingAnimations
        }
    
        @Override
        public void runPendingAnimations() {
            for (AddHolder ah : pending) {
                ah.start();
            }
            pending.clear();
            super.runPendingAnimations();
        }
    
        @Override
        public void endAnimation(RecyclerView.ViewHolder item) {
            AddHolder ah = additions.get(item);
            if (ah != null) {
                ah.endAnimation();
            }
            super.endAnimation(item);
        }
    
        @Override
        public void endAnimations() {
            for (AddHolder ah : pending) {
                ah.resetViewHolderState();
                dispatchAddFinished(ah.holder);
            }
            for (AddHolder ah : additions.values()) {
                ah.resetViewHolderState();
                dispatchAddFinished(ah.holder);
            }
            pending.clear();
            additions.clear();
            super.endAnimations();
        }
    
        @Override
        public boolean isRunning() {
            return super.isRunning() &&
                    !pending.isEmpty() &&
                    !additions.isEmpty();
        }
    
        /**
         * This is container for addition animation. It's also end listener for it.
         */
        private final class AddHolder implements Animation.AnimationListener {
            private final RecyclerView.ViewHolder holder;
    
            private AddHolder(RecyclerView.ViewHolder holder) {
                this.holder = holder;
                Animation anim = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f,
                        ScaleAnimation.RELATIVE_TO_SELF, 0.5f,
                        ScaleAnimation.RELATIVE_TO_SELF, 0.5f);
                anim.setDuration(500);
                anim.setAnimationListener(this);
                holder.itemView.setAnimation(anim);
                dispatchAddStarting(holder);
            }
    
            void start() {
                View itemView = holder.itemView;
                Animation a = itemView.getAnimation();
                if (a != null) {
                    a.start();
                    additions.put(holder, this);
                } else {
                    endAnimation(); // invalid state, animation missing
                }
            }
    
            private void resetViewHolderState() {
                // reset state as if no animation was ran
                Animation a = holder.itemView.getAnimation();
                if (a != null) {
                    a.setAnimationListener(null);
                    a.cancel();
                    holder.itemView.clearAnimation();
                }
                holder.itemView.setScaleX(1f);
                holder.itemView.setScaleY(1f);
            }
    
            // called when animation ends or is manually cancelled
            protected void endAnimation(){
                additions.remove(holder);
                resetViewHolderState();
                dispatchAddFinished(holder);
                // if all animations in animator are done dispatch they're finished
                if (!isRunning()) dispatchAnimationsFinished();
            }
    
            @Override
            public void onAnimationStart(Animation animation) {
    
            }
    
            @Override
            public void onAnimationEnd(Animation animation) {
                endAnimation();
            }
    
            @Override
            public void onAnimationRepeat(Animation animation) {
    
            }
        }
    }