DefaultItemAnimator.java revision abea494886a17e7a51080ab5e9c2ca041c533353
1d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase/*
2d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * Copyright (C) 2014 The Android Open Source Project
3d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase *
4d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * Licensed under the Apache License, Version 2.0 (the "License");
5d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * you may not use this file except in compliance with the License.
6d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * You may obtain a copy of the License at
7d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase *
8d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase *      http://www.apache.org/licenses/LICENSE-2.0
9d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase *
10d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * Unless required by applicable law or agreed to in writing, software
11d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * distributed under the License is distributed on an "AS IS" BASIS,
12d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * See the License for the specific language governing permissions and
14d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * limitations under the License.
15d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase */
16d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haasepackage android.support.v7.widget;
17d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
18abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyarimport android.support.annotation.NonNull;
19d03a495b04ee74c1cb493cee0d5998b895b1c79bVladislav Kaznacheevimport android.support.v4.animation.AnimatorCompatHelper;
20d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haaseimport android.support.v4.view.ViewCompat;
21a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyarimport android.support.v4.view.ViewPropertyAnimatorCompat;
22d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haaseimport android.support.v4.view.ViewPropertyAnimatorListener;
23d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haaseimport android.support.v7.widget.RecyclerView.ViewHolder;
24d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haaseimport android.view.View;
25d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
26d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haaseimport java.util.ArrayList;
27a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyarimport java.util.List;
28d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
29d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase/**
30d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * This implementation of {@link RecyclerView.ItemAnimator} provides basic
31d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * animations on remove, add, and move events that happen to the items in
32d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * a RecyclerView. RecyclerView uses a DefaultItemAnimator by default.
33d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase *
34d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * @see RecyclerView#setItemAnimator(RecyclerView.ItemAnimator)
35d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase */
36121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyarpublic class DefaultItemAnimator extends SimpleItemAnimator {
37a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar    private static final boolean DEBUG = false;
38d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
39e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar    private ArrayList<ViewHolder> mPendingRemovals = new ArrayList<>();
40e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar    private ArrayList<ViewHolder> mPendingAdditions = new ArrayList<>();
41e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar    private ArrayList<MoveInfo> mPendingMoves = new ArrayList<>();
42e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar    private ArrayList<ChangeInfo> mPendingChanges = new ArrayList<>();
43d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
44e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar    private ArrayList<ArrayList<ViewHolder>> mAdditionsList = new ArrayList<>();
45e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar    private ArrayList<ArrayList<MoveInfo>> mMovesList = new ArrayList<>();
46e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar    private ArrayList<ArrayList<ChangeInfo>> mChangesList = new ArrayList<>();
47d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
48e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar    private ArrayList<ViewHolder> mAddAnimations = new ArrayList<>();
49e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar    private ArrayList<ViewHolder> mMoveAnimations = new ArrayList<>();
50e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar    private ArrayList<ViewHolder> mRemoveAnimations = new ArrayList<>();
51e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar    private ArrayList<ViewHolder> mChangeAnimations = new ArrayList<>();
52d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
53d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    private static class MoveInfo {
54d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        public ViewHolder holder;
55d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        public int fromX, fromY, toX, toY;
56d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
57d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        private MoveInfo(ViewHolder holder, int fromX, int fromY, int toX, int toY) {
58d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            this.holder = holder;
59d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            this.fromX = fromX;
60d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            this.fromY = fromY;
61d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            this.toX = toX;
62d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            this.toY = toY;
63d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
64d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
65d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
66235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase    private static class ChangeInfo {
67235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase        public ViewHolder oldHolder, newHolder;
68a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        public int fromX, fromY, toX, toY;
69235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase        private ChangeInfo(ViewHolder oldHolder, ViewHolder newHolder) {
70235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase            this.oldHolder = oldHolder;
71235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase            this.newHolder = newHolder;
72235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase        }
73a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar
74a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        private ChangeInfo(ViewHolder oldHolder, ViewHolder newHolder,
75a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar                int fromX, int fromY, int toX, int toY) {
76a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar            this(oldHolder, newHolder);
77a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar            this.fromX = fromX;
78a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar            this.fromY = fromY;
79a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar            this.toX = toX;
80a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar            this.toY = toY;
81a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        }
82a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar
83a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        @Override
84a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        public String toString() {
85a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar            return "ChangeInfo{" +
86a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar                    "oldHolder=" + oldHolder +
87a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar                    ", newHolder=" + newHolder +
88a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar                    ", fromX=" + fromX +
89a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar                    ", fromY=" + fromY +
90a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar                    ", toX=" + toX +
91a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar                    ", toY=" + toY +
92a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar                    '}';
93a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        }
94235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase    }
95235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase
96d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    @Override
97d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public void runPendingAnimations() {
98d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        boolean removalsPending = !mPendingRemovals.isEmpty();
99d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        boolean movesPending = !mPendingMoves.isEmpty();
100235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase        boolean changesPending = !mPendingChanges.isEmpty();
101d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        boolean additionsPending = !mPendingAdditions.isEmpty();
102a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        if (!removalsPending && !movesPending && !additionsPending && !changesPending) {
103d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            // nothing to animate
104d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            return;
105d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
106d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        // First, remove stuff
107d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        for (ViewHolder holder : mPendingRemovals) {
108d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            animateRemoveImpl(holder);
109d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
110d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        mPendingRemovals.clear();
111d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        // Next, move stuff
112d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if (movesPending) {
113e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar            final ArrayList<MoveInfo> moves = new ArrayList<>();
1140e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase            moves.addAll(mPendingMoves);
1150e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase            mMovesList.add(moves);
116d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            mPendingMoves.clear();
117d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            Runnable mover = new Runnable() {
118d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                @Override
119d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                public void run() {
1200e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                    for (MoveInfo moveInfo : moves) {
121d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                        animateMoveImpl(moveInfo.holder, moveInfo.fromX, moveInfo.fromY,
122d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                                moveInfo.toX, moveInfo.toY);
123d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                    }
1240e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                    moves.clear();
1250e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                    mMovesList.remove(moves);
126d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                }
127d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            };
128d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            if (removalsPending) {
1290e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                View view = moves.get(0).holder.itemView;
130d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                ViewCompat.postOnAnimationDelayed(view, mover, getRemoveDuration());
131d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            } else {
132d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                mover.run();
133d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            }
134d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
135235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase        // Next, change stuff, to run in parallel with move animations
136235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase        if (changesPending) {
137e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar            final ArrayList<ChangeInfo> changes = new ArrayList<>();
1380e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase            changes.addAll(mPendingChanges);
1390e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase            mChangesList.add(changes);
140235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase            mPendingChanges.clear();
141235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase            Runnable changer = new Runnable() {
142235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase                @Override
143235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase                public void run() {
1440e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                    for (ChangeInfo change : changes) {
145235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase                        animateChangeImpl(change);
146235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase                    }
1470e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                    changes.clear();
1480e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                    mChangesList.remove(changes);
149235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase                }
150235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase            };
151235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase            if (removalsPending) {
1520e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                ViewHolder holder = changes.get(0).oldHolder;
153235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase                ViewCompat.postOnAnimationDelayed(holder.itemView, changer, getRemoveDuration());
154235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase            } else {
155235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase                changer.run();
156235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase            }
157235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase        }
158d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        // Next, add stuff
159d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if (additionsPending) {
160e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar            final ArrayList<ViewHolder> additions = new ArrayList<>();
1610e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase            additions.addAll(mPendingAdditions);
1620e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase            mAdditionsList.add(additions);
163d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            mPendingAdditions.clear();
164d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            Runnable adder = new Runnable() {
165d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                public void run() {
1660e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                    for (ViewHolder holder : additions) {
167d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                        animateAddImpl(holder);
168d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                    }
1690e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                    additions.clear();
1700e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                    mAdditionsList.remove(additions);
171d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                }
172d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            };
173549bbdfca3cffe64fd3ef69723a54037df326689Chet Haase            if (removalsPending || movesPending || changesPending) {
174235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase                long removeDuration = removalsPending ? getRemoveDuration() : 0;
175235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase                long moveDuration = movesPending ? getMoveDuration() : 0;
176235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase                long changeDuration = changesPending ? getChangeDuration() : 0;
177235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase                long totalDelay = removeDuration + Math.max(moveDuration, changeDuration);
1780e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                View view = additions.get(0).itemView;
179235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase                ViewCompat.postOnAnimationDelayed(view, adder, totalDelay);
180d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            } else {
181d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                adder.run();
182d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            }
183d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
184d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
185d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
186d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    @Override
187d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public boolean animateRemove(final ViewHolder holder) {
188d03a495b04ee74c1cb493cee0d5998b895b1c79bVladislav Kaznacheev        resetAnimation(holder);
189d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        mPendingRemovals.add(holder);
190d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        return true;
191d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
192d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
193d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    private void animateRemoveImpl(final ViewHolder holder) {
194d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        final View view = holder.itemView;
19507715e8dcfa3e9fcd6c3e7727f61ca41b50e5763Dake Gu        final ViewPropertyAnimatorCompat animation = ViewCompat.animate(view);
1964d21e073e1aa2eb08777c288d08a92c419faa1e9Yigit Boyar        mRemoveAnimations.add(holder);
19707715e8dcfa3e9fcd6c3e7727f61ca41b50e5763Dake Gu        animation.setDuration(getRemoveDuration())
19807715e8dcfa3e9fcd6c3e7727f61ca41b50e5763Dake Gu                .alpha(0).setListener(new VpaListenerAdapter() {
199d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            @Override
200e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase            public void onAnimationStart(View view) {
201e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase                dispatchRemoveStarting(holder);
202e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase            }
2034d21e073e1aa2eb08777c288d08a92c419faa1e9Yigit Boyar
204e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase            @Override
205d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            public void onAnimationEnd(View view) {
20607715e8dcfa3e9fcd6c3e7727f61ca41b50e5763Dake Gu                animation.setListener(null);
207d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                ViewCompat.setAlpha(view, 1);
208d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                dispatchRemoveFinished(holder);
209d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                mRemoveAnimations.remove(holder);
210d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                dispatchFinishedWhenDone();
211d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            }
212d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }).start();
213d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
214d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
215d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    @Override
216d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public boolean animateAdd(final ViewHolder holder) {
217d03a495b04ee74c1cb493cee0d5998b895b1c79bVladislav Kaznacheev        resetAnimation(holder);
218d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        ViewCompat.setAlpha(holder.itemView, 0);
219d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        mPendingAdditions.add(holder);
220d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        return true;
221d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
222d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
223d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    private void animateAddImpl(final ViewHolder holder) {
224d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        final View view = holder.itemView;
22507715e8dcfa3e9fcd6c3e7727f61ca41b50e5763Dake Gu        final ViewPropertyAnimatorCompat animation = ViewCompat.animate(view);
2264d21e073e1aa2eb08777c288d08a92c419faa1e9Yigit Boyar        mAddAnimations.add(holder);
22707715e8dcfa3e9fcd6c3e7727f61ca41b50e5763Dake Gu        animation.alpha(1).setDuration(getAddDuration()).
228d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                setListener(new VpaListenerAdapter() {
229d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                    @Override
230e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase                    public void onAnimationStart(View view) {
231e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase                        dispatchAddStarting(holder);
232e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase                    }
233e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase                    @Override
234d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                    public void onAnimationCancel(View view) {
235d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                        ViewCompat.setAlpha(view, 1);
236d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                    }
237c35968d173f900d8024bdf38174e2225c9a7f311Chet Haase
238d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                    @Override
239d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                    public void onAnimationEnd(View view) {
24007715e8dcfa3e9fcd6c3e7727f61ca41b50e5763Dake Gu                        animation.setListener(null);
241d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                        dispatchAddFinished(holder);
242d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                        mAddAnimations.remove(holder);
243d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                        dispatchFinishedWhenDone();
244d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                    }
245d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                }).start();
246d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
247d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
248d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    @Override
249d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public boolean animateMove(final ViewHolder holder, int fromX, int fromY,
250d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            int toX, int toY) {
251d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        final View view = holder.itemView;
252504c54ea52c1b2aae6f8f4ae128f1dcaac7e3f6aYigit Boyar        fromX += ViewCompat.getTranslationX(holder.itemView);
253504c54ea52c1b2aae6f8f4ae128f1dcaac7e3f6aYigit Boyar        fromY += ViewCompat.getTranslationY(holder.itemView);
254d03a495b04ee74c1cb493cee0d5998b895b1c79bVladislav Kaznacheev        resetAnimation(holder);
255d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        int deltaX = toX - fromX;
256d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        int deltaY = toY - fromY;
257d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if (deltaX == 0 && deltaY == 0) {
258d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            dispatchMoveFinished(holder);
259d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            return false;
260d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
261d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if (deltaX != 0) {
262d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            ViewCompat.setTranslationX(view, -deltaX);
263d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
264d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if (deltaY != 0) {
265d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            ViewCompat.setTranslationY(view, -deltaY);
266d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
267d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        mPendingMoves.add(new MoveInfo(holder, fromX, fromY, toX, toY));
268d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        return true;
269d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
270d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
271d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    private void animateMoveImpl(final ViewHolder holder, int fromX, int fromY, int toX, int toY) {
272d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        final View view = holder.itemView;
273d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        final int deltaX = toX - fromX;
274d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        final int deltaY = toY - fromY;
275d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if (deltaX != 0) {
276d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            ViewCompat.animate(view).translationX(0);
277d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
278d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if (deltaY != 0) {
279d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            ViewCompat.animate(view).translationY(0);
280d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
281d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        // TODO: make EndActions end listeners instead, since end actions aren't called when
282d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        // vpas are canceled (and can't end them. why?)
283d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        // need listener functionality in VPACompat for this. Ick.
28407715e8dcfa3e9fcd6c3e7727f61ca41b50e5763Dake Gu        final ViewPropertyAnimatorCompat animation = ViewCompat.animate(view);
2854d21e073e1aa2eb08777c288d08a92c419faa1e9Yigit Boyar        mMoveAnimations.add(holder);
28607715e8dcfa3e9fcd6c3e7727f61ca41b50e5763Dake Gu        animation.setDuration(getMoveDuration()).setListener(new VpaListenerAdapter() {
287d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            @Override
288e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase            public void onAnimationStart(View view) {
289e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase                dispatchMoveStarting(holder);
290e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase            }
291e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase            @Override
292d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            public void onAnimationCancel(View view) {
293d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                if (deltaX != 0) {
294d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                    ViewCompat.setTranslationX(view, 0);
295d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                }
296d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                if (deltaY != 0) {
297d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                    ViewCompat.setTranslationY(view, 0);
298d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                }
299d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            }
300d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            @Override
301d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            public void onAnimationEnd(View view) {
30207715e8dcfa3e9fcd6c3e7727f61ca41b50e5763Dake Gu                animation.setListener(null);
303d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                dispatchMoveFinished(holder);
304d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                mMoveAnimations.remove(holder);
305d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                dispatchFinishedWhenDone();
306d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            }
307d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }).start();
308d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
309d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
310d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    @Override
311a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar    public boolean animateChange(ViewHolder oldHolder, ViewHolder newHolder,
312a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar            int fromX, int fromY, int toX, int toY) {
313121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar        if (oldHolder == newHolder) {
314121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar            // Don't know how to run change animations when the same view holder is re-used.
315121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar            // run a move animation to handle position changes.
316121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar            return animateMove(oldHolder, fromX, fromY, toX, toY);
317121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar        }
318a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        final float prevTranslationX = ViewCompat.getTranslationX(oldHolder.itemView);
319a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        final float prevTranslationY = ViewCompat.getTranslationY(oldHolder.itemView);
320a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        final float prevAlpha = ViewCompat.getAlpha(oldHolder.itemView);
321d03a495b04ee74c1cb493cee0d5998b895b1c79bVladislav Kaznacheev        resetAnimation(oldHolder);
322a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        int deltaX = (int) (toX - fromX - prevTranslationX);
323a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        int deltaY = (int) (toY - fromY - prevTranslationY);
324a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        // recover prev translation state after ending animation
325a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        ViewCompat.setTranslationX(oldHolder.itemView, prevTranslationX);
326a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        ViewCompat.setTranslationY(oldHolder.itemView, prevTranslationY);
327a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        ViewCompat.setAlpha(oldHolder.itemView, prevAlpha);
328e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar        if (newHolder != null) {
329a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar            // carry over translation values
330d03a495b04ee74c1cb493cee0d5998b895b1c79bVladislav Kaznacheev            resetAnimation(newHolder);
331a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar            ViewCompat.setTranslationX(newHolder.itemView, -deltaX);
332a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar            ViewCompat.setTranslationY(newHolder.itemView, -deltaY);
333235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase            ViewCompat.setAlpha(newHolder.itemView, 0);
334235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase        }
335a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        mPendingChanges.add(new ChangeInfo(oldHolder, newHolder, fromX, fromY, toX, toY));
336235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase        return true;
337235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase    }
338235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase
339235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase    private void animateChangeImpl(final ChangeInfo changeInfo) {
340235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase        final ViewHolder holder = changeInfo.oldHolder;
34190ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar        final View view = holder == null ? null : holder.itemView;
342235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase        final ViewHolder newHolder = changeInfo.newHolder;
343235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase        final View newView = newHolder != null ? newHolder.itemView : null;
34490ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar        if (view != null) {
34590ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar            final ViewPropertyAnimatorCompat oldViewAnim = ViewCompat.animate(view).setDuration(
34690ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar                    getChangeDuration());
3474d21e073e1aa2eb08777c288d08a92c419faa1e9Yigit Boyar            mChangeAnimations.add(changeInfo.oldHolder);
34890ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar            oldViewAnim.translationX(changeInfo.toX - changeInfo.fromX);
34990ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar            oldViewAnim.translationY(changeInfo.toY - changeInfo.fromY);
35090ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar            oldViewAnim.alpha(0).setListener(new VpaListenerAdapter() {
35190ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar                @Override
35290ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar                public void onAnimationStart(View view) {
35390ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar                    dispatchChangeStarting(changeInfo.oldHolder, true);
35490ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar                }
355a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar
35690ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar                @Override
35790ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar                public void onAnimationEnd(View view) {
35890ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar                    oldViewAnim.setListener(null);
35990ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar                    ViewCompat.setAlpha(view, 1);
36090ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar                    ViewCompat.setTranslationX(view, 0);
36190ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar                    ViewCompat.setTranslationY(view, 0);
36290ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar                    dispatchChangeFinished(changeInfo.oldHolder, true);
36390ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar                    mChangeAnimations.remove(changeInfo.oldHolder);
36490ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar                    dispatchFinishedWhenDone();
36590ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar                }
36690ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar            }).start();
36790ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar        }
368235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase        if (newView != null) {
36907715e8dcfa3e9fcd6c3e7727f61ca41b50e5763Dake Gu            final ViewPropertyAnimatorCompat newViewAnimation = ViewCompat.animate(newView);
3704d21e073e1aa2eb08777c288d08a92c419faa1e9Yigit Boyar            mChangeAnimations.add(changeInfo.newHolder);
371a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar            newViewAnimation.translationX(0).translationY(0).setDuration(getChangeDuration()).
372235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase                    alpha(1).setListener(new VpaListenerAdapter() {
373235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase                @Override
374e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase                public void onAnimationStart(View view) {
375e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase                    dispatchChangeStarting(changeInfo.newHolder, false);
376e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase                }
377e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase                @Override
378235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase                public void onAnimationEnd(View view) {
37907715e8dcfa3e9fcd6c3e7727f61ca41b50e5763Dake Gu                    newViewAnimation.setListener(null);
380235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase                    ViewCompat.setAlpha(newView, 1);
381a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar                    ViewCompat.setTranslationX(newView, 0);
382a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar                    ViewCompat.setTranslationY(newView, 0);
383e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase                    dispatchChangeFinished(changeInfo.newHolder, false);
384a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar                    mChangeAnimations.remove(changeInfo.newHolder);
385a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar                    dispatchFinishedWhenDone();
386235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase                }
387235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase            }).start();
388235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase        }
389a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar    }
390a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar
391a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar    private void endChangeAnimation(List<ChangeInfo> infoList, ViewHolder item) {
392a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        for (int i = infoList.size() - 1; i >= 0; i--) {
393a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar            ChangeInfo changeInfo = infoList.get(i);
394a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar            if (endChangeAnimationIfNecessary(changeInfo, item)) {
395a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar                if (changeInfo.oldHolder == null && changeInfo.newHolder == null) {
396a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar                    infoList.remove(changeInfo);
397a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar                }
398a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar            }
399a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        }
400a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar    }
401a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar
402a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar    private void endChangeAnimationIfNecessary(ChangeInfo changeInfo) {
403a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        if (changeInfo.oldHolder != null) {
404a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar            endChangeAnimationIfNecessary(changeInfo, changeInfo.oldHolder);
405a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        }
406a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        if (changeInfo.newHolder != null) {
407a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar            endChangeAnimationIfNecessary(changeInfo, changeInfo.newHolder);
408a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        }
409a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar    }
410a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar    private boolean endChangeAnimationIfNecessary(ChangeInfo changeInfo, ViewHolder item) {
411e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase        boolean oldItem = false;
412a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        if (changeInfo.newHolder == item) {
413a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar            changeInfo.newHolder = null;
414a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        } else if (changeInfo.oldHolder == item) {
415a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar            changeInfo.oldHolder = null;
416e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase            oldItem = true;
417a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        } else {
418a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar            return false;
419a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        }
420a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        ViewCompat.setAlpha(item.itemView, 1);
421a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        ViewCompat.setTranslationX(item.itemView, 0);
422a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        ViewCompat.setTranslationY(item.itemView, 0);
423e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase        dispatchChangeFinished(item, oldItem);
424a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        return true;
425235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase    }
426235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase
427235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase    @Override
428d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public void endAnimation(ViewHolder item) {
429d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        final View view = item.itemView;
430a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        // this will trigger end callback which should set properties to their target values.
431d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        ViewCompat.animate(view).cancel();
432a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        // TODO if some other animations are chained to end, how do we cancel them as well?
433235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase        for (int i = mPendingMoves.size() - 1; i >= 0; i--) {
434235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase            MoveInfo moveInfo = mPendingMoves.get(i);
435235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase            if (moveInfo.holder == item) {
436235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase                ViewCompat.setTranslationY(view, 0);
437235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase                ViewCompat.setTranslationX(view, 0);
438235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase                dispatchMoveFinished(item);
4399457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                mPendingMoves.remove(i);
440235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase            }
44193b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu        }
442a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        endChangeAnimation(mPendingChanges, item);
443a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        if (mPendingRemovals.remove(item)) {
444a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar            ViewCompat.setAlpha(view, 1);
44593b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu            dispatchRemoveFinished(item);
44693b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu        }
447a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        if (mPendingAdditions.remove(item)) {
44893b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu            ViewCompat.setAlpha(view, 1);
44993b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu            dispatchAddFinished(item);
450235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase        }
451a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar
4520e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase        for (int i = mChangesList.size() - 1; i >= 0; i--) {
4530e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase            ArrayList<ChangeInfo> changes = mChangesList.get(i);
4540e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase            endChangeAnimation(changes, item);
4550e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase            if (changes.isEmpty()) {
4569457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                mChangesList.remove(i);
457ec93520d243d3eb3c6cddeaea7908d1b869bf367Dake Gu            }
458ec93520d243d3eb3c6cddeaea7908d1b869bf367Dake Gu        }
4590e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase        for (int i = mMovesList.size() - 1; i >= 0; i--) {
4600e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase            ArrayList<MoveInfo> moves = mMovesList.get(i);
4610e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase            for (int j = moves.size() - 1; j >= 0; j--) {
4620e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                MoveInfo moveInfo = moves.get(j);
4630e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                if (moveInfo.holder == item) {
4640e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                    ViewCompat.setTranslationY(view, 0);
4650e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                    ViewCompat.setTranslationX(view, 0);
4660e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                    dispatchMoveFinished(item);
4670e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                    moves.remove(j);
4680e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                    if (moves.isEmpty()) {
4699457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                        mMovesList.remove(i);
4700e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                    }
4710e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                    break;
4720e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                }
4730e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase            }
4740e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase        }
4750e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase        for (int i = mAdditionsList.size() - 1; i >= 0; i--) {
4760e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase            ArrayList<ViewHolder> additions = mAdditionsList.get(i);
4770e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase            if (additions.remove(item)) {
4780e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                ViewCompat.setAlpha(view, 1);
4790e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                dispatchAddFinished(item);
4800e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                if (additions.isEmpty()) {
4819457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                    mAdditionsList.remove(i);
4820e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                }
4830e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase            }
484ec93520d243d3eb3c6cddeaea7908d1b869bf367Dake Gu        }
485a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar
486a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        // animations should be ended by the cancel above.
487e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar        //noinspection PointlessBooleanExpression,ConstantConditions
488a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        if (mRemoveAnimations.remove(item) && DEBUG) {
489a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar            throw new IllegalStateException("after animation is cancelled, item should not be in "
490a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar                    + "mRemoveAnimations list");
491d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
492a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar
493e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar        //noinspection PointlessBooleanExpression,ConstantConditions
494a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        if (mAddAnimations.remove(item) && DEBUG) {
495a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar            throw new IllegalStateException("after animation is cancelled, item should not be in "
496a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar                    + "mAddAnimations list");
497d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
498a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar
499e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar        //noinspection PointlessBooleanExpression,ConstantConditions
500a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        if (mChangeAnimations.remove(item) && DEBUG) {
501a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar            throw new IllegalStateException("after animation is cancelled, item should not be in "
502a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar                    + "mChangeAnimations list");
503a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        }
504a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar
505e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar        //noinspection PointlessBooleanExpression,ConstantConditions
506a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        if (mMoveAnimations.remove(item) && DEBUG) {
507a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar            throw new IllegalStateException("after animation is cancelled, item should not be in "
508a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar                    + "mMoveAnimations list");
509235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase        }
510d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        dispatchFinishedWhenDone();
511d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
512d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
513d03a495b04ee74c1cb493cee0d5998b895b1c79bVladislav Kaznacheev    private void resetAnimation(ViewHolder holder) {
514d03a495b04ee74c1cb493cee0d5998b895b1c79bVladislav Kaznacheev        AnimatorCompatHelper.clearInterpolator(holder.itemView);
515d03a495b04ee74c1cb493cee0d5998b895b1c79bVladislav Kaznacheev        endAnimation(holder);
516d03a495b04ee74c1cb493cee0d5998b895b1c79bVladislav Kaznacheev    }
517d03a495b04ee74c1cb493cee0d5998b895b1c79bVladislav Kaznacheev
518d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    @Override
519d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public boolean isRunning() {
520e3d27c97eb0769997cd9d73baabffff70551efe0Yigit Boyar        return (!mPendingAdditions.isEmpty() ||
521047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar                !mPendingChanges.isEmpty() ||
522047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar                !mPendingMoves.isEmpty() ||
523047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar                !mPendingRemovals.isEmpty() ||
524e3d27c97eb0769997cd9d73baabffff70551efe0Yigit Boyar                !mMoveAnimations.isEmpty() ||
525d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                !mRemoveAnimations.isEmpty() ||
526d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                !mAddAnimations.isEmpty() ||
527235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase                !mChangeAnimations.isEmpty() ||
5280e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                !mMovesList.isEmpty() ||
5290e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                !mAdditionsList.isEmpty() ||
5300e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                !mChangesList.isEmpty());
531d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
532d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
533d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    /**
534d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * Check the state of currently pending and running animations. If there are none
535d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * pending/running, call {@link #dispatchAnimationsFinished()} to notify any
536d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * listeners.
537d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     */
538d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    private void dispatchFinishedWhenDone() {
539d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if (!isRunning()) {
540d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            dispatchAnimationsFinished();
541d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
542d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
543d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
544d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    @Override
545d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    public void endAnimations() {
54693b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu        int count = mPendingMoves.size();
54793b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu        for (int i = count - 1; i >= 0; i--) {
54893b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu            MoveInfo item = mPendingMoves.get(i);
54993b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu            View view = item.holder.itemView;
55093b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu            ViewCompat.setTranslationY(view, 0);
55193b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu            ViewCompat.setTranslationX(view, 0);
55293b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu            dispatchMoveFinished(item.holder);
553ec93520d243d3eb3c6cddeaea7908d1b869bf367Dake Gu            mPendingMoves.remove(i);
55493b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu        }
55593b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu        count = mPendingRemovals.size();
55693b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu        for (int i = count - 1; i >= 0; i--) {
55793b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu            ViewHolder item = mPendingRemovals.get(i);
55893b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu            dispatchRemoveFinished(item);
559ec93520d243d3eb3c6cddeaea7908d1b869bf367Dake Gu            mPendingRemovals.remove(i);
56093b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu        }
56193b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu        count = mPendingAdditions.size();
56293b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu        for (int i = count - 1; i >= 0; i--) {
56393b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu            ViewHolder item = mPendingAdditions.get(i);
56493b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu            View view = item.itemView;
56593b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu            ViewCompat.setAlpha(view, 1);
56693b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu            dispatchAddFinished(item);
567ec93520d243d3eb3c6cddeaea7908d1b869bf367Dake Gu            mPendingAdditions.remove(i);
56893b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu        }
569235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase        count = mPendingChanges.size();
570235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase        for (int i = count - 1; i >= 0; i--) {
571a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar            endChangeAnimationIfNecessary(mPendingChanges.get(i));
572235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase        }
573a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        mPendingChanges.clear();
574d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        if (!isRunning()) {
575d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            return;
576d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        }
577235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase
5780e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase        int listCount = mMovesList.size();
5790e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase        for (int i = listCount - 1; i >= 0; i--) {
5800e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase            ArrayList<MoveInfo> moves = mMovesList.get(i);
5810e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase            count = moves.size();
5820e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase            for (int j = count - 1; j >= 0; j--) {
5830e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                MoveInfo moveInfo = moves.get(j);
5840e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                ViewHolder item = moveInfo.holder;
5850e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                View view = item.itemView;
5860e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                ViewCompat.setTranslationY(view, 0);
5870e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                ViewCompat.setTranslationX(view, 0);
5880e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                dispatchMoveFinished(moveInfo.holder);
5890e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                moves.remove(j);
5900e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                if (moves.isEmpty()) {
5910e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                    mMovesList.remove(moves);
5920e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                }
5930e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase            }
594235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase        }
5950e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase        listCount = mAdditionsList.size();
5960e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase        for (int i = listCount - 1; i >= 0; i--) {
5970e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase            ArrayList<ViewHolder> additions = mAdditionsList.get(i);
5980e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase            count = additions.size();
5990e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase            for (int j = count - 1; j >= 0; j--) {
6000e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                ViewHolder item = additions.get(j);
6010e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                View view = item.itemView;
6020e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                ViewCompat.setAlpha(view, 1);
6030e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                dispatchAddFinished(item);
6040e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                additions.remove(j);
6050e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                if (additions.isEmpty()) {
6060e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                    mAdditionsList.remove(additions);
6070e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                }
6080e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase            }
609235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase        }
6100e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase        listCount = mChangesList.size();
6110e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase        for (int i = listCount - 1; i >= 0; i--) {
6120e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase            ArrayList<ChangeInfo> changes = mChangesList.get(i);
6130e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase            count = changes.size();
6140e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase            for (int j = count - 1; j >= 0; j--) {
6150e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                endChangeAnimationIfNecessary(changes.get(j));
6160e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                if (changes.isEmpty()) {
6170e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                    mChangesList.remove(changes);
6180e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase                }
6190e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase            }
620235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase        }
621235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase
622a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        cancelAll(mRemoveAnimations);
623a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        cancelAll(mMoveAnimations);
624a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        cancelAll(mAddAnimations);
625a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        cancelAll(mChangeAnimations);
626ec93520d243d3eb3c6cddeaea7908d1b869bf367Dake Gu
627d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        dispatchAnimationsFinished();
628d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
629d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
630a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar    void cancelAll(List<ViewHolder> viewHolders) {
631a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        for (int i = viewHolders.size() - 1; i >= 0; i--) {
632a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar            ViewCompat.animate(viewHolders.get(i).itemView).cancel();
633a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar        }
634a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar    }
635a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar
636abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar    /**
637abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar     * {@inheritDoc}
638abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar     * <p>
639abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar     * If the payload list is not empty, DefaultItemAnimator returns <code>true</code>.
640abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar     * When this is the case:
641abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar     * <ul>
642abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar     * <li>If you override {@link #animateChange(ViewHolder, ViewHolder, int, int, int, int)}, both
643abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar     * ViewHolder arguments will be the same instance.
644abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar     * </li>
645abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar     * <li>
646abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar     * If you are not overriding {@link #animateChange(ViewHolder, ViewHolder, int, int, int, int)},
647abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar     * then DefaultItemAnimator will call {@link #animateMove(ViewHolder, int, int, int, int)} and
648abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar     * run a move animation instead.
649abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar     * </li>
650abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar     * </ul>
651abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar     */
652abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar    @Override
653abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar    public boolean canReuseUpdatedViewHolder(@NonNull ViewHolder viewHolder,
654abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar            @NonNull List<Object> payloads) {
655abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar        return !payloads.isEmpty() || super.canReuseUpdatedViewHolder(viewHolder, payloads);
656abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar    }
657abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar
658d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    private static class VpaListenerAdapter implements ViewPropertyAnimatorListener {
659d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        @Override
660d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        public void onAnimationStart(View view) {}
661d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
662d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        @Override
663d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        public void onAnimationEnd(View view) {}
664d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
665d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        @Override
666d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        public void onAnimationCancel(View view) {}
667e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar    }
668d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase}
669