• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 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.systemui.recents.views;
18 
19 import android.animation.ObjectAnimator;
20 import android.animation.ValueAnimator;
21 import android.graphics.Outline;
22 import android.graphics.Rect;
23 import android.view.View;
24 import android.view.ViewOutlineProvider;
25 
26 import com.android.systemui.recents.RecentsConfiguration;
27 
28 /* An outline provider that has a clip and outline that can be animated. */
29 public class AnimateableViewBounds extends ViewOutlineProvider {
30 
31     RecentsConfiguration mConfig;
32 
33     TaskView mSourceView;
34     Rect mTmpRect = new Rect();
35     Rect mClipRect = new Rect();
36     Rect mClipBounds = new Rect();
37     Rect mOutlineClipRect = new Rect();
38     int mCornerRadius;
39     float mAlpha = 1f;
40     final float mMinAlpha = 0.25f;
41 
42     ObjectAnimator mClipTopAnimator;
43     ObjectAnimator mClipRightAnimator;
44     ObjectAnimator mClipBottomAnimator;
45 
AnimateableViewBounds(TaskView source, int cornerRadius)46     public AnimateableViewBounds(TaskView source, int cornerRadius) {
47         mConfig = RecentsConfiguration.getInstance();
48         mSourceView = source;
49         mCornerRadius = cornerRadius;
50         setClipTop(getClipTop());
51         setClipRight(getClipRight());
52         setClipBottom(getClipBottom());
53         setOutlineClipBottom(getOutlineClipBottom());
54     }
55 
56     @Override
getOutline(View view, Outline outline)57     public void getOutline(View view, Outline outline) {
58         outline.setAlpha(mMinAlpha + mAlpha / (1f - mMinAlpha));
59         outline.setRoundRect(Math.max(mClipRect.left, mOutlineClipRect.left),
60                 Math.max(mClipRect.top, mOutlineClipRect.top),
61                 mSourceView.getWidth() - Math.max(mClipRect.right, mOutlineClipRect.right),
62                 mSourceView.getHeight() - Math.max(mClipRect.bottom, mOutlineClipRect.bottom),
63                 mCornerRadius);
64     }
65 
66     /** Sets the view outline alpha. */
setAlpha(float alpha)67     void setAlpha(float alpha) {
68         if (Float.compare(alpha, mAlpha) != 0) {
69             mAlpha = alpha;
70             mSourceView.invalidateOutline();
71         }
72     }
73 
74     /** Animates the top clip. */
animateClipTop(int top, int duration, ValueAnimator.AnimatorUpdateListener updateListener)75     void animateClipTop(int top, int duration, ValueAnimator.AnimatorUpdateListener updateListener) {
76         if (mClipTopAnimator != null) {
77             mClipTopAnimator.removeAllListeners();
78             mClipTopAnimator.cancel();
79         }
80         mClipTopAnimator = ObjectAnimator.ofInt(this, "clipTop", top);
81         mClipTopAnimator.setDuration(duration);
82         mClipTopAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator);
83         if (updateListener != null) {
84             mClipTopAnimator.addUpdateListener(updateListener);
85         }
86         mClipTopAnimator.start();
87     }
88 
89     /** Sets the top clip. */
setClipTop(int top)90     public void setClipTop(int top) {
91         if (top != mClipRect.top) {
92             mClipRect.top = top;
93             mSourceView.invalidateOutline();
94             updateClipBounds();
95         }
96     }
97 
98     /** Returns the top clip. */
getClipTop()99     public int getClipTop() {
100         return mClipRect.top;
101     }
102 
103     /** Animates the right clip. */
animateClipRight(int right, int duration)104     void animateClipRight(int right, int duration) {
105         if (mClipRightAnimator != null) {
106             mClipRightAnimator.removeAllListeners();
107             mClipRightAnimator.cancel();
108         }
109         mClipRightAnimator = ObjectAnimator.ofInt(this, "clipRight", right);
110         mClipRightAnimator.setDuration(duration);
111         mClipRightAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator);
112         mClipRightAnimator.start();
113     }
114 
115     /** Sets the right clip. */
setClipRight(int right)116     public void setClipRight(int right) {
117         if (right != mClipRect.right) {
118             mClipRect.right = right;
119             mSourceView.invalidateOutline();
120             updateClipBounds();
121         }
122     }
123 
124     /** Returns the right clip. */
getClipRight()125     public int getClipRight() {
126         return mClipRect.right;
127     }
128 
129     /** Animates the bottom clip. */
animateClipBottom(int bottom, int duration)130     void animateClipBottom(int bottom, int duration) {
131         if (mClipBottomAnimator != null) {
132             mClipBottomAnimator.removeAllListeners();
133             mClipBottomAnimator.cancel();
134         }
135         mClipBottomAnimator = ObjectAnimator.ofInt(this, "clipBottom", bottom);
136         mClipBottomAnimator.setDuration(duration);
137         mClipBottomAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator);
138         mClipBottomAnimator.start();
139     }
140 
141     /** Sets the bottom clip. */
setClipBottom(int bottom)142     public void setClipBottom(int bottom) {
143         if (bottom != mClipRect.bottom) {
144             mClipRect.bottom = bottom;
145             mSourceView.invalidateOutline();
146             updateClipBounds();
147             if (!mConfig.useHardwareLayers) {
148                 mSourceView.mThumbnailView.updateVisibility(
149                         bottom - mSourceView.getPaddingBottom());
150             }
151         }
152     }
153 
154     /** Returns the bottom clip. */
getClipBottom()155     public int getClipBottom() {
156         return mClipRect.bottom;
157     }
158 
159     /** Sets the outline bottom clip. */
setOutlineClipBottom(int bottom)160     public void setOutlineClipBottom(int bottom) {
161         if (bottom != mOutlineClipRect.bottom) {
162             mOutlineClipRect.bottom = bottom;
163             mSourceView.invalidateOutline();
164         }
165     }
166 
167     /** Gets the outline bottom clip. */
getOutlineClipBottom()168     public int getOutlineClipBottom() {
169         return mOutlineClipRect.bottom;
170     }
171 
updateClipBounds()172     private void updateClipBounds() {
173         mClipBounds.set(mClipRect.left, mClipRect.top,
174                 mSourceView.getWidth() - mClipRect.right,
175                 mSourceView.getHeight() - mClipRect.bottom);
176         mSourceView.setClipBounds(mClipBounds);
177     }
178 }
179