DefaultItemAnimator.java revision d7d27e9ebe5c7325e67e1a8af265378bd2056cad
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; 19d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haaseimport android.support.v4.view.ViewPropertyAnimatorListener; 20d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haaseimport android.support.v7.widget.RecyclerView.ViewHolder; 21d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haaseimport android.view.View; 22d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 23d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haaseimport java.util.ArrayList; 24d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 25d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase/** 26d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * This implementation of {@link RecyclerView.ItemAnimator} provides basic 27d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * animations on remove, add, and move events that happen to the items in 28d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * a RecyclerView. RecyclerView uses a DefaultItemAnimator by default. 29d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * 30d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * @see RecyclerView#setItemAnimator(RecyclerView.ItemAnimator) 31d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase */ 32d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haasepublic class DefaultItemAnimator extends RecyclerView.ItemAnimator { 33d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 34d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase private ArrayList<ViewHolder> mPendingRemovals = new ArrayList<ViewHolder>(); 35d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase private ArrayList<ViewHolder> mPendingAdditions = new ArrayList<ViewHolder>(); 36d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase private ArrayList<MoveInfo> mPendingMoves = new ArrayList<MoveInfo>(); 37d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 38d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase private ArrayList<ViewHolder> mAdditions = new ArrayList<ViewHolder>(); 39d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase private ArrayList<MoveInfo> mMoves = new ArrayList<MoveInfo>(); 40d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 41d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase private ArrayList<ViewHolder> mAddAnimations = new ArrayList<ViewHolder>(); 42d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase private ArrayList<ViewHolder> mMoveAnimations = new ArrayList<ViewHolder>(); 43d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase private ArrayList<ViewHolder> mRemoveAnimations = new ArrayList<ViewHolder>(); 44d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 45d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase private static class MoveInfo { 46d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public ViewHolder holder; 47d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public int fromX, fromY, toX, toY; 48d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 49d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase private MoveInfo(ViewHolder holder, int fromX, int fromY, int toX, int toY) { 50d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase this.holder = holder; 51d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase this.fromX = fromX; 52d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase this.fromY = fromY; 53d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase this.toX = toX; 54d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase this.toY = toY; 55d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 56d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 57d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 58d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 59d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void runPendingAnimations() { 60d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase boolean removalsPending = !mPendingRemovals.isEmpty(); 61d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase boolean movesPending = !mPendingMoves.isEmpty(); 62d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase boolean additionsPending = !mPendingAdditions.isEmpty(); 63d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (!removalsPending && !movesPending && !additionsPending) { 64d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase // nothing to animate 65d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase return; 66d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 67d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase // First, remove stuff 68d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase for (ViewHolder holder : mPendingRemovals) { 69d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase animateRemoveImpl(holder); 70d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 71d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mPendingRemovals.clear(); 72d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase // Next, move stuff 73d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (movesPending) { 74d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mMoves.addAll(mPendingMoves); 75d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mPendingMoves.clear(); 76d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase Runnable mover = new Runnable() { 77d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 78d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void run() { 79d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase for (MoveInfo moveInfo : mMoves) { 80d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase animateMoveImpl(moveInfo.holder, moveInfo.fromX, moveInfo.fromY, 81d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase moveInfo.toX, moveInfo.toY); 82d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 83d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mMoves.clear(); 84d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 85d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase }; 86d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (removalsPending) { 87d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase View view = mMoves.get(0).holder.itemView; 88d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.postOnAnimationDelayed(view, mover, getRemoveDuration()); 89d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } else { 90d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mover.run(); 91d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 92d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 93d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase // Next, add stuff 94d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (additionsPending) { 95d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mAdditions.addAll(mPendingAdditions); 96d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mPendingAdditions.clear(); 97d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase Runnable adder = new Runnable() { 98d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void run() { 99d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase for (ViewHolder holder : mAdditions) { 100d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase animateAddImpl(holder); 101d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 102d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mAdditions.clear(); 103d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 104d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase }; 105d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (removalsPending || movesPending) { 106d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase View view = mAdditions.get(0).itemView; 107d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.postOnAnimationDelayed(view, adder, 108d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase (removalsPending ? getRemoveDuration() : 0) + 109d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase (movesPending ? getMoveDuration() : 0)); 110d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } else { 111d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase adder.run(); 112d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 113d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 114d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 115d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 116d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 117d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public boolean animateRemove(final ViewHolder holder) { 118d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mPendingRemovals.add(holder); 119d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase return true; 120d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 121d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 122d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase private void animateRemoveImpl(final ViewHolder holder) { 123d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase final View view = holder.itemView; 124d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.animate(view).cancel(); 125d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.animate(view).setDuration(getRemoveDuration()). 126d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase alpha(0).setListener(new VpaListenerAdapter() { 127d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 128d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void onAnimationEnd(View view) { 129d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.setAlpha(view, 1); 130d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase dispatchRemoveFinished(holder); 131d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mRemoveAnimations.remove(holder); 132d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase dispatchFinishedWhenDone(); 133d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 134d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase }).start(); 135d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mRemoveAnimations.add(holder); 136d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 137d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 138d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 139d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public boolean animateAdd(final ViewHolder holder) { 140d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.setAlpha(holder.itemView, 0); 141d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mPendingAdditions.add(holder); 142d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase return true; 143d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 144d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 145d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase private void animateAddImpl(final ViewHolder holder) { 146d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase final View view = holder.itemView; 147d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.animate(view).cancel(); 148d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.animate(view).alpha(1).setDuration(getAddDuration()). 149d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase setListener(new VpaListenerAdapter() { 150d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 151d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void onAnimationCancel(View view) { 152d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.setAlpha(view, 1); 153d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 154d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 155d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void onAnimationEnd(View view) { 156d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase dispatchAddFinished(holder); 157d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mAddAnimations.remove(holder); 158d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase dispatchFinishedWhenDone(); 159d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 160d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase }).start(); 161d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mAddAnimations.add(holder); 162d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 163d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 164d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 165d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public boolean animateMove(final ViewHolder holder, int fromX, int fromY, 166d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase int toX, int toY) { 167d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase final View view = holder.itemView; 168d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase int deltaX = toX - fromX; 169d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase int deltaY = toY - fromY; 170d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (deltaX == 0 && deltaY == 0) { 171d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase dispatchMoveFinished(holder); 172d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase return false; 173d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 174d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (deltaX != 0) { 175d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.setTranslationX(view, -deltaX); 176d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 177d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (deltaY != 0) { 178d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.setTranslationY(view, -deltaY); 179d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 180d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mPendingMoves.add(new MoveInfo(holder, fromX, fromY, toX, toY)); 181d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase return true; 182d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 183d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 184d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase private void animateMoveImpl(final ViewHolder holder, int fromX, int fromY, int toX, int toY) { 185d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase final View view = holder.itemView; 186d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase final int deltaX = toX - fromX; 187d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase final int deltaY = toY - fromY; 188d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.animate(view).cancel(); 189d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (deltaX != 0) { 190d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.animate(view).translationX(0); 191d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 192d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (deltaY != 0) { 193d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.animate(view).translationY(0); 194d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 195d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase // TODO: make EndActions end listeners instead, since end actions aren't called when 196d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase // vpas are canceled (and can't end them. why?) 197d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase // need listener functionality in VPACompat for this. Ick. 198d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.animate(view).setDuration(getMoveDuration()).setListener(new VpaListenerAdapter() { 199d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 200d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void onAnimationCancel(View view) { 201d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (deltaX != 0) { 202d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.setTranslationX(view, 0); 203d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 204d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (deltaY != 0) { 205d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.setTranslationY(view, 0); 206d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 207d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 208d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 209d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void onAnimationEnd(View view) { 210d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase dispatchMoveFinished(holder); 211d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mMoveAnimations.remove(holder); 212d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase dispatchFinishedWhenDone(); 213d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 214d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase }).start(); 215d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mMoveAnimations.add(holder); 216d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 217d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 218d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 219d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void endAnimation(ViewHolder item) { 220d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase final View view = item.itemView; 221d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.animate(view).cancel(); 222d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (mMoveAnimations.contains(item)) { 223d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.setTranslationY(view, 0); 224d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.setTranslationX(view, 0); 225d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase dispatchMoveFinished(item); 226d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mMoveAnimations.remove(item); 227d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 228d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (mRemoveAnimations.contains(item)) { 229d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.setAlpha(view, 1); 230d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase dispatchRemoveFinished(item); 231d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mRemoveAnimations.remove(item); 232d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 233d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (mAddAnimations.contains(item)) { 234d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.setAlpha(view, 1); 235d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase dispatchAddFinished(item); 236d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mAddAnimations.remove(item); 237d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 238d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase dispatchFinishedWhenDone(); 239d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 240d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 241d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 242d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public boolean isRunning() { 243d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase return (!mMoveAnimations.isEmpty() || 244d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase !mRemoveAnimations.isEmpty() || 245d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase !mAddAnimations.isEmpty() || 246d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase !mMoves.isEmpty() || 247d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase !mAdditions.isEmpty()); 248d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 249d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 250d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase /** 251d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * Check the state of currently pending and running animations. If there are none 252d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * pending/running, call {@link #dispatchAnimationsFinished()} to notify any 253d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * listeners. 254d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase */ 255d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase private void dispatchFinishedWhenDone() { 256d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (!isRunning()) { 257d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase dispatchAnimationsFinished(); 258d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 259d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 260d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 261d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 262d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void endAnimations() { 263d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (!isRunning()) { 264d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase return; 265d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 266d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase int count = mMoveAnimations.size(); 267d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase for (int i = count - 1; i >= 0; i--) { 268d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewHolder item = mMoveAnimations.get(i); 269d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase View view = item.itemView; 270d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.animate(view).cancel(); 271d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.setTranslationY(view, 0); 272d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.setTranslationX(view, 0); 273d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase dispatchMoveFinished(item); 274d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mMoveAnimations.remove(item); 275d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 276d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase count = mRemoveAnimations.size(); 277d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase for (int i = count - 1; i >= 0; i--) { 278d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewHolder item = mRemoveAnimations.get(i); 279d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase View view = item.itemView; 280d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.animate(view).cancel(); 281d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.setAlpha(view, 1); 282d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase dispatchRemoveFinished(item); 283d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mRemoveAnimations.remove(item); 284d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 285d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase count = mAddAnimations.size(); 286d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase for (int i = count - 1; i >= 0; i--) { 287d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewHolder item = mAddAnimations.get(i); 288d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase View view = item.itemView; 289d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.animate(view).cancel(); 290d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewCompat.setAlpha(view, 1); 291d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase dispatchAddFinished(item); 292d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mAddAnimations.remove(item); 293d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 294d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mMoves.clear(); 295d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mAdditions.clear(); 296d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase dispatchAnimationsFinished(); 297d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 298d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 299d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase private static class VpaListenerAdapter implements ViewPropertyAnimatorListener { 300d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 301d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void onAnimationStart(View view) {} 302d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 303d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 304d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void onAnimationEnd(View view) {} 305d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 306d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 307d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void onAnimationCancel(View view) {} 308d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase }; 309d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase} 310