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