blob: 1135c215660e2f2c1f60dab9da619e67895d5ee6 [file] [log] [blame]
Ben Kwa60d91e42015-10-20 15:02:33 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Steve McKayf68210e2015-11-03 15:23:16 -080017package com.android.documentsui.dirlist;
Ben Kwa60d91e42015-10-20 15:02:33 -070018
19import android.animation.Animator;
20import android.animation.ArgbEvaluator;
21import android.animation.ValueAnimator;
22import android.content.Context;
23import android.support.v4.util.ArrayMap;
24import android.support.v7.widget.DefaultItemAnimator;
25import android.support.v7.widget.RecyclerView;
26import android.util.TypedValue;
27
Ben Kwa65d7c042015-11-10 21:02:47 -080028import com.android.documentsui.R;
29
Ben Kwa60d91e42015-10-20 15:02:33 -070030import java.util.ArrayList;
31import java.util.List;
32import java.util.Map;
33
34/**
35 * Performs change animations on Items in DirectoryFragment's RecyclerView. This class overrides
36 * the way selection animations are normally performed - instead of cross fading the old Item with a
37 * new Item, this class manually animates a background color change. This enables selected Items to
38 * correctly maintain focus.
39 */
40class DirectoryItemAnimator extends DefaultItemAnimator {
41 private final List<ColorAnimation> mPendingAnimations = new ArrayList<>();
42 private final Map<RecyclerView.ViewHolder, ColorAnimation> mRunningAnimations =
43 new ArrayMap<>();
44 private final Integer mDefaultColor;
45 private final Integer mSelectedColor;
46
47 public DirectoryItemAnimator(Context context) {
Ben Kwa65d7c042015-11-10 21:02:47 -080048 mDefaultColor = context.getResources().getColor(R.color.item_doc_background);
49 mSelectedColor = context.getResources().getColor(R.color.item_doc_background_selected);
Ben Kwa60d91e42015-10-20 15:02:33 -070050 }
51
52 @Override
53 public void runPendingAnimations() {
54 super.runPendingAnimations();
55 for (ColorAnimation anim: mPendingAnimations) {
56 anim.start();
57 mRunningAnimations.put(anim.viewHolder, anim);
58 }
59 mPendingAnimations.clear();
60 }
61
62 @Override
63 public void endAnimation(RecyclerView.ViewHolder vh) {
64 super.endAnimation(vh);
65
66 for (int i = mPendingAnimations.size() - 1; i >= 0; --i) {
67 ColorAnimation anim = mPendingAnimations.get(i);
68 if (anim.viewHolder == vh) {
69 mPendingAnimations.remove(i);
70 anim.end();
71 }
72 }
73
74 ColorAnimation anim = mRunningAnimations.get(vh);
75 if (anim != null) {
76 anim.cancel();
77 }
78 }
79
80 @Override
81 public ItemHolderInfo recordPreLayoutInformation(
82 RecyclerView.State state,
83 RecyclerView.ViewHolder viewHolder,
84 @AdapterChanges int changeFlags,
85 List<Object> payloads) {
86 ItemInfo info = (ItemInfo) super.recordPreLayoutInformation(state,
87 viewHolder, changeFlags, payloads);
88 info.isActivated = viewHolder.itemView.isActivated();
89 return info;
90 }
91
92
93 @Override
94 public ItemHolderInfo recordPostLayoutInformation(
95 RecyclerView.State state, RecyclerView.ViewHolder viewHolder) {
96 ItemInfo info = (ItemInfo) super.recordPostLayoutInformation(state,
97 viewHolder);
98 info.isActivated = viewHolder.itemView.isActivated();
99 return info;
100 }
101
102 @Override
103 public boolean animateChange(final RecyclerView.ViewHolder oldHolder,
104 RecyclerView.ViewHolder newHolder, ItemHolderInfo preInfo,
105 ItemHolderInfo postInfo) {
106 if (oldHolder != newHolder) {
107 return super.animateChange(oldHolder, newHolder, preInfo, postInfo);
108 }
109
110 ItemInfo pre = (ItemInfo)preInfo;
111 ItemInfo post = (ItemInfo)postInfo;
112
113 if (pre.isActivated == post.isActivated) {
114 dispatchAnimationFinished(oldHolder);
115 return false;
116 } else {
117 Integer startColor = pre.isActivated ? mSelectedColor : mDefaultColor;
118 Integer endColor = post.isActivated ? mSelectedColor : mDefaultColor;
119 oldHolder.itemView.setBackgroundColor(startColor);
120 mPendingAnimations.add(new ColorAnimation(oldHolder, startColor, endColor));
121 }
122 return true;
123 }
124
125 @Override
126 public ItemHolderInfo obtainHolderInfo() {
127 return new ItemInfo();
128 }
129
130 @Override
131 public boolean canReuseUpdatedViewHolder(RecyclerView.ViewHolder vh) {
132 return true;
133 }
134
135 class ItemInfo extends DefaultItemAnimator.ItemHolderInfo {
136 boolean isActivated;
137 };
138
139 /**
140 * Animates changes in background color.
141 */
142 class ColorAnimation
143 implements ValueAnimator.AnimatorUpdateListener, Animator.AnimatorListener {
144 ValueAnimator mValueAnimator;
145 final RecyclerView.ViewHolder viewHolder;
146 int mEndColor;
147
148 public ColorAnimation(RecyclerView.ViewHolder vh, int startColor, int endColor)
149 {
150 viewHolder = vh;
151 mValueAnimator = ValueAnimator.ofObject(new ArgbEvaluator(), startColor, endColor);
152 mValueAnimator.addUpdateListener(this);
153 mValueAnimator.addListener(this);
154
155 mEndColor = endColor;
156 }
157
158 public void start() {
159 mValueAnimator.start();
160 }
161
162 public void cancel() {
163 mValueAnimator.cancel();
164 }
165
166 public void end() {
167 mValueAnimator.end();
168 }
169
170 @Override
171 public void onAnimationUpdate(ValueAnimator animator) {
172 viewHolder.itemView.setBackgroundColor((Integer)animator.getAnimatedValue());
173 }
174
175 @Override
176 public void onAnimationEnd(Animator animator) {
177 viewHolder.itemView.setBackgroundColor(mEndColor);
178 mRunningAnimations.remove(viewHolder);
179 dispatchAnimationFinished(viewHolder);
180 }
181
182 @Override
183 public void onAnimationStart(Animator animation) {
184 dispatchAnimationStarted(viewHolder);
185 }
186
187 @Override
188 public void onAnimationCancel(Animator animation) {}
189
190 @Override
191 public void onAnimationRepeat(Animator animation) {}
192 };
193};