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.shared.recents.view;
18 
19 import android.graphics.Outline;
20 import android.graphics.Rect;
21 import android.view.View;
22 import android.view.ViewDebug;
23 import android.view.ViewOutlineProvider;
24 
25 import com.android.systemui.shared.recents.utilities.Utilities;
26 
27 /**
28  * An outline provider that has a clip and outline that can be animated.
29  */
30 public class AnimateableViewBounds extends ViewOutlineProvider {
31 
32     private static final float MIN_ALPHA = 0.1f;
33     private static final float MAX_ALPHA = 0.8f;
34 
35     protected View mSourceView;
36     protected Rect mClipRect = new Rect();
37     protected Rect mClipBounds = new Rect();
38     protected Rect mLastClipBounds = new Rect();
39     protected int mCornerRadius;
40     protected float mAlpha = 1f;
41 
AnimateableViewBounds(View source, int cornerRadius)42     public AnimateableViewBounds(View source, int cornerRadius) {
43         mSourceView = source;
44         mCornerRadius = cornerRadius;
45     }
46 
47     /**
48      * Resets the right and bottom clip for this view.
49      */
reset()50     public void reset() {
51         mClipRect.set(0, 0, 0, 0);
52         updateClipBounds();
53     }
54 
55     @Override
getOutline(View view, Outline outline)56     public void getOutline(View view, Outline outline) {
57         outline.setAlpha(Utilities.mapRange(mAlpha, MIN_ALPHA, MAX_ALPHA));
58         if (mCornerRadius > 0) {
59             outline.setRoundRect(mClipRect.left, mClipRect.top,
60                     mSourceView.getWidth() - mClipRect.right,
61                     mSourceView.getHeight() - mClipRect.bottom,
62                     mCornerRadius);
63         } else {
64             outline.setRect(mClipRect.left, mClipRect.top,
65                     mSourceView.getWidth() - mClipRect.right,
66                     mSourceView.getHeight() - mClipRect.bottom);
67         }
68     }
69 
70     /**
71      * Sets the view outline alpha.
72      */
setAlpha(float alpha)73     public void setAlpha(float alpha) {
74         if (Float.compare(alpha, mAlpha) != 0) {
75             mAlpha = alpha;
76             // TODO, If both clip and alpha change in the same frame, only invalidate once
77             mSourceView.invalidateOutline();
78         }
79     }
80 
81     /**
82      * @return the outline alpha.
83      */
getAlpha()84     public float getAlpha() {
85         return mAlpha;
86     }
87 
88     /**
89      * Sets the top clip.
90      */
setClipTop(int top)91     public void setClipTop(int top) {
92         mClipRect.top = top;
93         updateClipBounds();
94     }
95 
96     /**
97      * @return the top clip.
98      */
getClipTop()99     public int getClipTop() {
100         return mClipRect.top;
101     }
102 
103     /**
104      * Sets the bottom clip.
105      */
setClipBottom(int bottom)106     public void setClipBottom(int bottom) {
107         mClipRect.bottom = bottom;
108         updateClipBounds();
109     }
110 
111     /**
112      * @return the bottom clip.
113      */
getClipBottom()114     public int getClipBottom() {
115         return mClipRect.bottom;
116     }
117 
118     /**
119      * @return the clip bounds.
120      */
getClipBounds()121     public Rect getClipBounds() {
122         return mClipBounds;
123     }
124 
updateClipBounds()125     protected void updateClipBounds() {
126         mClipBounds.set(Math.max(0, mClipRect.left), Math.max(0, mClipRect.top),
127                 mSourceView.getWidth() - Math.max(0, mClipRect.right),
128                 mSourceView.getHeight() - Math.max(0, mClipRect.bottom));
129         if (!mLastClipBounds.equals(mClipBounds)) {
130             mSourceView.setClipBounds(mClipBounds);
131             // TODO, If both clip and alpha change in the same frame, only invalidate once
132             mSourceView.invalidateOutline();
133             mLastClipBounds.set(mClipBounds);
134         }
135     }
136 }
137