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