• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package com.android.documentsui.dirlist;
18 
19 import android.animation.Animator;
20 import android.animation.ArgbEvaluator;
21 import android.animation.ValueAnimator;
22 import android.content.Context;
23 import androidx.collection.ArrayMap;
24 import androidx.recyclerview.widget.DefaultItemAnimator;
25 import androidx.recyclerview.widget.RecyclerView;
26 
27 import android.content.res.TypedArray;
28 import android.util.TypedValue;
29 
30 import com.android.documentsui.R;
31 
32 import java.util.ArrayList;
33 import java.util.List;
34 import java.util.Map;
35 
36 /**
37  * Performs change animations on Items in DirectoryFragment's RecyclerView.  This class overrides
38  * the way selection animations are normally performed - instead of cross fading the old Item with a
39  * new Item, this class manually animates a background color change.  This enables selected Items to
40  * correctly maintain focus.
41  */
42 class DirectoryItemAnimator extends DefaultItemAnimator {
43     private final List<ColorAnimation> mPendingAnimations = new ArrayList<>();
44     private final Map<RecyclerView.ViewHolder, ColorAnimation> mRunningAnimations =
45             new ArrayMap<>();
46 
47     @Override
runPendingAnimations()48     public void runPendingAnimations() {
49         super.runPendingAnimations();
50         for (ColorAnimation anim: mPendingAnimations) {
51             anim.start();
52             mRunningAnimations.put(anim.viewHolder, anim);
53         }
54         mPendingAnimations.clear();
55     }
56 
57     @Override
endAnimation(RecyclerView.ViewHolder vh)58     public void endAnimation(RecyclerView.ViewHolder vh) {
59         super.endAnimation(vh);
60 
61         for (int i = mPendingAnimations.size() - 1; i >= 0; --i) {
62             ColorAnimation anim = mPendingAnimations.get(i);
63             if (anim.viewHolder == vh) {
64                 mPendingAnimations.remove(i);
65                 anim.end();
66             }
67         }
68 
69         ColorAnimation anim = mRunningAnimations.get(vh);
70         if (anim != null) {
71             anim.cancel();
72         }
73     }
74 
75     @Override
recordPreLayoutInformation( RecyclerView.State state, RecyclerView.ViewHolder viewHolder, @AdapterChanges int changeFlags, List<Object> payloads)76     public ItemHolderInfo recordPreLayoutInformation(
77         RecyclerView.State state,
78         RecyclerView.ViewHolder viewHolder,
79         @AdapterChanges int changeFlags,
80         List<Object> payloads) {
81         ItemInfo info = (ItemInfo) super.recordPreLayoutInformation(state,
82                 viewHolder, changeFlags, payloads);
83         info.isActivated = viewHolder.itemView.isActivated();
84         return info;
85     }
86 
87 
88     @Override
recordPostLayoutInformation( RecyclerView.State state, RecyclerView.ViewHolder viewHolder)89     public ItemHolderInfo recordPostLayoutInformation(
90         RecyclerView.State state, RecyclerView.ViewHolder viewHolder) {
91         ItemInfo info = (ItemInfo) super.recordPostLayoutInformation(state,
92                 viewHolder);
93         info.isActivated = viewHolder.itemView.isActivated();
94         return info;
95     }
96 
97     @Override
obtainHolderInfo()98     public ItemHolderInfo obtainHolderInfo() {
99         return new ItemInfo();
100     }
101 
102     @Override
canReuseUpdatedViewHolder(RecyclerView.ViewHolder vh)103     public boolean canReuseUpdatedViewHolder(RecyclerView.ViewHolder vh) {
104         return true;
105     }
106 
107     class ItemInfo extends DefaultItemAnimator.ItemHolderInfo {
108         boolean isActivated;
109     };
110 
111     /**
112      * Animates changes in background color.
113      */
114     class ColorAnimation
115             implements ValueAnimator.AnimatorUpdateListener, Animator.AnimatorListener {
116         ValueAnimator mValueAnimator;
117         final RecyclerView.ViewHolder viewHolder;
118         int mEndColor;
119 
ColorAnimation(RecyclerView.ViewHolder vh, int startColor, int endColor)120         public ColorAnimation(RecyclerView.ViewHolder vh, int startColor, int endColor)
121         {
122             viewHolder = vh;
123             mValueAnimator = ValueAnimator.ofObject(new ArgbEvaluator(), startColor, endColor);
124             mValueAnimator.addUpdateListener(this);
125             mValueAnimator.addListener(this);
126 
127             mEndColor = endColor;
128         }
129 
start()130         public void start() {
131             mValueAnimator.start();
132         }
133 
cancel()134         public void cancel() {
135             mValueAnimator.cancel();
136         }
137 
end()138         public void end() {
139             mValueAnimator.end();
140         }
141 
142         @Override
onAnimationUpdate(ValueAnimator animator)143         public void onAnimationUpdate(ValueAnimator animator) {
144             viewHolder.itemView.setBackgroundColor((Integer)animator.getAnimatedValue());
145         }
146 
147         @Override
onAnimationEnd(Animator animator)148         public void onAnimationEnd(Animator animator) {
149             viewHolder.itemView.setBackgroundColor(mEndColor);
150             mRunningAnimations.remove(viewHolder);
151             dispatchAnimationFinished(viewHolder);
152         }
153 
154         @Override
onAnimationStart(Animator animation)155         public void onAnimationStart(Animator animation) {
156             dispatchAnimationStarted(viewHolder);
157         }
158 
159         @Override
onAnimationCancel(Animator animation)160         public void onAnimationCancel(Animator animation) {}
161 
162         @Override
onAnimationRepeat(Animator animation)163         public void onAnimationRepeat(Animator animation) {}
164     };
165 };
166