diff options
author | Yuzhou <jiayuzhou@google.com> | 2018-05-18 13:07:54 -0700 |
---|---|---|
committer | Yuzhou <jiayuzhou@google.com> | 2018-05-23 16:06:00 -0700 |
commit | f76e41153fb5c0dcdda456409b3c3709469df82e (patch) | |
tree | ec12b16975a4883f9dc967cd83409401757a89a7 | |
parent | e08e94d68133a37e3aa751b4eb75d14090752055 (diff) | |
download | platform_packages_apps_Car_Dialer-f76e41153fb5c0dcdda456409b3c3709469df82e.tar.gz platform_packages_apps_Car_Dialer-f76e41153fb5c0dcdda456409b3c3709469df82e.tar.bz2 platform_packages_apps_Car_Dialer-f76e41153fb5c0dcdda456409b3c3709469df82e.zip |
DO NOT MERGE Refresh relative time of the recent call card every minute.
Test: build and load the app.
Bug: 77980012.
Change-Id: I9bdbf2d4e6154eeda2fb5fb2668ab5b10159b6c2
-rw-r--r-- | res/layout/call_log_last_call_item_card.xml | 29 | ||||
-rw-r--r-- | src/com/android/car/dialer/StrequentsAdapter.java | 65 | ||||
-rw-r--r-- | src/com/android/car/dialer/StrequentsFragment.java | 2 | ||||
-rw-r--r-- | src/com/android/car/dialer/StrequentsItemAnimator.java | 637 |
4 files changed, 45 insertions, 688 deletions
diff --git a/res/layout/call_log_last_call_item_card.xml b/res/layout/call_log_last_call_item_card.xml deleted file mode 100644 index f836fff0..00000000 --- a/res/layout/call_log_last_call_item_card.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2015 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<android.support.v7.widget.CardView - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" - android:id="@+id/call_log_card" - android:foreground="@drawable/dialer_ripple_background" - android:layout_gravity="center" - android:layout_width="match_parent" - android:layout_height="@dimen/call_log_item_height" - app:cardBackgroundColor="@color/phone_theme" - app:cardCornerRadius="@dimen/favorite_card_corner_radius" - app:cardElevation="@dimen/car_action_bar_elevation"> - - <include layout="@layout/call_log_list_item_card_base"/> -</android.support.v7.widget.CardView> diff --git a/src/com/android/car/dialer/StrequentsAdapter.java b/src/com/android/car/dialer/StrequentsAdapter.java index 8d14019a..da07b236 100644 --- a/src/com/android/car/dialer/StrequentsAdapter.java +++ b/src/com/android/car/dialer/StrequentsAdapter.java @@ -19,6 +19,7 @@ import android.content.ContentResolver; import android.content.Context; import android.database.Cursor; import android.graphics.PorterDuff; +import android.os.Handler; import android.provider.CallLog; import android.support.annotation.Nullable; import android.support.v7.widget.RecyclerView; @@ -44,8 +45,8 @@ import java.util.List; * It handles two types of contacts: * <p> * <ul> - * <li>Strequent contacts (starred and/or frequent) - * <li>Last call contact + * <li>Strequent contacts (starred and/or frequent) + * <li>Last call contact * </ul> */ public class StrequentsAdapter extends RecyclerView.Adapter<CallLogViewHolder> @@ -54,12 +55,16 @@ public class StrequentsAdapter extends RecyclerView.Adapter<CallLogViewHolder> private static final int VIEW_TYPE_EMPTY = 0; private static final int VIEW_TYPE_LASTCALL = 1; private static final int VIEW_TYPE_STREQUENT = 2; + private static final long LAST_CALL_REFRESH_INTERVAL_MILLIS = 60 * 1000L; private final Context mContext; private final UiCallManager mUiCallManager; private List<ContactEntry> mData; + private Handler mMainThreadHandler = new Handler(); private LastCallData mLastCallData; + private Cursor mLastCallCursor; + private LastCallPeriodicalUpdater mLastCallPeriodicalUpdater = new LastCallPeriodicalUpdater(); private final ContentResolver mContentResolver; @@ -85,7 +90,15 @@ public class StrequentsAdapter extends RecyclerView.Adapter<CallLogViewHolder> } public void setLastCallCursor(@Nullable Cursor cursor) { + mLastCallCursor = cursor; mLastCallData = convertLastCallCursor(cursor); + if (cursor != null) { + mMainThreadHandler.postDelayed(mLastCallPeriodicalUpdater, + LAST_CALL_REFRESH_INTERVAL_MILLIS); + } else { + mMainThreadHandler.removeCallbacks(mLastCallPeriodicalUpdater); + } + notifyDataSetChanged(); } @@ -139,16 +152,12 @@ public class StrequentsAdapter extends RecyclerView.Adapter<CallLogViewHolder> public CallLogViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view; switch (viewType) { - case VIEW_TYPE_LASTCALL: - view = LayoutInflater.from(parent.getContext()) - .inflate(R.layout.call_log_last_call_item_card, parent, false); - return new CallLogViewHolder(view); - case VIEW_TYPE_EMPTY: view = LayoutInflater.from(parent.getContext()) .inflate(R.layout.call_log_list_item_empty, parent, false); return new CallLogViewHolder(view); + case VIEW_TYPE_LASTCALL: case VIEW_TYPE_STREQUENT: default: view = LayoutInflater.from(parent.getContext()) @@ -236,22 +245,26 @@ public class StrequentsAdapter extends RecyclerView.Adapter<CallLogViewHolder> String primaryText = mLastCallData.getPrimaryText(); String number = mLastCallData.getNumber(); - viewHolder.title.setText(mLastCallData.getPrimaryText()); - viewHolder.text.setText(mLastCallData.getSecondaryText()); - viewHolder.itemView.setTag(number); - viewHolder.callTypeIconsView.clear(); - viewHolder.callTypeIconsView.setVisibility(View.VISIBLE); - - // mHasFirstItem is true only in main screen, or else it is in drawer, then we need to add - // call type icons for call history items. - viewHolder.smallIcon.setVisibility(View.GONE); - int[] callTypes = mLastCallData.getCallTypes(); - int icons = Math.min(callTypes.length, CallTypeIconsView.MAX_CALL_TYPE_ICONS); - for (int i = 0; i < icons; i++) { - viewHolder.callTypeIconsView.add(callTypes[i]); + if (!number.equals(viewHolder.itemView.getTag())) { + viewHolder.title.setText(mLastCallData.getPrimaryText()); + viewHolder.itemView.setTag(number); + viewHolder.callTypeIconsView.clear(); + viewHolder.callTypeIconsView.setVisibility(View.VISIBLE); + + // mHasFirstItem is true only in main screen, or else it is in drawer, then we need + // to add + // call type icons for call history items. + viewHolder.smallIcon.setVisibility(View.GONE); + int[] callTypes = mLastCallData.getCallTypes(); + int icons = Math.min(callTypes.length, CallTypeIconsView.MAX_CALL_TYPE_ICONS); + for (int i = 0; i < icons; i++) { + viewHolder.callTypeIconsView.add(callTypes[i]); + } + + TelecomUtils.setContactBitmapAsync(mContext, viewHolder.icon, primaryText, number); } - TelecomUtils.setContactBitmapAsync(mContext, viewHolder.icon, primaryText, number); + viewHolder.text.setText(mLastCallData.getSecondaryText()); } /** @@ -395,4 +408,14 @@ public class StrequentsAdapter extends RecyclerView.Adapter<CallLogViewHolder> return mCallTypes; } } + + private class LastCallPeriodicalUpdater implements Runnable { + + @Override + public void run() { + mLastCallData = convertLastCallCursor(mLastCallCursor); + notifyItemChanged(0); + mMainThreadHandler.postDelayed(this, LAST_CALL_REFRESH_INTERVAL_MILLIS); + } + } } diff --git a/src/com/android/car/dialer/StrequentsFragment.java b/src/com/android/car/dialer/StrequentsFragment.java index 6e37c38c..7bd8d4a5 100644 --- a/src/com/android/car/dialer/StrequentsFragment.java +++ b/src/com/android/car/dialer/StrequentsFragment.java @@ -141,7 +141,7 @@ public class StrequentsFragment extends Fragment { Log.d(TAG, "setItemAnimator"); } - mListView.getRecyclerView().setItemAnimator(new StrequentsItemAnimator()); + mListView.getRecyclerView().setItemAnimator(null); return view; } diff --git a/src/com/android/car/dialer/StrequentsItemAnimator.java b/src/com/android/car/dialer/StrequentsItemAnimator.java deleted file mode 100644 index 23e8b1d8..00000000 --- a/src/com/android/car/dialer/StrequentsItemAnimator.java +++ /dev/null @@ -1,637 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.car.dialer; - -import android.support.v4.view.ViewCompat; -import android.support.v4.view.ViewPropertyAnimatorCompat; -import android.support.v4.view.ViewPropertyAnimatorListener; -import android.support.v7.widget.RecyclerView.ViewHolder; -import android.support.v7.widget.SimpleItemAnimator; -import android.view.View; - -import java.util.ArrayList; -import java.util.List; - -/** - * Branch from {@link android.support.v7.widget.DefaultItemAnimator} with changes on - * {@link #animateAddImpl}, {@link #animateAdd} and {@link #animateRemoveImpl}. - */ -public class StrequentsItemAnimator extends SimpleItemAnimator { - private static final boolean DEBUG = false; - - private ArrayList<ViewHolder> mPendingRemovals = new ArrayList<>(); - private ArrayList<ViewHolder> mPendingAdditions = new ArrayList<>(); - private ArrayList<MoveInfo> mPendingMoves = new ArrayList<>(); - private ArrayList<ChangeInfo> mPendingChanges = new ArrayList<>(); - - private ArrayList<ArrayList<ViewHolder>> mAdditionsList = new ArrayList<>(); - private ArrayList<ArrayList<MoveInfo>> mMovesList = new ArrayList<>(); - private ArrayList<ArrayList<ChangeInfo>> mChangesList = new ArrayList<>(); - - private ArrayList<ViewHolder> mAddAnimations = new ArrayList<>(); - private ArrayList<ViewHolder> mMoveAnimations = new ArrayList<>(); - private ArrayList<ViewHolder> mRemoveAnimations = new ArrayList<>(); - private ArrayList<ViewHolder> mChangeAnimations = new ArrayList<>(); - - private static class MoveInfo { - public ViewHolder holder; - public int fromX, fromY, toX, toY; - - private MoveInfo(ViewHolder holder, int fromX, int fromY, int toX, int toY) { - this.holder = holder; - this.fromX = fromX; - this.fromY = fromY; - this.toX = toX; - this.toY = toY; - } - } - - private static class ChangeInfo { - public ViewHolder oldHolder, newHolder; - public int fromX, fromY, toX, toY; - private ChangeInfo(ViewHolder oldHolder, ViewHolder newHolder) { - this.oldHolder = oldHolder; - this.newHolder = newHolder; - } - - private ChangeInfo(ViewHolder oldHolder, ViewHolder newHolder, - int fromX, int fromY, int toX, int toY) { - this(oldHolder, newHolder); - this.fromX = fromX; - this.fromY = fromY; - this.toX = toX; - this.toY = toY; - } - - @Override - public String toString() { - return "ChangeInfo{" + - "oldHolder=" + oldHolder + - ", newHolder=" + newHolder + - ", fromX=" + fromX + - ", fromY=" + fromY + - ", toX=" + toX + - ", toY=" + toY + - '}'; - } - } - - @Override - public void runPendingAnimations() { - boolean removalsPending = !mPendingRemovals.isEmpty(); - boolean movesPending = !mPendingMoves.isEmpty(); - boolean changesPending = !mPendingChanges.isEmpty(); - boolean additionsPending = !mPendingAdditions.isEmpty(); - if (!removalsPending && !movesPending && !additionsPending && !changesPending) { - // nothing to animate - return; - } - // First, remove stuff - for (ViewHolder holder : mPendingRemovals) { - animateRemoveImpl(holder); - } - mPendingRemovals.clear(); - // Next, move stuff - if (movesPending) { - final ArrayList<MoveInfo> moves = new ArrayList<MoveInfo>(); - moves.addAll(mPendingMoves); - mMovesList.add(moves); - mPendingMoves.clear(); - Runnable mover = new Runnable() { - @Override - public void run() { - for (MoveInfo moveInfo : moves) { - animateMoveImpl(moveInfo.holder, moveInfo.fromX, moveInfo.fromY, - moveInfo.toX, moveInfo.toY); - } - moves.clear(); - mMovesList.remove(moves); - } - }; - if (removalsPending) { - View view = moves.get(0).holder.itemView; - ViewCompat.postOnAnimationDelayed(view, mover, getRemoveDuration()); - } else { - mover.run(); - } - } - // Next, change stuff, to run in parallel with move animations - if (changesPending) { - final ArrayList<ChangeInfo> changes = new ArrayList<ChangeInfo>(); - changes.addAll(mPendingChanges); - mChangesList.add(changes); - mPendingChanges.clear(); - Runnable changer = new Runnable() { - @Override - public void run() { - for (ChangeInfo change : changes) { - animateChangeImpl(change); - } - changes.clear(); - mChangesList.remove(changes); - } - }; - if (removalsPending) { - ViewHolder holder = changes.get(0).oldHolder; - ViewCompat.postOnAnimationDelayed(holder.itemView, changer, getRemoveDuration()); - } else { - changer.run(); - } - } - // Next, add stuff - if (additionsPending) { - final ArrayList<ViewHolder> additions = new ArrayList<ViewHolder>(); - additions.addAll(mPendingAdditions); - mAdditionsList.add(additions); - mPendingAdditions.clear(); - Runnable adder = new Runnable() { - public void run() { - for (ViewHolder holder : additions) { - animateAddImpl(holder); - } - additions.clear(); - mAdditionsList.remove(additions); - } - }; - if (removalsPending || movesPending || changesPending) { - long removeDuration = removalsPending ? getRemoveDuration() : 0; - long moveDuration = movesPending ? getMoveDuration() : 0; - long changeDuration = changesPending ? getChangeDuration() : 0; - long totalDelay = removeDuration + Math.max(moveDuration, changeDuration); - View view = additions.get(0).itemView; - ViewCompat.postOnAnimationDelayed(view, adder, totalDelay); - } else { - adder.run(); - } - } - } - - @Override - public boolean animateRemove(final ViewHolder holder) { - endAnimation(holder); - mPendingRemovals.add(holder); - return true; - } - - private void animateRemoveImpl(final ViewHolder holder) { - // Animate on the content if it's CallLogViewHolder. - final View view = holder instanceof CallLogViewHolder ? - ((CallLogViewHolder) holder).container : holder.itemView; - final ViewPropertyAnimatorCompat animation = ViewCompat.animate(view); - mRemoveAnimations.add(holder); - animation.setDuration(getRemoveDuration()) - .alpha(0).setListener(new VpaListenerAdapter() { - @Override - public void onAnimationStart(View view) { - dispatchRemoveStarting(holder); - } - - @Override - public void onAnimationEnd(View view) { - animation.setListener(null); - ViewCompat.setAlpha(view, 1); - dispatchRemoveFinished(holder); - mRemoveAnimations.remove(holder); - dispatchFinishedWhenDone(); - } - }).start(); - } - - @Override - public boolean animateAdd(final ViewHolder holder) { - endAnimation(holder); - // for CallLogViewHolder, instead of fade out the whole card, fade out only the content. - if (holder instanceof CallLogViewHolder) { - ViewCompat.setAlpha(((CallLogViewHolder) holder).container, 0); - } else { - ViewCompat.setAlpha(holder.itemView, 0); - } - mPendingAdditions.add(holder); - return true; - } - - private void animateAddImpl(final ViewHolder holder) { - // Animate on the content if it's CallLogViewHolder. - final View view = holder instanceof CallLogViewHolder ? - ((CallLogViewHolder) holder).container : holder.itemView; - final ViewPropertyAnimatorCompat animation = ViewCompat.animate(view); - mAddAnimations.add(holder); - animation.alpha(1).setDuration(getAddDuration()). - setListener(new VpaListenerAdapter() { - @Override - public void onAnimationStart(View view) { - dispatchAddStarting(holder); - } - @Override - public void onAnimationCancel(View view) { - ViewCompat.setAlpha(view, 1); - } - - @Override - public void onAnimationEnd(View view) { - animation.setListener(null); - dispatchAddFinished(holder); - mAddAnimations.remove(holder); - dispatchFinishedWhenDone(); - } - }).start(); - } - - @Override - public boolean animateMove(final ViewHolder holder, int fromX, int fromY, - int toX, int toY) { - final View view = holder.itemView; - fromX += ViewCompat.getTranslationX(holder.itemView); - fromY += ViewCompat.getTranslationY(holder.itemView); - endAnimation(holder); - int deltaX = toX - fromX; - int deltaY = toY - fromY; - if (deltaX == 0 && deltaY == 0) { - dispatchMoveFinished(holder); - return false; - } - if (deltaX != 0) { - ViewCompat.setTranslationX(view, -deltaX); - } - if (deltaY != 0) { - ViewCompat.setTranslationY(view, -deltaY); - } - mPendingMoves.add(new MoveInfo(holder, fromX, fromY, toX, toY)); - return true; - } - - private void animateMoveImpl(final ViewHolder holder, int fromX, int fromY, int toX, int toY) { - final View view = holder.itemView; - final int deltaX = toX - fromX; - final int deltaY = toY - fromY; - if (deltaX != 0) { - ViewCompat.animate(view).translationX(0); - } - if (deltaY != 0) { - ViewCompat.animate(view).translationY(0); - } - // TODO: make EndActions end listeners instead, since end actions aren't called when - // vpas are canceled (and can't end them. why?) - // need listener functionality in VPACompat for this. Ick. - final ViewPropertyAnimatorCompat animation = ViewCompat.animate(view); - mMoveAnimations.add(holder); - animation.setDuration(getMoveDuration()).setListener(new VpaListenerAdapter() { - @Override - public void onAnimationStart(View view) { - dispatchMoveStarting(holder); - } - @Override - public void onAnimationCancel(View view) { - if (deltaX != 0) { - ViewCompat.setTranslationX(view, 0); - } - if (deltaY != 0) { - ViewCompat.setTranslationY(view, 0); - } - } - @Override - public void onAnimationEnd(View view) { - animation.setListener(null); - dispatchMoveFinished(holder); - mMoveAnimations.remove(holder); - dispatchFinishedWhenDone(); - } - }).start(); - } - - @Override - public boolean animateChange(ViewHolder oldHolder, ViewHolder newHolder, - int fromX, int fromY, int toX, int toY) { - final float prevTranslationX = ViewCompat.getTranslationX(oldHolder.itemView); - final float prevTranslationY = ViewCompat.getTranslationY(oldHolder.itemView); - final float prevAlpha = ViewCompat.getAlpha(oldHolder.itemView); - endAnimation(oldHolder); - int deltaX = (int) (toX - fromX - prevTranslationX); - int deltaY = (int) (toY - fromY - prevTranslationY); - // recover prev translation state after ending animation - ViewCompat.setTranslationX(oldHolder.itemView, prevTranslationX); - ViewCompat.setTranslationY(oldHolder.itemView, prevTranslationY); - ViewCompat.setAlpha(oldHolder.itemView, prevAlpha); - if (newHolder != null && newHolder.itemView != null) { - // carry over translation values - endAnimation(newHolder); - ViewCompat.setTranslationX(newHolder.itemView, -deltaX); - ViewCompat.setTranslationY(newHolder.itemView, -deltaY); - ViewCompat.setAlpha(newHolder.itemView, 0); - } - mPendingChanges.add(new ChangeInfo(oldHolder, newHolder, fromX, fromY, toX, toY)); - return true; - } - - private void animateChangeImpl(final ChangeInfo changeInfo) { - final ViewHolder holder = changeInfo.oldHolder; - final View view = holder == null ? null : holder.itemView; - final ViewHolder newHolder = changeInfo.newHolder; - final View newView = newHolder != null ? newHolder.itemView : null; - if (view != null) { - final ViewPropertyAnimatorCompat oldViewAnim = ViewCompat.animate(view).setDuration( - getChangeDuration()); - mChangeAnimations.add(changeInfo.oldHolder); - oldViewAnim.translationX(changeInfo.toX - changeInfo.fromX); - oldViewAnim.translationY(changeInfo.toY - changeInfo.fromY); - oldViewAnim.alpha(0).setListener(new VpaListenerAdapter() { - @Override - public void onAnimationStart(View view) { - dispatchChangeStarting(changeInfo.oldHolder, true); - } - - @Override - public void onAnimationEnd(View view) { - oldViewAnim.setListener(null); - ViewCompat.setAlpha(view, 1); - ViewCompat.setTranslationX(view, 0); - ViewCompat.setTranslationY(view, 0); - dispatchChangeFinished(changeInfo.oldHolder, true); - mChangeAnimations.remove(changeInfo.oldHolder); - dispatchFinishedWhenDone(); - } - }).start(); - } - if (newView != null) { - final ViewPropertyAnimatorCompat newViewAnimation = ViewCompat.animate(newView); - mChangeAnimations.add(changeInfo.newHolder); - newViewAnimation.translationX(0).translationY(0).setDuration(getChangeDuration()). - alpha(1).setListener(new VpaListenerAdapter() { - @Override - public void onAnimationStart(View view) { - dispatchChangeStarting(changeInfo.newHolder, false); - } - @Override - public void onAnimationEnd(View view) { - newViewAnimation.setListener(null); - ViewCompat.setAlpha(newView, 1); - ViewCompat.setTranslationX(newView, 0); - ViewCompat.setTranslationY(newView, 0); - dispatchChangeFinished(changeInfo.newHolder, false); - mChangeAnimations.remove(changeInfo.newHolder); - dispatchFinishedWhenDone(); - } - }).start(); - } - } - - private void endChangeAnimation(List<ChangeInfo> infoList, ViewHolder item) { - for (int i = infoList.size() - 1; i >= 0; i--) { - ChangeInfo changeInfo = infoList.get(i); - if (endChangeAnimationIfNecessary(changeInfo, item)) { - if (changeInfo.oldHolder == null && changeInfo.newHolder == null) { - infoList.remove(changeInfo); - } - } - } - } - - private void endChangeAnimationIfNecessary(ChangeInfo changeInfo) { - if (changeInfo.oldHolder != null) { - endChangeAnimationIfNecessary(changeInfo, changeInfo.oldHolder); - } - if (changeInfo.newHolder != null) { - endChangeAnimationIfNecessary(changeInfo, changeInfo.newHolder); - } - } - private boolean endChangeAnimationIfNecessary(ChangeInfo changeInfo, ViewHolder item) { - boolean oldItem = false; - if (changeInfo.newHolder == item) { - changeInfo.newHolder = null; - } else if (changeInfo.oldHolder == item) { - changeInfo.oldHolder = null; - oldItem = true; - } else { - return false; - } - ViewCompat.setAlpha(item.itemView, 1); - ViewCompat.setTranslationX(item.itemView, 0); - ViewCompat.setTranslationY(item.itemView, 0); - dispatchChangeFinished(item, oldItem); - return true; - } - - @Override - public void endAnimation(ViewHolder item) { - final View view = item.itemView; - // this will trigger end callback which should set properties to their target values. - ViewCompat.animate(view).cancel(); - // TODO if some other animations are chained to end, how do we cancel them as well? - for (int i = mPendingMoves.size() - 1; i >= 0; i--) { - MoveInfo moveInfo = mPendingMoves.get(i); - if (moveInfo.holder == item) { - ViewCompat.setTranslationY(view, 0); - ViewCompat.setTranslationX(view, 0); - dispatchMoveFinished(item); - mPendingMoves.remove(i); - } - } - endChangeAnimation(mPendingChanges, item); - if (mPendingRemovals.remove(item)) { - ViewCompat.setAlpha(view, 1); - dispatchRemoveFinished(item); - } - if (mPendingAdditions.remove(item)) { - ViewCompat.setAlpha(view, 1); - dispatchAddFinished(item); - } - - for (int i = mChangesList.size() - 1; i >= 0; i--) { - ArrayList<ChangeInfo> changes = mChangesList.get(i); - endChangeAnimation(changes, item); - if (changes.isEmpty()) { - mChangesList.remove(i); - } - } - for (int i = mMovesList.size() - 1; i >= 0; i--) { - ArrayList<MoveInfo> moves = mMovesList.get(i); - for (int j = moves.size() - 1; j >= 0; j--) { - MoveInfo moveInfo = moves.get(j); - if (moveInfo.holder == item) { - ViewCompat.setTranslationY(view, 0); - ViewCompat.setTranslationX(view, 0); - dispatchMoveFinished(item); - moves.remove(j); - if (moves.isEmpty()) { - mMovesList.remove(i); - } - break; - } - } - } - for (int i = mAdditionsList.size() - 1; i >= 0; i--) { - ArrayList<ViewHolder> additions = mAdditionsList.get(i); - if (additions.remove(item)) { - ViewCompat.setAlpha(view, 1); - dispatchAddFinished(item); - if (additions.isEmpty()) { - mAdditionsList.remove(i); - } - } - } - - // animations should be ended by the cancel above. - if (mRemoveAnimations.remove(item) && DEBUG) { - throw new IllegalStateException("after animation is cancelled, item should not be in " - + "mRemoveAnimations list"); - } - - if (mAddAnimations.remove(item) && DEBUG) { - throw new IllegalStateException("after animation is cancelled, item should not be in " - + "mAddAnimations list"); - } - - if (mChangeAnimations.remove(item) && DEBUG) { - throw new IllegalStateException("after animation is cancelled, item should not be in " - + "mChangeAnimations list"); - } - - if (mMoveAnimations.remove(item) && DEBUG) { - throw new IllegalStateException("after animation is cancelled, item should not be in " - + "mMoveAnimations list"); - } - dispatchFinishedWhenDone(); - } - - @Override - public boolean isRunning() { - return (!mPendingAdditions.isEmpty() || - !mPendingChanges.isEmpty() || - !mPendingMoves.isEmpty() || - !mPendingRemovals.isEmpty() || - !mMoveAnimations.isEmpty() || - !mRemoveAnimations.isEmpty() || - !mAddAnimations.isEmpty() || - !mChangeAnimations.isEmpty() || - !mMovesList.isEmpty() || - !mAdditionsList.isEmpty() || - !mChangesList.isEmpty()); - } - - /** - * Check the state of currently pending and running animations. If there are none - * pending/running, call {@link #dispatchAnimationsFinished()} to notify any - * listeners. - */ - private void dispatchFinishedWhenDone() { - if (!isRunning()) { - dispatchAnimationsFinished(); - } - } - - @Override - public void endAnimations() { - int count = mPendingMoves.size(); - for (int i = count - 1; i >= 0; i--) { - MoveInfo item = mPendingMoves.get(i); - View view = item.holder.itemView; - ViewCompat.setTranslationY(view, 0); - ViewCompat.setTranslationX(view, 0); - dispatchMoveFinished(item.holder); - mPendingMoves.remove(i); - } - count = mPendingRemovals.size(); - for (int i = count - 1; i >= 0; i--) { - ViewHolder item = mPendingRemovals.get(i); - dispatchRemoveFinished(item); - mPendingRemovals.remove(i); - } - count = mPendingAdditions.size(); - for (int i = count - 1; i >= 0; i--) { - ViewHolder item = mPendingAdditions.get(i); - View view = item.itemView; - ViewCompat.setAlpha(view, 1); - dispatchAddFinished(item); - mPendingAdditions.remove(i); - } - count = mPendingChanges.size(); - for (int i = count - 1; i >= 0; i--) { - endChangeAnimationIfNecessary(mPendingChanges.get(i)); - } - mPendingChanges.clear(); - if (!isRunning()) { - return; - } - - int listCount = mMovesList.size(); - for (int i = listCount - 1; i >= 0; i--) { - ArrayList<MoveInfo> moves = mMovesList.get(i); - count = moves.size(); - for (int j = count - 1; j >= 0; j--) { - MoveInfo moveInfo = moves.get(j); - ViewHolder item = moveInfo.holder; - View view = item.itemView; - ViewCompat.setTranslationY(view, 0); - ViewCompat.setTranslationX(view, 0); - dispatchMoveFinished(moveInfo.holder); - moves.remove(j); - if (moves.isEmpty()) { - mMovesList.remove(moves); - } - } - } - listCount = mAdditionsList.size(); - for (int i = listCount - 1; i >= 0; i--) { - ArrayList<ViewHolder> additions = mAdditionsList.get(i); - count = additions.size(); - for (int j = count - 1; j >= 0; j--) { - ViewHolder item = additions.get(j); - View view = item.itemView; - ViewCompat.setAlpha(view, 1); - dispatchAddFinished(item); - additions.remove(j); - if (additions.isEmpty()) { - mAdditionsList.remove(additions); - } - } - } - listCount = mChangesList.size(); - for (int i = listCount - 1; i >= 0; i--) { - ArrayList<ChangeInfo> changes = mChangesList.get(i); - count = changes.size(); - for (int j = count - 1; j >= 0; j--) { - endChangeAnimationIfNecessary(changes.get(j)); - if (changes.isEmpty()) { - mChangesList.remove(changes); - } - } - } - - cancelAll(mRemoveAnimations); - cancelAll(mMoveAnimations); - cancelAll(mAddAnimations); - cancelAll(mChangeAnimations); - - dispatchAnimationsFinished(); - } - - void cancelAll(List<ViewHolder> viewHolders) { - for (int i = viewHolders.size() - 1; i >= 0; i--) { - ViewCompat.animate(viewHolders.get(i).itemView).cancel(); - } - } - - private static class VpaListenerAdapter implements ViewPropertyAnimatorListener { - @Override - public void onAnimationStart(View view) {} - - @Override - public void onAnimationEnd(View view) {} - - @Override - public void onAnimationCancel(View view) {} - }; -} |