DefaultItemAnimator.java revision 549bbdfca3cffe64fd3ef69723a54037df326689
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 18d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haaseimport android.support.v4.view.ViewCompat; 19a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyarimport android.support.v4.view.ViewPropertyAnimatorCompat; 20d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haaseimport android.support.v4.view.ViewPropertyAnimatorListener; 21d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haaseimport android.support.v7.widget.RecyclerView.ViewHolder; 22d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haaseimport android.view.View; 23d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 24d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haaseimport java.util.ArrayList; 25a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyarimport java.util.List; 26d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 27d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase/** 28d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * This implementation of {@link RecyclerView.ItemAnimator} provides basic 29d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * animations on remove, add, and move events that happen to the items in 30d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * a RecyclerView. RecyclerView uses a DefaultItemAnimator by default. 31d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * 32d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * @see RecyclerView#setItemAnimator(RecyclerView.ItemAnimator) 33d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase */ 34d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haasepublic class DefaultItemAnimator extends RecyclerView.ItemAnimator { 35a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar private static final boolean DEBUG = false; 36d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 37d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase private ArrayList<ViewHolder> mPendingRemovals = new ArrayList<ViewHolder>(); 38d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase private ArrayList<ViewHolder> mPendingAdditions = new ArrayList<ViewHolder>(); 39d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase private ArrayList<MoveInfo> mPendingMoves = new ArrayList<MoveInfo>(); 40235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase private ArrayList<ChangeInfo> mPendingChanges = new ArrayList<ChangeInfo>(); 41d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 420e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase private ArrayList<ArrayList<ViewHolder>> mAdditionsList = 430e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase new ArrayList<ArrayList<ViewHolder>>(); 440e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase private ArrayList<ArrayList<MoveInfo>> mMovesList = new ArrayList<ArrayList<MoveInfo>>(); 450e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase private ArrayList<ArrayList<ChangeInfo>> mChangesList = new ArrayList<ArrayList<ChangeInfo>>(); 46d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 47d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase private ArrayList<ViewHolder> mAddAnimations = new ArrayList<ViewHolder>(); 48d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase private ArrayList<ViewHolder> mMoveAnimations = new ArrayList<ViewHolder>(); 49d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase private ArrayList<ViewHolder> mRemoveAnimations = new ArrayList<ViewHolder>(); 50a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar private ArrayList<ViewHolder> mChangeAnimations = new ArrayList<ViewHolder>(); 51d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 52d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase private static class MoveInfo { 53d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public ViewHolder holder; 54d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public int fromX, fromY, toX, toY; 55d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 56d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase private MoveInfo(ViewHolder holder, int fromX, int fromY, int toX, int toY) { 57d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase this.holder = holder; 58d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase this.fromX = fromX; 59d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase this.fromY = fromY; 60d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase this.toX = toX; 61d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase this.toY = toY; 62d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 63d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 64d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 65235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase private static class ChangeInfo { 66235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase public ViewHolder oldHolder, newHolder; 67a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar public int fromX, fromY, toX, toY; 68235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase private ChangeInfo(ViewHolder oldHolder, ViewHolder newHolder) { 69235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase this.oldHolder = oldHolder; 70235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase this.newHolder = newHolder; 71235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 72a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar 73a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar private ChangeInfo(ViewHolder oldHolder, ViewHolder newHolder, 74a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar int fromX, int fromY, int toX, int toY) { 75a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar this(oldHolder, newHolder); 76a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar this.fromX = fromX; 77a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar this.fromY = fromY; 78a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar this.toX = toX; 79a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar this.toY = toY; 80a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 81a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar 82a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar @Override 83a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar public String toString() { 84a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar return "ChangeInfo{" + 85a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar "oldHolder=" + oldHolder + 86a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar ", newHolder=" + newHolder + 87a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar ", fromX=" + fromX + 88a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar ", fromY=" + fromY + 89a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar ", toX=" + toX + 90a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar ", toY=" + toY + 91a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar '}'; 92a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 93235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 94235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase 95d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 96d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void runPendingAnimations() { 97d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase boolean removalsPending = !mPendingRemovals.isEmpty(); 98d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase boolean movesPending = !mPendingMoves.isEmpty(); 99235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase boolean changesPending = !mPendingChanges.isEmpty(); 100d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase boolean additionsPending = !mPendingAdditions.isEmpty(); 101a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar if (!removalsPending && !movesPending && !additionsPending && !changesPending) { 102d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase // nothing to animate 103d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase return; 104d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 105d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase // First, remove stuff 106d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase for (ViewHolder holder : mPendingRemovals) { 107d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase animateRemoveImpl(holder); 108d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 109d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mPendingRemovals.clear(); 110d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase // Next, move stuff 111d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (movesPending) { 1120e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase final ArrayList<MoveInfo> moves = new ArrayList<MoveInfo>(); 1130e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase moves.addAll(mPendingMoves); 1140e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase mMovesList.add(moves); 115d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mPendingMoves.clear(); 116d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase Runnable mover = new Runnable() { 117d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 118d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void run() { 1190e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase for (MoveInfo moveInfo : moves) { 120d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase animateMoveImpl(moveInfo.holder, moveInfo.fromX, moveInfo.fromY, 121d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase moveInfo.toX, moveInfo.toY); 122d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 1230e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase moves.clear(); 1240e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase mMovesList.remove(moves); 125d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 126d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase }; 127d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (removalsPending) { 1280e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase View view = moves.get(0).holder.itemView; 129d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.postOnAnimationDelayed(view, mover, getRemoveDuration()); 130d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } else { 131d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mover.run(); 132d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 133d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 134235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase // Next, change stuff, to run in parallel with move animations 135235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase if (changesPending) { 1360e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase final ArrayList<ChangeInfo> changes = new ArrayList<ChangeInfo>(); 1370e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase changes.addAll(mPendingChanges); 1380e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase mChangesList.add(changes); 139235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase mPendingChanges.clear(); 140235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase Runnable changer = new Runnable() { 141235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase @Override 142235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase public void run() { 1430e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase for (ChangeInfo change : changes) { 144235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase animateChangeImpl(change); 145235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 1460e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase changes.clear(); 1470e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase mChangesList.remove(changes); 148235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 149235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase }; 150235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase if (removalsPending) { 1510e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ViewHolder holder = changes.get(0).oldHolder; 152235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase ViewCompat.postOnAnimationDelayed(holder.itemView, changer, getRemoveDuration()); 153235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } else { 154235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase changer.run(); 155235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 156235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 157d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase // Next, add stuff 158d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (additionsPending) { 1590e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase final ArrayList<ViewHolder> additions = new ArrayList<ViewHolder>(); 1600e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase additions.addAll(mPendingAdditions); 1610e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase mAdditionsList.add(additions); 162d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mPendingAdditions.clear(); 163d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase Runnable adder = new Runnable() { 164d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void run() { 1650e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase for (ViewHolder holder : additions) { 166d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase animateAddImpl(holder); 167d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 1680e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase additions.clear(); 1690e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase mAdditionsList.remove(additions); 170d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 171d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase }; 172549bbdfca3cffe64fd3ef69723a54037df326689Chet Haase if (removalsPending || movesPending || changesPending) { 173235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase long removeDuration = removalsPending ? getRemoveDuration() : 0; 174235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase long moveDuration = movesPending ? getMoveDuration() : 0; 175235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase long changeDuration = changesPending ? getChangeDuration() : 0; 176235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase long totalDelay = removeDuration + Math.max(moveDuration, changeDuration); 1770e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase View view = additions.get(0).itemView; 178235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase ViewCompat.postOnAnimationDelayed(view, adder, totalDelay); 179d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } else { 180d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase adder.run(); 181d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 182d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 183d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 184d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 185d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 186d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public boolean animateRemove(final ViewHolder holder) { 187504c54ea52c1b2aae6f8f4ae128f1dcaac7e3f6aYigit Boyar endAnimation(holder); 188d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mPendingRemovals.add(holder); 189d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase return true; 190d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 191d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 192d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase private void animateRemoveImpl(final ViewHolder holder) { 193d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase final View view = holder.itemView; 19407715e8dcfa3e9fcd6c3e7727f61ca41b50e5763Dake Gu final ViewPropertyAnimatorCompat animation = ViewCompat.animate(view); 19507715e8dcfa3e9fcd6c3e7727f61ca41b50e5763Dake Gu animation.setDuration(getRemoveDuration()) 19607715e8dcfa3e9fcd6c3e7727f61ca41b50e5763Dake Gu .alpha(0).setListener(new VpaListenerAdapter() { 197d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 198e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase public void onAnimationStart(View view) { 199e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase dispatchRemoveStarting(holder); 200e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase } 201e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase @Override 202d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void onAnimationEnd(View view) { 20307715e8dcfa3e9fcd6c3e7727f61ca41b50e5763Dake Gu animation.setListener(null); 204d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.setAlpha(view, 1); 205d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase dispatchRemoveFinished(holder); 206d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mRemoveAnimations.remove(holder); 207d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase dispatchFinishedWhenDone(); 208d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 209d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase }).start(); 210d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mRemoveAnimations.add(holder); 211d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 212d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 213d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 214d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public boolean animateAdd(final ViewHolder holder) { 215504c54ea52c1b2aae6f8f4ae128f1dcaac7e3f6aYigit Boyar endAnimation(holder); 216d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.setAlpha(holder.itemView, 0); 217d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mPendingAdditions.add(holder); 218d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase return true; 219d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 220d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 221d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase private void animateAddImpl(final ViewHolder holder) { 222d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase final View view = holder.itemView; 223a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar mAddAnimations.add(holder); 22407715e8dcfa3e9fcd6c3e7727f61ca41b50e5763Dake Gu final ViewPropertyAnimatorCompat animation = ViewCompat.animate(view); 22507715e8dcfa3e9fcd6c3e7727f61ca41b50e5763Dake Gu animation.alpha(1).setDuration(getAddDuration()). 226d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase setListener(new VpaListenerAdapter() { 227d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 228e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase public void onAnimationStart(View view) { 229e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase dispatchAddStarting(holder); 230e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase } 231e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase @Override 232d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void onAnimationCancel(View view) { 233d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.setAlpha(view, 1); 234d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 235c35968d173f900d8024bdf38174e2225c9a7f311Chet Haase 236d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 237d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void onAnimationEnd(View view) { 23807715e8dcfa3e9fcd6c3e7727f61ca41b50e5763Dake Gu animation.setListener(null); 239d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase dispatchAddFinished(holder); 240d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mAddAnimations.remove(holder); 241d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase dispatchFinishedWhenDone(); 242d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 243d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase }).start(); 244d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 245d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 246d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 247d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public boolean animateMove(final ViewHolder holder, int fromX, int fromY, 248d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase int toX, int toY) { 249d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase final View view = holder.itemView; 250504c54ea52c1b2aae6f8f4ae128f1dcaac7e3f6aYigit Boyar fromX += ViewCompat.getTranslationX(holder.itemView); 251504c54ea52c1b2aae6f8f4ae128f1dcaac7e3f6aYigit Boyar fromY += ViewCompat.getTranslationY(holder.itemView); 252504c54ea52c1b2aae6f8f4ae128f1dcaac7e3f6aYigit Boyar endAnimation(holder); 253d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase int deltaX = toX - fromX; 254d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase int deltaY = toY - fromY; 255d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (deltaX == 0 && deltaY == 0) { 256d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase dispatchMoveFinished(holder); 257d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase return false; 258d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 259d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (deltaX != 0) { 260d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.setTranslationX(view, -deltaX); 261d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 262d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (deltaY != 0) { 263d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.setTranslationY(view, -deltaY); 264d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 265d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mPendingMoves.add(new MoveInfo(holder, fromX, fromY, toX, toY)); 266d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase return true; 267d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 268d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 269d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase private void animateMoveImpl(final ViewHolder holder, int fromX, int fromY, int toX, int toY) { 270d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase final View view = holder.itemView; 271d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase final int deltaX = toX - fromX; 272d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase final int deltaY = toY - fromY; 273d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (deltaX != 0) { 274d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.animate(view).translationX(0); 275d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 276d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (deltaY != 0) { 277d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.animate(view).translationY(0); 278d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 279d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase // TODO: make EndActions end listeners instead, since end actions aren't called when 280d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase // vpas are canceled (and can't end them. why?) 281d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase // need listener functionality in VPACompat for this. Ick. 282a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar mMoveAnimations.add(holder); 28307715e8dcfa3e9fcd6c3e7727f61ca41b50e5763Dake Gu final ViewPropertyAnimatorCompat animation = ViewCompat.animate(view); 28407715e8dcfa3e9fcd6c3e7727f61ca41b50e5763Dake Gu animation.setDuration(getMoveDuration()).setListener(new VpaListenerAdapter() { 285d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 286e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase public void onAnimationStart(View view) { 287e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase dispatchMoveStarting(holder); 288e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase } 289e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase @Override 290d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void onAnimationCancel(View view) { 291d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (deltaX != 0) { 292d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.setTranslationX(view, 0); 293d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 294d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (deltaY != 0) { 295d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.setTranslationY(view, 0); 296d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 297d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 298d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 299d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void onAnimationEnd(View view) { 30007715e8dcfa3e9fcd6c3e7727f61ca41b50e5763Dake Gu animation.setListener(null); 301d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase dispatchMoveFinished(holder); 302d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mMoveAnimations.remove(holder); 303d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase dispatchFinishedWhenDone(); 304d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 305d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase }).start(); 306d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 307d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 308d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 309a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar public boolean animateChange(ViewHolder oldHolder, ViewHolder newHolder, 310a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar int fromX, int fromY, int toX, int toY) { 311a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar final float prevTranslationX = ViewCompat.getTranslationX(oldHolder.itemView); 312a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar final float prevTranslationY = ViewCompat.getTranslationY(oldHolder.itemView); 313a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar final float prevAlpha = ViewCompat.getAlpha(oldHolder.itemView); 314504c54ea52c1b2aae6f8f4ae128f1dcaac7e3f6aYigit Boyar endAnimation(oldHolder); 315a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar int deltaX = (int) (toX - fromX - prevTranslationX); 316a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar int deltaY = (int) (toY - fromY - prevTranslationY); 317a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar // recover prev translation state after ending animation 318a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar ViewCompat.setTranslationX(oldHolder.itemView, prevTranslationX); 319a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar ViewCompat.setTranslationY(oldHolder.itemView, prevTranslationY); 320a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar ViewCompat.setAlpha(oldHolder.itemView, prevAlpha); 321235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase if (newHolder != null && newHolder.itemView != null) { 322a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar // carry over translation values 323504c54ea52c1b2aae6f8f4ae128f1dcaac7e3f6aYigit Boyar endAnimation(newHolder); 324a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar ViewCompat.setTranslationX(newHolder.itemView, -deltaX); 325a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar ViewCompat.setTranslationY(newHolder.itemView, -deltaY); 326235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase ViewCompat.setAlpha(newHolder.itemView, 0); 327235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 328a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar mPendingChanges.add(new ChangeInfo(oldHolder, newHolder, fromX, fromY, toX, toY)); 329235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase return true; 330235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 331235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase 332235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase private void animateChangeImpl(final ChangeInfo changeInfo) { 333235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase final ViewHolder holder = changeInfo.oldHolder; 334235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase final View view = holder.itemView; 335235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase final ViewHolder newHolder = changeInfo.newHolder; 336235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase final View newView = newHolder != null ? newHolder.itemView : null; 337a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar mChangeAnimations.add(changeInfo.oldHolder); 338a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar 33907715e8dcfa3e9fcd6c3e7727f61ca41b50e5763Dake Gu final ViewPropertyAnimatorCompat oldViewAnim = ViewCompat.animate(view).setDuration( 340a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar getChangeDuration()); 341a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar oldViewAnim.translationX(changeInfo.toX - changeInfo.fromX); 342a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar oldViewAnim.translationY(changeInfo.toY - changeInfo.fromY); 343a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar oldViewAnim.alpha(0).setListener(new VpaListenerAdapter() { 344235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase @Override 345e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase public void onAnimationStart(View view) { 346e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase dispatchChangeStarting(changeInfo.oldHolder, true); 347e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase } 348e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase @Override 349235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase public void onAnimationEnd(View view) { 35007715e8dcfa3e9fcd6c3e7727f61ca41b50e5763Dake Gu oldViewAnim.setListener(null); 351235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase ViewCompat.setAlpha(view, 1); 352a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar ViewCompat.setTranslationX(view, 0); 353a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar ViewCompat.setTranslationY(view, 0); 354e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase dispatchChangeFinished(changeInfo.oldHolder, true); 355a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar mChangeAnimations.remove(changeInfo.oldHolder); 356235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase dispatchFinishedWhenDone(); 357235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 358235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase }).start(); 359235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase if (newView != null) { 360a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar mChangeAnimations.add(changeInfo.newHolder); 36107715e8dcfa3e9fcd6c3e7727f61ca41b50e5763Dake Gu final ViewPropertyAnimatorCompat newViewAnimation = ViewCompat.animate(newView); 362a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar newViewAnimation.translationX(0).translationY(0).setDuration(getChangeDuration()). 363235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase alpha(1).setListener(new VpaListenerAdapter() { 364235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase @Override 365e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase public void onAnimationStart(View view) { 366e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase dispatchChangeStarting(changeInfo.newHolder, false); 367e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase } 368e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase @Override 369235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase public void onAnimationEnd(View view) { 37007715e8dcfa3e9fcd6c3e7727f61ca41b50e5763Dake Gu newViewAnimation.setListener(null); 371235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase ViewCompat.setAlpha(newView, 1); 372a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar ViewCompat.setTranslationX(newView, 0); 373a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar ViewCompat.setTranslationY(newView, 0); 374e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase dispatchChangeFinished(changeInfo.newHolder, false); 375a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar mChangeAnimations.remove(changeInfo.newHolder); 376a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar dispatchFinishedWhenDone(); 377235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 378235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase }).start(); 379235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 380a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 381a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar 382a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar private void endChangeAnimation(List<ChangeInfo> infoList, ViewHolder item) { 383a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar for (int i = infoList.size() - 1; i >= 0; i--) { 384a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar ChangeInfo changeInfo = infoList.get(i); 385a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar if (endChangeAnimationIfNecessary(changeInfo, item)) { 386a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar if (changeInfo.oldHolder == null && changeInfo.newHolder == null) { 387a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar infoList.remove(changeInfo); 388a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 389a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 390a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 391a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 392a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar 393a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar private void endChangeAnimationIfNecessary(ChangeInfo changeInfo) { 394a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar if (changeInfo.oldHolder != null) { 395a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar endChangeAnimationIfNecessary(changeInfo, changeInfo.oldHolder); 396a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 397a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar if (changeInfo.newHolder != null) { 398a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar endChangeAnimationIfNecessary(changeInfo, changeInfo.newHolder); 399a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 400a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 401a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar private boolean endChangeAnimationIfNecessary(ChangeInfo changeInfo, ViewHolder item) { 402e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase boolean oldItem = false; 403a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar if (changeInfo.newHolder == item) { 404a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar changeInfo.newHolder = null; 405a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } else if (changeInfo.oldHolder == item) { 406a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar changeInfo.oldHolder = null; 407e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase oldItem = true; 408a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } else { 409a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar return false; 410a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 411a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar ViewCompat.setAlpha(item.itemView, 1); 412a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar ViewCompat.setTranslationX(item.itemView, 0); 413a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar ViewCompat.setTranslationY(item.itemView, 0); 414e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase dispatchChangeFinished(item, oldItem); 415a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar return true; 416235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 417235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase 418235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase @Override 419d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void endAnimation(ViewHolder item) { 420d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase final View view = item.itemView; 421a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar // this will trigger end callback which should set properties to their target values. 422d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.animate(view).cancel(); 423a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar // TODO if some other animations are chained to end, how do we cancel them as well? 424235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase for (int i = mPendingMoves.size() - 1; i >= 0; i--) { 425235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase MoveInfo moveInfo = mPendingMoves.get(i); 426235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase if (moveInfo.holder == item) { 427235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase ViewCompat.setTranslationY(view, 0); 428235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase ViewCompat.setTranslationX(view, 0); 429235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase dispatchMoveFinished(item); 430235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase mPendingMoves.remove(item); 431235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 43293b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu } 433a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar endChangeAnimation(mPendingChanges, item); 434a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar if (mPendingRemovals.remove(item)) { 435a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar ViewCompat.setAlpha(view, 1); 43693b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu dispatchRemoveFinished(item); 43793b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu } 438a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar if (mPendingAdditions.remove(item)) { 43993b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu ViewCompat.setAlpha(view, 1); 44093b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu dispatchAddFinished(item); 441235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 442a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar 4430e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase for (int i = mChangesList.size() - 1; i >= 0; i--) { 4440e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ArrayList<ChangeInfo> changes = mChangesList.get(i); 4450e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase endChangeAnimation(changes, item); 4460e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase if (changes.isEmpty()) { 4470e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase mChangesList.remove(changes); 448ec93520d243d3eb3c6cddeaea7908d1b869bf367Dake Gu } 449ec93520d243d3eb3c6cddeaea7908d1b869bf367Dake Gu } 4500e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase for (int i = mMovesList.size() - 1; i >= 0; i--) { 4510e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ArrayList<MoveInfo> moves = mMovesList.get(i); 4520e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase for (int j = moves.size() - 1; j >= 0; j--) { 4530e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase MoveInfo moveInfo = moves.get(j); 4540e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase if (moveInfo.holder == item) { 4550e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ViewCompat.setTranslationY(view, 0); 4560e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ViewCompat.setTranslationX(view, 0); 4570e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase dispatchMoveFinished(item); 4580e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase moves.remove(j); 4590e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase if (moves.isEmpty()) { 4600e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase mMovesList.remove(moves); 4610e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase } 4620e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase break; 4630e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase } 4640e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase } 4650e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase } 4660e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase for (int i = mAdditionsList.size() - 1; i >= 0; i--) { 4670e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ArrayList<ViewHolder> additions = mAdditionsList.get(i); 4680e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase if (additions.remove(item)) { 4690e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ViewCompat.setAlpha(view, 1); 4700e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase dispatchAddFinished(item); 4710e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase if (additions.isEmpty()) { 4720e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase mAdditionsList.remove(additions); 4730e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase } 4740e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase } 475ec93520d243d3eb3c6cddeaea7908d1b869bf367Dake Gu } 476a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar 477a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar // animations should be ended by the cancel above. 478a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar if (mRemoveAnimations.remove(item) && DEBUG) { 479a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar throw new IllegalStateException("after animation is cancelled, item should not be in " 480a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar + "mRemoveAnimations list"); 481d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 482a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar 483a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar if (mAddAnimations.remove(item) && DEBUG) { 484a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar throw new IllegalStateException("after animation is cancelled, item should not be in " 485a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar + "mAddAnimations list"); 486d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 487a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar 488a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar if (mChangeAnimations.remove(item) && DEBUG) { 489a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar throw new IllegalStateException("after animation is cancelled, item should not be in " 490a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar + "mChangeAnimations list"); 491a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 492a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar 493a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar if (mMoveAnimations.remove(item) && DEBUG) { 494a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar throw new IllegalStateException("after animation is cancelled, item should not be in " 495a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar + "mMoveAnimations list"); 496235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 497d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase dispatchFinishedWhenDone(); 498d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 499d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 500d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 501d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public boolean isRunning() { 502e3d27c97eb0769997cd9d73baabffff70551efe0Yigit Boyar return (!mPendingAdditions.isEmpty() || 503047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar !mPendingChanges.isEmpty() || 504047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar !mPendingMoves.isEmpty() || 505047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar !mPendingRemovals.isEmpty() || 506e3d27c97eb0769997cd9d73baabffff70551efe0Yigit Boyar !mMoveAnimations.isEmpty() || 507d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase !mRemoveAnimations.isEmpty() || 508d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase !mAddAnimations.isEmpty() || 509235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase !mChangeAnimations.isEmpty() || 5100e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase !mMovesList.isEmpty() || 5110e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase !mAdditionsList.isEmpty() || 5120e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase !mChangesList.isEmpty()); 513d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 514d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 515d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase /** 516d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * Check the state of currently pending and running animations. If there are none 517d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * pending/running, call {@link #dispatchAnimationsFinished()} to notify any 518d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * listeners. 519d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase */ 520d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase private void dispatchFinishedWhenDone() { 521d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (!isRunning()) { 522d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase dispatchAnimationsFinished(); 523d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 524d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 525d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 526d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 527d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void endAnimations() { 52893b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu int count = mPendingMoves.size(); 52993b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu for (int i = count - 1; i >= 0; i--) { 53093b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu MoveInfo item = mPendingMoves.get(i); 53193b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu View view = item.holder.itemView; 53293b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu ViewCompat.setTranslationY(view, 0); 53393b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu ViewCompat.setTranslationX(view, 0); 53493b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu dispatchMoveFinished(item.holder); 535ec93520d243d3eb3c6cddeaea7908d1b869bf367Dake Gu mPendingMoves.remove(i); 53693b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu } 53793b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu count = mPendingRemovals.size(); 53893b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu for (int i = count - 1; i >= 0; i--) { 53993b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu ViewHolder item = mPendingRemovals.get(i); 54093b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu dispatchRemoveFinished(item); 541ec93520d243d3eb3c6cddeaea7908d1b869bf367Dake Gu mPendingRemovals.remove(i); 54293b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu } 54393b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu count = mPendingAdditions.size(); 54493b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu for (int i = count - 1; i >= 0; i--) { 54593b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu ViewHolder item = mPendingAdditions.get(i); 54693b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu View view = item.itemView; 54793b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu ViewCompat.setAlpha(view, 1); 54893b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu dispatchAddFinished(item); 549ec93520d243d3eb3c6cddeaea7908d1b869bf367Dake Gu mPendingAdditions.remove(i); 55093b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu } 551235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase count = mPendingChanges.size(); 552235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase for (int i = count - 1; i >= 0; i--) { 553a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar endChangeAnimationIfNecessary(mPendingChanges.get(i)); 554235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 555a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar mPendingChanges.clear(); 556d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (!isRunning()) { 557d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase return; 558d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 559235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase 5600e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase int listCount = mMovesList.size(); 5610e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase for (int i = listCount - 1; i >= 0; i--) { 5620e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ArrayList<MoveInfo> moves = mMovesList.get(i); 5630e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase count = moves.size(); 5640e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase for (int j = count - 1; j >= 0; j--) { 5650e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase MoveInfo moveInfo = moves.get(j); 5660e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ViewHolder item = moveInfo.holder; 5670e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase View view = item.itemView; 5680e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ViewCompat.setTranslationY(view, 0); 5690e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ViewCompat.setTranslationX(view, 0); 5700e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase dispatchMoveFinished(moveInfo.holder); 5710e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase moves.remove(j); 5720e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase if (moves.isEmpty()) { 5730e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase mMovesList.remove(moves); 5740e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase } 5750e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase } 576235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 5770e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase listCount = mAdditionsList.size(); 5780e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase for (int i = listCount - 1; i >= 0; i--) { 5790e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ArrayList<ViewHolder> additions = mAdditionsList.get(i); 5800e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase count = additions.size(); 5810e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase for (int j = count - 1; j >= 0; j--) { 5820e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ViewHolder item = additions.get(j); 5830e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase View view = item.itemView; 5840e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ViewCompat.setAlpha(view, 1); 5850e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase dispatchAddFinished(item); 5860e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase additions.remove(j); 5870e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase if (additions.isEmpty()) { 5880e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase mAdditionsList.remove(additions); 5890e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase } 5900e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase } 591235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 5920e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase listCount = mChangesList.size(); 5930e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase for (int i = listCount - 1; i >= 0; i--) { 5940e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ArrayList<ChangeInfo> changes = mChangesList.get(i); 5950e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase count = changes.size(); 5960e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase for (int j = count - 1; j >= 0; j--) { 5970e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase endChangeAnimationIfNecessary(changes.get(j)); 5980e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase if (changes.isEmpty()) { 5990e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase mChangesList.remove(changes); 6000e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase } 6010e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase } 602235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 603235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase 604a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar cancelAll(mRemoveAnimations); 605a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar cancelAll(mMoveAnimations); 606a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar cancelAll(mAddAnimations); 607a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar cancelAll(mChangeAnimations); 608ec93520d243d3eb3c6cddeaea7908d1b869bf367Dake Gu 609d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase dispatchAnimationsFinished(); 610d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 611d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 612a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar void cancelAll(List<ViewHolder> viewHolders) { 613a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar for (int i = viewHolders.size() - 1; i >= 0; i--) { 614a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar ViewCompat.animate(viewHolders.get(i).itemView).cancel(); 615a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 616a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 617a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar 618d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase private static class VpaListenerAdapter implements ViewPropertyAnimatorListener { 619d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 620d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void onAnimationStart(View view) {} 621d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 622d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 623d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void onAnimationEnd(View view) {} 624d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 625d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 626d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void onAnimationCancel(View view) {} 627d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase }; 628d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase} 629