DefaultItemAnimator.java revision 90ca3086dbf66ad6bb8840e46ec8524a705e1c18
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; 33490ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar final View view = holder == null ? null : holder.itemView; 335235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase final ViewHolder newHolder = changeInfo.newHolder; 336235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase final View newView = newHolder != null ? newHolder.itemView : null; 33790ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar if (view != null) { 33890ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar mChangeAnimations.add(changeInfo.oldHolder); 33990ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar final ViewPropertyAnimatorCompat oldViewAnim = ViewCompat.animate(view).setDuration( 34090ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar getChangeDuration()); 34190ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar oldViewAnim.translationX(changeInfo.toX - changeInfo.fromX); 34290ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar oldViewAnim.translationY(changeInfo.toY - changeInfo.fromY); 34390ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar oldViewAnim.alpha(0).setListener(new VpaListenerAdapter() { 34490ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar @Override 34590ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar public void onAnimationStart(View view) { 34690ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar dispatchChangeStarting(changeInfo.oldHolder, true); 34790ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar } 348a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar 34990ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar @Override 35090ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar public void onAnimationEnd(View view) { 35190ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar oldViewAnim.setListener(null); 35290ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar ViewCompat.setAlpha(view, 1); 35390ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar ViewCompat.setTranslationX(view, 0); 35490ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar ViewCompat.setTranslationY(view, 0); 35590ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar dispatchChangeFinished(changeInfo.oldHolder, true); 35690ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar mChangeAnimations.remove(changeInfo.oldHolder); 35790ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar dispatchFinishedWhenDone(); 35890ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar } 35990ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar }).start(); 36090ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar } 361235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase if (newView != null) { 362a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar mChangeAnimations.add(changeInfo.newHolder); 36307715e8dcfa3e9fcd6c3e7727f61ca41b50e5763Dake Gu final ViewPropertyAnimatorCompat newViewAnimation = ViewCompat.animate(newView); 364a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar newViewAnimation.translationX(0).translationY(0).setDuration(getChangeDuration()). 365235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase alpha(1).setListener(new VpaListenerAdapter() { 366235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase @Override 367e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase public void onAnimationStart(View view) { 368e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase dispatchChangeStarting(changeInfo.newHolder, false); 369e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase } 370e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase @Override 371235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase public void onAnimationEnd(View view) { 37207715e8dcfa3e9fcd6c3e7727f61ca41b50e5763Dake Gu newViewAnimation.setListener(null); 373235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase ViewCompat.setAlpha(newView, 1); 374a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar ViewCompat.setTranslationX(newView, 0); 375a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar ViewCompat.setTranslationY(newView, 0); 376e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase dispatchChangeFinished(changeInfo.newHolder, false); 377a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar mChangeAnimations.remove(changeInfo.newHolder); 378a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar dispatchFinishedWhenDone(); 379235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 380235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase }).start(); 381235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 382a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 383a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar 384a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar private void endChangeAnimation(List<ChangeInfo> infoList, ViewHolder item) { 385a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar for (int i = infoList.size() - 1; i >= 0; i--) { 386a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar ChangeInfo changeInfo = infoList.get(i); 387a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar if (endChangeAnimationIfNecessary(changeInfo, item)) { 388a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar if (changeInfo.oldHolder == null && changeInfo.newHolder == null) { 389a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar infoList.remove(changeInfo); 390a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 391a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 392a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 393a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 394a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar 395a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar private void endChangeAnimationIfNecessary(ChangeInfo changeInfo) { 396a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar if (changeInfo.oldHolder != null) { 397a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar endChangeAnimationIfNecessary(changeInfo, changeInfo.oldHolder); 398a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 399a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar if (changeInfo.newHolder != null) { 400a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar endChangeAnimationIfNecessary(changeInfo, changeInfo.newHolder); 401a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 402a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 403a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar private boolean endChangeAnimationIfNecessary(ChangeInfo changeInfo, ViewHolder item) { 404e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase boolean oldItem = false; 405a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar if (changeInfo.newHolder == item) { 406a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar changeInfo.newHolder = null; 407a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } else if (changeInfo.oldHolder == item) { 408a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar changeInfo.oldHolder = null; 409e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase oldItem = true; 410a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } else { 411a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar return false; 412a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 413a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar ViewCompat.setAlpha(item.itemView, 1); 414a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar ViewCompat.setTranslationX(item.itemView, 0); 415a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar ViewCompat.setTranslationY(item.itemView, 0); 416e321eb5c831282c92a28a483692d8520b766a0a5Chet Haase dispatchChangeFinished(item, oldItem); 417a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar return true; 418235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 419235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase 420235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase @Override 421d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void endAnimation(ViewHolder item) { 422d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase final View view = item.itemView; 423a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar // this will trigger end callback which should set properties to their target values. 424d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.animate(view).cancel(); 425a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar // TODO if some other animations are chained to end, how do we cancel them as well? 426235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase for (int i = mPendingMoves.size() - 1; i >= 0; i--) { 427235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase MoveInfo moveInfo = mPendingMoves.get(i); 428235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase if (moveInfo.holder == item) { 429235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase ViewCompat.setTranslationY(view, 0); 430235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase ViewCompat.setTranslationX(view, 0); 431235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase dispatchMoveFinished(item); 432235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase mPendingMoves.remove(item); 433235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 43493b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu } 435a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar endChangeAnimation(mPendingChanges, item); 436a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar if (mPendingRemovals.remove(item)) { 437a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar ViewCompat.setAlpha(view, 1); 43893b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu dispatchRemoveFinished(item); 43993b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu } 440a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar if (mPendingAdditions.remove(item)) { 44193b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu ViewCompat.setAlpha(view, 1); 44293b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu dispatchAddFinished(item); 443235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 444a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar 4450e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase for (int i = mChangesList.size() - 1; i >= 0; i--) { 4460e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ArrayList<ChangeInfo> changes = mChangesList.get(i); 4470e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase endChangeAnimation(changes, item); 4480e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase if (changes.isEmpty()) { 4490e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase mChangesList.remove(changes); 450ec93520d243d3eb3c6cddeaea7908d1b869bf367Dake Gu } 451ec93520d243d3eb3c6cddeaea7908d1b869bf367Dake Gu } 4520e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase for (int i = mMovesList.size() - 1; i >= 0; i--) { 4530e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ArrayList<MoveInfo> moves = mMovesList.get(i); 4540e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase for (int j = moves.size() - 1; j >= 0; j--) { 4550e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase MoveInfo moveInfo = moves.get(j); 4560e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase if (moveInfo.holder == item) { 4570e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ViewCompat.setTranslationY(view, 0); 4580e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ViewCompat.setTranslationX(view, 0); 4590e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase dispatchMoveFinished(item); 4600e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase moves.remove(j); 4610e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase if (moves.isEmpty()) { 4620e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase mMovesList.remove(moves); 4630e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase } 4640e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase break; 4650e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase } 4660e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase } 4670e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase } 4680e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase for (int i = mAdditionsList.size() - 1; i >= 0; i--) { 4690e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ArrayList<ViewHolder> additions = mAdditionsList.get(i); 4700e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase if (additions.remove(item)) { 4710e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ViewCompat.setAlpha(view, 1); 4720e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase dispatchAddFinished(item); 4730e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase if (additions.isEmpty()) { 4740e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase mAdditionsList.remove(additions); 4750e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase } 4760e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase } 477ec93520d243d3eb3c6cddeaea7908d1b869bf367Dake Gu } 478a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar 479a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar // animations should be ended by the cancel above. 480a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar if (mRemoveAnimations.remove(item) && DEBUG) { 481a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar throw new IllegalStateException("after animation is cancelled, item should not be in " 482a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar + "mRemoveAnimations list"); 483d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 484a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar 485a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar if (mAddAnimations.remove(item) && DEBUG) { 486a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar throw new IllegalStateException("after animation is cancelled, item should not be in " 487a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar + "mAddAnimations list"); 488d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 489a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar 490a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar if (mChangeAnimations.remove(item) && DEBUG) { 491a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar throw new IllegalStateException("after animation is cancelled, item should not be in " 492a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar + "mChangeAnimations list"); 493a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 494a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar 495a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar if (mMoveAnimations.remove(item) && DEBUG) { 496a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar throw new IllegalStateException("after animation is cancelled, item should not be in " 497a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar + "mMoveAnimations list"); 498235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 499d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase dispatchFinishedWhenDone(); 500d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 501d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 502d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 503d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public boolean isRunning() { 504e3d27c97eb0769997cd9d73baabffff70551efe0Yigit Boyar return (!mPendingAdditions.isEmpty() || 505047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar !mPendingChanges.isEmpty() || 506047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar !mPendingMoves.isEmpty() || 507047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar !mPendingRemovals.isEmpty() || 508e3d27c97eb0769997cd9d73baabffff70551efe0Yigit Boyar !mMoveAnimations.isEmpty() || 509d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase !mRemoveAnimations.isEmpty() || 510d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase !mAddAnimations.isEmpty() || 511235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase !mChangeAnimations.isEmpty() || 5120e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase !mMovesList.isEmpty() || 5130e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase !mAdditionsList.isEmpty() || 5140e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase !mChangesList.isEmpty()); 515d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 516d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 517d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase /** 518d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * Check the state of currently pending and running animations. If there are none 519d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * pending/running, call {@link #dispatchAnimationsFinished()} to notify any 520d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * listeners. 521d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase */ 522d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase private void dispatchFinishedWhenDone() { 523d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (!isRunning()) { 524d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase dispatchAnimationsFinished(); 525d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 526d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 527d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 528d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 529d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void endAnimations() { 53093b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu int count = mPendingMoves.size(); 53193b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu for (int i = count - 1; i >= 0; i--) { 53293b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu MoveInfo item = mPendingMoves.get(i); 53393b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu View view = item.holder.itemView; 53493b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu ViewCompat.setTranslationY(view, 0); 53593b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu ViewCompat.setTranslationX(view, 0); 53693b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu dispatchMoveFinished(item.holder); 537ec93520d243d3eb3c6cddeaea7908d1b869bf367Dake Gu mPendingMoves.remove(i); 53893b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu } 53993b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu count = mPendingRemovals.size(); 54093b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu for (int i = count - 1; i >= 0; i--) { 54193b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu ViewHolder item = mPendingRemovals.get(i); 54293b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu dispatchRemoveFinished(item); 543ec93520d243d3eb3c6cddeaea7908d1b869bf367Dake Gu mPendingRemovals.remove(i); 54493b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu } 54593b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu count = mPendingAdditions.size(); 54693b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu for (int i = count - 1; i >= 0; i--) { 54793b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu ViewHolder item = mPendingAdditions.get(i); 54893b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu View view = item.itemView; 54993b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu ViewCompat.setAlpha(view, 1); 55093b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu dispatchAddFinished(item); 551ec93520d243d3eb3c6cddeaea7908d1b869bf367Dake Gu mPendingAdditions.remove(i); 55293b78dd7cbfafbe669e124b38a8e3ccb38ad3079Dake Gu } 553235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase count = mPendingChanges.size(); 554235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase for (int i = count - 1; i >= 0; i--) { 555a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar endChangeAnimationIfNecessary(mPendingChanges.get(i)); 556235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 557a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar mPendingChanges.clear(); 558d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (!isRunning()) { 559d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase return; 560d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 561235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase 5620e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase int listCount = mMovesList.size(); 5630e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase for (int i = listCount - 1; i >= 0; i--) { 5640e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ArrayList<MoveInfo> moves = mMovesList.get(i); 5650e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase count = moves.size(); 5660e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase for (int j = count - 1; j >= 0; j--) { 5670e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase MoveInfo moveInfo = moves.get(j); 5680e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ViewHolder item = moveInfo.holder; 5690e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase View view = item.itemView; 5700e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ViewCompat.setTranslationY(view, 0); 5710e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ViewCompat.setTranslationX(view, 0); 5720e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase dispatchMoveFinished(moveInfo.holder); 5730e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase moves.remove(j); 5740e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase if (moves.isEmpty()) { 5750e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase mMovesList.remove(moves); 5760e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase } 5770e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase } 578235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 5790e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase listCount = mAdditionsList.size(); 5800e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase for (int i = listCount - 1; i >= 0; i--) { 5810e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ArrayList<ViewHolder> additions = mAdditionsList.get(i); 5820e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase count = additions.size(); 5830e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase for (int j = count - 1; j >= 0; j--) { 5840e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ViewHolder item = additions.get(j); 5850e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase View view = item.itemView; 5860e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ViewCompat.setAlpha(view, 1); 5870e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase dispatchAddFinished(item); 5880e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase additions.remove(j); 5890e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase if (additions.isEmpty()) { 5900e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase mAdditionsList.remove(additions); 5910e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase } 5920e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase } 593235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 5940e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase listCount = mChangesList.size(); 5950e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase for (int i = listCount - 1; i >= 0; i--) { 5960e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase ArrayList<ChangeInfo> changes = mChangesList.get(i); 5970e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase count = changes.size(); 5980e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase for (int j = count - 1; j >= 0; j--) { 5990e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase endChangeAnimationIfNecessary(changes.get(j)); 6000e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase if (changes.isEmpty()) { 6010e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase mChangesList.remove(changes); 6020e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase } 6030e0bfdb790fd9477e3531a1db92c3377057f83b7Chet Haase } 604235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase } 605235114f0ea0ae165e74a478f39bfc586392c53aaChet Haase 606a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar cancelAll(mRemoveAnimations); 607a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar cancelAll(mMoveAnimations); 608a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar cancelAll(mAddAnimations); 609a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar cancelAll(mChangeAnimations); 610ec93520d243d3eb3c6cddeaea7908d1b869bf367Dake Gu 611d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase dispatchAnimationsFinished(); 612d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 613d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 614a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar void cancelAll(List<ViewHolder> viewHolders) { 615a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar for (int i = viewHolders.size() - 1; i >= 0; i--) { 616a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar ViewCompat.animate(viewHolders.get(i).itemView).cancel(); 617a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 618a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar } 619a29fe6d4967a704799dc83d35ba80e426e9512cfYigit Boyar 620d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase private static class VpaListenerAdapter implements ViewPropertyAnimatorListener { 621d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 622d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void onAnimationStart(View view) {} 623d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 624d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 625d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void onAnimationEnd(View view) {} 626d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 627d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 628d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void onAnimationCancel(View view) {} 629d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase }; 630d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase} 631