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 18ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikasimport android.animation.Animator; 19ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikasimport android.animation.AnimatorListenerAdapter; 20ae7189188acb2bc972b08d9fbd59939f341c7829Aurimas Liutikasimport android.animation.TimeInterpolator; 21ae7189188acb2bc972b08d9fbd59939f341c7829Aurimas Liutikasimport android.animation.ValueAnimator; 22abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyarimport android.support.annotation.NonNull; 23d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haaseimport android.support.v4.view.ViewCompat; 24d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haaseimport android.support.v7.widget.RecyclerView.ViewHolder; 25d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haaseimport android.view.View; 26ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikasimport android.view.ViewPropertyAnimator; 27d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 28d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haaseimport java.util.ArrayList; 29a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyarimport java.util.List; 30d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 31d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase/** 32d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * This implementation of {@link RecyclerView.ItemAnimator} provides basic 33d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * animations on remove, add, and move events that happen to the items in 34d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * a RecyclerView. RecyclerView uses a DefaultItemAnimator by default. 35d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * 36d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * @see RecyclerView#setItemAnimator(RecyclerView.ItemAnimator) 37d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase */ 38121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyarpublic class DefaultItemAnimator extends SimpleItemAnimator { 39a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar private static final boolean DEBUG = false; 40d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 41ae7189188acb2bc972b08d9fbd59939f341c7829Aurimas Liutikas private static TimeInterpolator sDefaultInterpolator; 42ae7189188acb2bc972b08d9fbd59939f341c7829Aurimas Liutikas 43e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar private ArrayList<ViewHolder> mPendingRemovals = new ArrayList<>(); 44e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar private ArrayList<ViewHolder> mPendingAdditions = new ArrayList<>(); 45e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar private ArrayList<MoveInfo> mPendingMoves = new ArrayList<>(); 46e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar private ArrayList<ChangeInfo> mPendingChanges = new ArrayList<>(); 47d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 483a500f61a8bdf48904f380f2d4925fe420d18ce7Aurimas Liutikas ArrayList<ArrayList<ViewHolder>> mAdditionsList = new ArrayList<>(); 493a500f61a8bdf48904f380f2d4925fe420d18ce7Aurimas Liutikas ArrayList<ArrayList<MoveInfo>> mMovesList = new ArrayList<>(); 503a500f61a8bdf48904f380f2d4925fe420d18ce7Aurimas Liutikas ArrayList<ArrayList<ChangeInfo>> mChangesList = new ArrayList<>(); 51d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 523a500f61a8bdf48904f380f2d4925fe420d18ce7Aurimas Liutikas ArrayList<ViewHolder> mAddAnimations = new ArrayList<>(); 533a500f61a8bdf48904f380f2d4925fe420d18ce7Aurimas Liutikas ArrayList<ViewHolder> mMoveAnimations = new ArrayList<>(); 543a500f61a8bdf48904f380f2d4925fe420d18ce7Aurimas Liutikas ArrayList<ViewHolder> mRemoveAnimations = new ArrayList<>(); 553a500f61a8bdf48904f380f2d4925fe420d18ce7Aurimas Liutikas ArrayList<ViewHolder> mChangeAnimations = new ArrayList<>(); 56d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 57d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase private static class MoveInfo { 58d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public ViewHolder holder; 59d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public int fromX, fromY, toX, toY; 60d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 613a500f61a8bdf48904f380f2d4925fe420d18ce7Aurimas Liutikas MoveInfo(ViewHolder holder, int fromX, int fromY, int toX, int toY) { 62d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase this.holder = holder; 63d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase this.fromX = fromX; 64d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase this.fromY = fromY; 65d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase this.toX = toX; 66d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase this.toY = toY; 67d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 68d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 69d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 70235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase private static class ChangeInfo { 71235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase public ViewHolder oldHolder, newHolder; 72a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar public int fromX, fromY, toX, toY; 73235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase private ChangeInfo(ViewHolder oldHolder, ViewHolder newHolder) { 74235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase this.oldHolder = oldHolder; 75235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase this.newHolder = newHolder; 76235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 77a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar 783a500f61a8bdf48904f380f2d4925fe420d18ce7Aurimas Liutikas ChangeInfo(ViewHolder oldHolder, ViewHolder newHolder, 79a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar int fromX, int fromY, int toX, int toY) { 80a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar this(oldHolder, newHolder); 81a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar this.fromX = fromX; 82a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar this.fromY = fromY; 83a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar this.toX = toX; 84a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar this.toY = toY; 85a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 86a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar 87a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar @Override 88a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar public String toString() { 891e827caa16440590647019b9c1338f6309c5be7aAurimas Liutikas return "ChangeInfo{" 901e827caa16440590647019b9c1338f6309c5be7aAurimas Liutikas + "oldHolder=" + oldHolder 911e827caa16440590647019b9c1338f6309c5be7aAurimas Liutikas + ", newHolder=" + newHolder 921e827caa16440590647019b9c1338f6309c5be7aAurimas Liutikas + ", fromX=" + fromX 931e827caa16440590647019b9c1338f6309c5be7aAurimas Liutikas + ", fromY=" + fromY 941e827caa16440590647019b9c1338f6309c5be7aAurimas Liutikas + ", toX=" + toX 951e827caa16440590647019b9c1338f6309c5be7aAurimas Liutikas + ", toY=" + toY 961e827caa16440590647019b9c1338f6309c5be7aAurimas Liutikas + '}'; 97a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 98235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 99235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase 100d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 101d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void runPendingAnimations() { 102d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase boolean removalsPending = !mPendingRemovals.isEmpty(); 103d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase boolean movesPending = !mPendingMoves.isEmpty(); 104235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase boolean changesPending = !mPendingChanges.isEmpty(); 105d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase boolean additionsPending = !mPendingAdditions.isEmpty(); 106a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar if (!removalsPending && !movesPending && !additionsPending && !changesPending) { 107d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase // nothing to animate 108d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase return; 109d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 110d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase // First, remove stuff 111d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase for (ViewHolder holder : mPendingRemovals) { 112d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase animateRemoveImpl(holder); 113d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 114d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mPendingRemovals.clear(); 115d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase // Next, move stuff 116d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (movesPending) { 117e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar final ArrayList<MoveInfo> moves = new ArrayList<>(); 1180e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase moves.addAll(mPendingMoves); 1190e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase mMovesList.add(moves); 120d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mPendingMoves.clear(); 121d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase Runnable mover = new Runnable() { 122d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 123d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void run() { 1240e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase for (MoveInfo moveInfo : moves) { 125d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase animateMoveImpl(moveInfo.holder, moveInfo.fromX, moveInfo.fromY, 126d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase moveInfo.toX, moveInfo.toY); 127d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 1280e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase moves.clear(); 1290e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase mMovesList.remove(moves); 130d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 131d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase }; 132d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (removalsPending) { 1330e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase View view = moves.get(0).holder.itemView; 134d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.postOnAnimationDelayed(view, mover, getRemoveDuration()); 135d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } else { 136d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mover.run(); 137d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 138d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 139235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase // Next, change stuff, to run in parallel with move animations 140235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase if (changesPending) { 141e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar final ArrayList<ChangeInfo> changes = new ArrayList<>(); 1420e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase changes.addAll(mPendingChanges); 1430e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase mChangesList.add(changes); 144235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase mPendingChanges.clear(); 145235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase Runnable changer = new Runnable() { 146235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase @Override 147235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase public void run() { 1480e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase for (ChangeInfo change : changes) { 149235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase animateChangeImpl(change); 150235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 1510e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase changes.clear(); 1520e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase mChangesList.remove(changes); 153235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 154235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase }; 155235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase if (removalsPending) { 1560e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ViewHolder holder = changes.get(0).oldHolder; 157235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase ViewCompat.postOnAnimationDelayed(holder.itemView, changer, getRemoveDuration()); 158235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } else { 159235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase changer.run(); 160235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 161235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 162d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase // Next, add stuff 163d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (additionsPending) { 164e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar final ArrayList<ViewHolder> additions = new ArrayList<>(); 1650e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase additions.addAll(mPendingAdditions); 1660e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase mAdditionsList.add(additions); 167d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mPendingAdditions.clear(); 168d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase Runnable adder = new Runnable() { 169dc8e099ed130434c0238f558277c5bcb6a533121Aurimas Liutikas @Override 170d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void run() { 1710e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase for (ViewHolder holder : additions) { 172d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase animateAddImpl(holder); 173d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 1740e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase additions.clear(); 1750e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase mAdditionsList.remove(additions); 176d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 177d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase }; 178549bbdfca3cffe64fd3ef69723a54037df326689Chet Haase if (removalsPending || movesPending || changesPending) { 179235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase long removeDuration = removalsPending ? getRemoveDuration() : 0; 180235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase long moveDuration = movesPending ? getMoveDuration() : 0; 181235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase long changeDuration = changesPending ? getChangeDuration() : 0; 182235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase long totalDelay = removeDuration + Math.max(moveDuration, changeDuration); 1830e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase View view = additions.get(0).itemView; 184235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase ViewCompat.postOnAnimationDelayed(view, adder, totalDelay); 185d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } else { 186d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase adder.run(); 187d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 188d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 189d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 190d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 191d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 192d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public boolean animateRemove(final ViewHolder holder) { 193d03a495b04ee74c1cb493cee0d5998b895b1c79bVladislav Kaznacheev resetAnimation(holder); 194d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mPendingRemovals.add(holder); 195d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase return true; 196d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 197d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 198d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase private void animateRemoveImpl(final ViewHolder holder) { 199d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase final View view = holder.itemView; 200ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas final ViewPropertyAnimator animation = view.animate(); 2014d21e073e1aa2eb08777c288d08a92c419faa1e9Yigit Boyar mRemoveAnimations.add(holder); 202ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas animation.setDuration(getRemoveDuration()).alpha(0).setListener( 203ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas new AnimatorListenerAdapter() { 204ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas @Override 205ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas public void onAnimationStart(Animator animator) { 206ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas dispatchRemoveStarting(holder); 207ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas } 2084d21e073e1aa2eb08777c288d08a92c419faa1e9Yigit Boyar 209ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas @Override 210ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas public void onAnimationEnd(Animator animator) { 211ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas animation.setListener(null); 212ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas view.setAlpha(1); 213ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas dispatchRemoveFinished(holder); 214ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas mRemoveAnimations.remove(holder); 215ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas dispatchFinishedWhenDone(); 216ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas } 217ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas }).start(); 218d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 219d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 220d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 221d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public boolean animateAdd(final ViewHolder holder) { 222d03a495b04ee74c1cb493cee0d5998b895b1c79bVladislav Kaznacheev resetAnimation(holder); 223ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas holder.itemView.setAlpha(0); 224d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mPendingAdditions.add(holder); 225d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase return true; 226d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 227d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 2283a500f61a8bdf48904f380f2d4925fe420d18ce7Aurimas Liutikas void animateAddImpl(final ViewHolder holder) { 229d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase final View view = holder.itemView; 230ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas final ViewPropertyAnimator animation = view.animate(); 2314d21e073e1aa2eb08777c288d08a92c419faa1e9Yigit Boyar mAddAnimations.add(holder); 232ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas animation.alpha(1).setDuration(getAddDuration()) 233ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas .setListener(new AnimatorListenerAdapter() { 234d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 235ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas public void onAnimationStart(Animator animator) { 236e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase dispatchAddStarting(holder); 237e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase } 238ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas 239e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase @Override 240ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas public void onAnimationCancel(Animator animator) { 241ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas view.setAlpha(1); 242d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 243c35968d173f900d8024bdf38174e2225c9a7f311Chet Haase 244d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 245ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas public void onAnimationEnd(Animator animator) { 24607715e8dcfa3e9fcd6c3e7727f61ca41b50e5763Dake Gu animation.setListener(null); 247d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase dispatchAddFinished(holder); 248d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mAddAnimations.remove(holder); 249d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase dispatchFinishedWhenDone(); 250d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 251d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase }).start(); 252d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 253d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 254d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 255d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public boolean animateMove(final ViewHolder holder, int fromX, int fromY, 256d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase int toX, int toY) { 257d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase final View view = holder.itemView; 2586bebe14261b8f3f17ef5059f00d077c7b81561ccAurimas Liutikas fromX += (int) holder.itemView.getTranslationX(); 2596bebe14261b8f3f17ef5059f00d077c7b81561ccAurimas Liutikas fromY += (int) holder.itemView.getTranslationY(); 260d03a495b04ee74c1cb493cee0d5998b895b1c79bVladislav Kaznacheev resetAnimation(holder); 261d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase int deltaX = toX - fromX; 262d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase int deltaY = toY - fromY; 263d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (deltaX == 0 && deltaY == 0) { 264d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase dispatchMoveFinished(holder); 265d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase return false; 266d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 267d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (deltaX != 0) { 268ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas view.setTranslationX(-deltaX); 269d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 270d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (deltaY != 0) { 271ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas view.setTranslationY(-deltaY); 272d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 273d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mPendingMoves.add(new MoveInfo(holder, fromX, fromY, toX, toY)); 274d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase return true; 275d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 276d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 2773a500f61a8bdf48904f380f2d4925fe420d18ce7Aurimas Liutikas void animateMoveImpl(final ViewHolder holder, int fromX, int fromY, int toX, int toY) { 278d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase final View view = holder.itemView; 279d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase final int deltaX = toX - fromX; 280d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase final int deltaY = toY - fromY; 281d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (deltaX != 0) { 282ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas view.animate().translationX(0); 283d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 284d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (deltaY != 0) { 285ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas view.animate().translationY(0); 286d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 287d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase // TODO: make EndActions end listeners instead, since end actions aren't called when 288d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase // vpas are canceled (and can't end them. why?) 289d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase // need listener functionality in VPACompat for this. Ick. 290ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas final ViewPropertyAnimator animation = view.animate(); 2914d21e073e1aa2eb08777c288d08a92c419faa1e9Yigit Boyar mMoveAnimations.add(holder); 292ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas animation.setDuration(getMoveDuration()).setListener(new AnimatorListenerAdapter() { 293d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 294ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas public void onAnimationStart(Animator animator) { 295e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase dispatchMoveStarting(holder); 296e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase } 297ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas 298e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase @Override 299ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas public void onAnimationCancel(Animator animator) { 300d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (deltaX != 0) { 301ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas view.setTranslationX(0); 302d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 303d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (deltaY != 0) { 304ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas view.setTranslationY(0); 305d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 306d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 307ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas 308d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 309ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas public void onAnimationEnd(Animator animator) { 31007715e8dcfa3e9fcd6c3e7727f61ca41b50e5763Dake Gu animation.setListener(null); 311d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase dispatchMoveFinished(holder); 312d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mMoveAnimations.remove(holder); 313d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase dispatchFinishedWhenDone(); 314d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 315d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase }).start(); 316d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 317d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 318d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 319a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar public boolean animateChange(ViewHolder oldHolder, ViewHolder newHolder, 320a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar int fromX, int fromY, int toX, int toY) { 321121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar if (oldHolder == newHolder) { 322121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar // Don't know how to run change animations when the same view holder is re-used. 323121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar // run a move animation to handle position changes. 324121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar return animateMove(oldHolder, fromX, fromY, toX, toY); 325121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 326ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas final float prevTranslationX = oldHolder.itemView.getTranslationX(); 327ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas final float prevTranslationY = oldHolder.itemView.getTranslationY(); 328ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas final float prevAlpha = oldHolder.itemView.getAlpha(); 329d03a495b04ee74c1cb493cee0d5998b895b1c79bVladislav Kaznacheev resetAnimation(oldHolder); 330a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar int deltaX = (int) (toX - fromX - prevTranslationX); 331a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar int deltaY = (int) (toY - fromY - prevTranslationY); 332a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar // recover prev translation state after ending animation 333ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas oldHolder.itemView.setTranslationX(prevTranslationX); 334ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas oldHolder.itemView.setTranslationY(prevTranslationY); 335ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas oldHolder.itemView.setAlpha(prevAlpha); 336e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar if (newHolder != null) { 337a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar // carry over translation values 338d03a495b04ee74c1cb493cee0d5998b895b1c79bVladislav Kaznacheev resetAnimation(newHolder); 339ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas newHolder.itemView.setTranslationX(-deltaX); 340ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas newHolder.itemView.setTranslationY(-deltaY); 341ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas newHolder.itemView.setAlpha(0); 342235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 343a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar mPendingChanges.add(new ChangeInfo(oldHolder, newHolder, fromX, fromY, toX, toY)); 344235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase return true; 345235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 346235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase 3473a500f61a8bdf48904f380f2d4925fe420d18ce7Aurimas Liutikas void animateChangeImpl(final ChangeInfo changeInfo) { 348235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase final ViewHolder holder = changeInfo.oldHolder; 34990ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar final View view = holder == null ? null : holder.itemView; 350235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase final ViewHolder newHolder = changeInfo.newHolder; 351235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase final View newView = newHolder != null ? newHolder.itemView : null; 35290ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar if (view != null) { 353ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas final ViewPropertyAnimator oldViewAnim = view.animate().setDuration( 35490ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar getChangeDuration()); 3554d21e073e1aa2eb08777c288d08a92c419faa1e9Yigit Boyar mChangeAnimations.add(changeInfo.oldHolder); 35690ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar oldViewAnim.translationX(changeInfo.toX - changeInfo.fromX); 35790ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar oldViewAnim.translationY(changeInfo.toY - changeInfo.fromY); 358ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas oldViewAnim.alpha(0).setListener(new AnimatorListenerAdapter() { 35990ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar @Override 360ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas public void onAnimationStart(Animator animator) { 36190ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar dispatchChangeStarting(changeInfo.oldHolder, true); 36290ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar } 363a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar 36490ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar @Override 365ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas public void onAnimationEnd(Animator animator) { 36690ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar oldViewAnim.setListener(null); 367ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas view.setAlpha(1); 368ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas view.setTranslationX(0); 369ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas view.setTranslationY(0); 37090ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar dispatchChangeFinished(changeInfo.oldHolder, true); 37190ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar mChangeAnimations.remove(changeInfo.oldHolder); 37290ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar dispatchFinishedWhenDone(); 37390ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar } 37490ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar }).start(); 37590ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar } 376235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase if (newView != null) { 377f18d9dcf92e0103b163491b1fcf242e18ec1e59eAurimas Liutikas final ViewPropertyAnimator newViewAnimation = newView.animate(); 3784d21e073e1aa2eb08777c288d08a92c419faa1e9Yigit Boyar mChangeAnimations.add(changeInfo.newHolder); 3791e827caa16440590647019b9c1338f6309c5be7aAurimas Liutikas newViewAnimation.translationX(0).translationY(0).setDuration(getChangeDuration()) 3801e827caa16440590647019b9c1338f6309c5be7aAurimas Liutikas .alpha(1).setListener(new AnimatorListenerAdapter() { 381ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas @Override 382ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas public void onAnimationStart(Animator animator) { 383ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas dispatchChangeStarting(changeInfo.newHolder, false); 384ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas } 385ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas @Override 386ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas public void onAnimationEnd(Animator animator) { 387ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas newViewAnimation.setListener(null); 388ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas newView.setAlpha(1); 389ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas newView.setTranslationX(0); 390ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas newView.setTranslationY(0); 391ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas dispatchChangeFinished(changeInfo.newHolder, false); 392ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas mChangeAnimations.remove(changeInfo.newHolder); 393ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas dispatchFinishedWhenDone(); 394ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas } 395ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas }).start(); 396235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 397a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 398a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar 399a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar private void endChangeAnimation(List<ChangeInfo> infoList, ViewHolder item) { 400a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar for (int i = infoList.size() - 1; i >= 0; i--) { 401a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar ChangeInfo changeInfo = infoList.get(i); 402a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar if (endChangeAnimationIfNecessary(changeInfo, item)) { 403a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar if (changeInfo.oldHolder == null && changeInfo.newHolder == null) { 404a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar infoList.remove(changeInfo); 405a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 406a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 407a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 408a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 409a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar 410a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar private void endChangeAnimationIfNecessary(ChangeInfo changeInfo) { 411a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar if (changeInfo.oldHolder != null) { 412a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar endChangeAnimationIfNecessary(changeInfo, changeInfo.oldHolder); 413a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 414a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar if (changeInfo.newHolder != null) { 415a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar endChangeAnimationIfNecessary(changeInfo, changeInfo.newHolder); 416a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 417a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 418a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar private boolean endChangeAnimationIfNecessary(ChangeInfo changeInfo, ViewHolder item) { 419e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase boolean oldItem = false; 420a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar if (changeInfo.newHolder == item) { 421a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar changeInfo.newHolder = null; 422a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } else if (changeInfo.oldHolder == item) { 423a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar changeInfo.oldHolder = null; 424e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase oldItem = true; 425a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } else { 426a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar return false; 427a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 428ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas item.itemView.setAlpha(1); 429ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas item.itemView.setTranslationX(0); 430ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas item.itemView.setTranslationY(0); 431e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase dispatchChangeFinished(item, oldItem); 432a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar return true; 433235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 434235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase 435235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase @Override 436d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void endAnimation(ViewHolder item) { 437d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase final View view = item.itemView; 438a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar // this will trigger end callback which should set properties to their target values. 439ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas view.animate().cancel(); 440a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar // TODO if some other animations are chained to end, how do we cancel them as well? 441235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase for (int i = mPendingMoves.size() - 1; i >= 0; i--) { 442235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase MoveInfo moveInfo = mPendingMoves.get(i); 443235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase if (moveInfo.holder == item) { 444ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas view.setTranslationY(0); 445ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas view.setTranslationX(0); 446235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase dispatchMoveFinished(item); 4479457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar mPendingMoves.remove(i); 448235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 44993b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu } 450a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar endChangeAnimation(mPendingChanges, item); 451a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar if (mPendingRemovals.remove(item)) { 452ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas view.setAlpha(1); 45393b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu dispatchRemoveFinished(item); 45493b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu } 455a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar if (mPendingAdditions.remove(item)) { 456ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas view.setAlpha(1); 45793b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu dispatchAddFinished(item); 458235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 459a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar 4600e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase for (int i = mChangesList.size() - 1; i >= 0; i--) { 4610e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ArrayList<ChangeInfo> changes = mChangesList.get(i); 4620e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase endChangeAnimation(changes, item); 4630e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase if (changes.isEmpty()) { 4649457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar mChangesList.remove(i); 465ec93520d243d3eb3c6cddeaea7908d1b869bf367Dake Gu } 466ec93520d243d3eb3c6cddeaea7908d1b869bf367Dake Gu } 4670e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase for (int i = mMovesList.size() - 1; i >= 0; i--) { 4680e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ArrayList<MoveInfo> moves = mMovesList.get(i); 4690e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase for (int j = moves.size() - 1; j >= 0; j--) { 4700e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase MoveInfo moveInfo = moves.get(j); 4710e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase if (moveInfo.holder == item) { 472ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas view.setTranslationY(0); 473ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas view.setTranslationX(0); 4740e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase dispatchMoveFinished(item); 4750e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase moves.remove(j); 4760e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase if (moves.isEmpty()) { 4779457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar mMovesList.remove(i); 4780e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase } 4790e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase break; 4800e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase } 4810e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase } 4820e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase } 4830e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase for (int i = mAdditionsList.size() - 1; i >= 0; i--) { 4840e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ArrayList<ViewHolder> additions = mAdditionsList.get(i); 4850e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase if (additions.remove(item)) { 486ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas view.setAlpha(1); 4870e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase dispatchAddFinished(item); 4880e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase if (additions.isEmpty()) { 4899457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar mAdditionsList.remove(i); 4900e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase } 4910e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase } 492ec93520d243d3eb3c6cddeaea7908d1b869bf367Dake Gu } 493a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar 494a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar // animations should be ended by the cancel above. 495e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar //noinspection PointlessBooleanExpression,ConstantConditions 496a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar if (mRemoveAnimations.remove(item) && DEBUG) { 497a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar throw new IllegalStateException("after animation is cancelled, item should not be in " 498a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar + "mRemoveAnimations list"); 499d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 500a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar 501e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar //noinspection PointlessBooleanExpression,ConstantConditions 502a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar if (mAddAnimations.remove(item) && DEBUG) { 503a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar throw new IllegalStateException("after animation is cancelled, item should not be in " 504a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar + "mAddAnimations list"); 505d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 506a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar 507e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar //noinspection PointlessBooleanExpression,ConstantConditions 508a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar if (mChangeAnimations.remove(item) && DEBUG) { 509a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar throw new IllegalStateException("after animation is cancelled, item should not be in " 510a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar + "mChangeAnimations list"); 511a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 512a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar 513e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar //noinspection PointlessBooleanExpression,ConstantConditions 514a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar if (mMoveAnimations.remove(item) && DEBUG) { 515a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar throw new IllegalStateException("after animation is cancelled, item should not be in " 516a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar + "mMoveAnimations list"); 517235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 518d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase dispatchFinishedWhenDone(); 519d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 520d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 521d03a495b04ee74c1cb493cee0d5998b895b1c79bVladislav Kaznacheev private void resetAnimation(ViewHolder holder) { 522ae7189188acb2bc972b08d9fbd59939f341c7829Aurimas Liutikas if (sDefaultInterpolator == null) { 523ae7189188acb2bc972b08d9fbd59939f341c7829Aurimas Liutikas sDefaultInterpolator = new ValueAnimator().getInterpolator(); 524ae7189188acb2bc972b08d9fbd59939f341c7829Aurimas Liutikas } 525ae7189188acb2bc972b08d9fbd59939f341c7829Aurimas Liutikas holder.itemView.animate().setInterpolator(sDefaultInterpolator); 526d03a495b04ee74c1cb493cee0d5998b895b1c79bVladislav Kaznacheev endAnimation(holder); 527d03a495b04ee74c1cb493cee0d5998b895b1c79bVladislav Kaznacheev } 528d03a495b04ee74c1cb493cee0d5998b895b1c79bVladislav Kaznacheev 529d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 530d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public boolean isRunning() { 5311e827caa16440590647019b9c1338f6309c5be7aAurimas Liutikas return (!mPendingAdditions.isEmpty() 5321e827caa16440590647019b9c1338f6309c5be7aAurimas Liutikas || !mPendingChanges.isEmpty() 5331e827caa16440590647019b9c1338f6309c5be7aAurimas Liutikas || !mPendingMoves.isEmpty() 5341e827caa16440590647019b9c1338f6309c5be7aAurimas Liutikas || !mPendingRemovals.isEmpty() 5351e827caa16440590647019b9c1338f6309c5be7aAurimas Liutikas || !mMoveAnimations.isEmpty() 5361e827caa16440590647019b9c1338f6309c5be7aAurimas Liutikas || !mRemoveAnimations.isEmpty() 5371e827caa16440590647019b9c1338f6309c5be7aAurimas Liutikas || !mAddAnimations.isEmpty() 5381e827caa16440590647019b9c1338f6309c5be7aAurimas Liutikas || !mChangeAnimations.isEmpty() 5391e827caa16440590647019b9c1338f6309c5be7aAurimas Liutikas || !mMovesList.isEmpty() 5401e827caa16440590647019b9c1338f6309c5be7aAurimas Liutikas || !mAdditionsList.isEmpty() 5411e827caa16440590647019b9c1338f6309c5be7aAurimas Liutikas || !mChangesList.isEmpty()); 542d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 543d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 544d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase /** 545d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * Check the state of currently pending and running animations. If there are none 546d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * pending/running, call {@link #dispatchAnimationsFinished()} to notify any 547d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * listeners. 548d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase */ 5493a500f61a8bdf48904f380f2d4925fe420d18ce7Aurimas Liutikas void dispatchFinishedWhenDone() { 550d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (!isRunning()) { 551d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase dispatchAnimationsFinished(); 552d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 553d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 554d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 555d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 556d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void endAnimations() { 55793b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu int count = mPendingMoves.size(); 55893b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu for (int i = count - 1; i >= 0; i--) { 55993b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu MoveInfo item = mPendingMoves.get(i); 56093b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu View view = item.holder.itemView; 561ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas view.setTranslationY(0); 562ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas view.setTranslationX(0); 56393b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu dispatchMoveFinished(item.holder); 564ec93520d243d3eb3c6cddeaea7908d1b869bf367Dake Gu mPendingMoves.remove(i); 56593b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu } 56693b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu count = mPendingRemovals.size(); 56793b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu for (int i = count - 1; i >= 0; i--) { 56893b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu ViewHolder item = mPendingRemovals.get(i); 56993b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu dispatchRemoveFinished(item); 570ec93520d243d3eb3c6cddeaea7908d1b869bf367Dake Gu mPendingRemovals.remove(i); 57193b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu } 57293b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu count = mPendingAdditions.size(); 57393b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu for (int i = count - 1; i >= 0; i--) { 57493b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu ViewHolder item = mPendingAdditions.get(i); 575ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas item.itemView.setAlpha(1); 57693b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu dispatchAddFinished(item); 577ec93520d243d3eb3c6cddeaea7908d1b869bf367Dake Gu mPendingAdditions.remove(i); 57893b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu } 579235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase count = mPendingChanges.size(); 580235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase for (int i = count - 1; i >= 0; i--) { 581a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar endChangeAnimationIfNecessary(mPendingChanges.get(i)); 582235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 583a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar mPendingChanges.clear(); 584d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (!isRunning()) { 585d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase return; 586d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 587235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase 5880e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase int listCount = mMovesList.size(); 5890e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase for (int i = listCount - 1; i >= 0; i--) { 5900e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ArrayList<MoveInfo> moves = mMovesList.get(i); 5910e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase count = moves.size(); 5920e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase for (int j = count - 1; j >= 0; j--) { 5930e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase MoveInfo moveInfo = moves.get(j); 5940e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ViewHolder item = moveInfo.holder; 5950e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase View view = item.itemView; 596ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas view.setTranslationY(0); 597ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas view.setTranslationX(0); 5980e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase dispatchMoveFinished(moveInfo.holder); 5990e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase moves.remove(j); 6000e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase if (moves.isEmpty()) { 6010e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase mMovesList.remove(moves); 6020e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase } 6030e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase } 604235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 6050e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase listCount = mAdditionsList.size(); 6060e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase for (int i = listCount - 1; i >= 0; i--) { 6070e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ArrayList<ViewHolder> additions = mAdditionsList.get(i); 6080e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase count = additions.size(); 6090e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase for (int j = count - 1; j >= 0; j--) { 6100e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ViewHolder item = additions.get(j); 6110e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase View view = item.itemView; 612ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas view.setAlpha(1); 6130e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase dispatchAddFinished(item); 6140e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase additions.remove(j); 6150e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase if (additions.isEmpty()) { 6160e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase mAdditionsList.remove(additions); 6170e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase } 6180e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase } 619235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 6200e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase listCount = mChangesList.size(); 6210e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase for (int i = listCount - 1; i >= 0; i--) { 6220e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ArrayList<ChangeInfo> changes = mChangesList.get(i); 6230e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase count = changes.size(); 6240e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase for (int j = count - 1; j >= 0; j--) { 6250e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase endChangeAnimationIfNecessary(changes.get(j)); 6260e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase if (changes.isEmpty()) { 6270e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase mChangesList.remove(changes); 6280e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase } 6290e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase } 630235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 631235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase 632a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar cancelAll(mRemoveAnimations); 633a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar cancelAll(mMoveAnimations); 634a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar cancelAll(mAddAnimations); 635a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar cancelAll(mChangeAnimations); 636ec93520d243d3eb3c6cddeaea7908d1b869bf367Dake Gu 637d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase dispatchAnimationsFinished(); 638d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 639d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 640a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar void cancelAll(List<ViewHolder> viewHolders) { 641a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar for (int i = viewHolders.size() - 1; i >= 0; i--) { 642ca03208c6ef5bd79af99309d0e14db4a238cb691Aurimas Liutikas viewHolders.get(i).itemView.animate().cancel(); 643a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 644a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 645a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar 646abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar /** 647abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar * {@inheritDoc} 648abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar * <p> 649abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar * If the payload list is not empty, DefaultItemAnimator returns <code>true</code>. 650abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar * When this is the case: 651abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar * <ul> 652abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar * <li>If you override {@link #animateChange(ViewHolder, ViewHolder, int, int, int, int)}, both 653abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar * ViewHolder arguments will be the same instance. 654abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar * </li> 655abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar * <li> 656abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar * If you are not overriding {@link #animateChange(ViewHolder, ViewHolder, int, int, int, int)}, 657abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar * then DefaultItemAnimator will call {@link #animateMove(ViewHolder, int, int, int, int)} and 658abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar * run a move animation instead. 659abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar * </li> 660abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar * </ul> 661abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar */ 662abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar @Override 663abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar public boolean canReuseUpdatedViewHolder(@NonNull ViewHolder viewHolder, 664abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar @NonNull List<Object> payloads) { 665abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar return !payloads.isEmpty() || super.canReuseUpdatedViewHolder(viewHolder, payloads); 666abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar } 667d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase} 668