• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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.wm.shell.draganddrop;
18 
19 import android.animation.ObjectAnimator;
20 import android.animation.RectEvaluator;
21 import android.content.Context;
22 import android.graphics.Canvas;
23 import android.graphics.Color;
24 import android.graphics.ColorFilter;
25 import android.graphics.Paint;
26 import android.graphics.PixelFormat;
27 import android.graphics.Rect;
28 import android.graphics.drawable.Drawable;
29 import android.util.IntProperty;
30 import android.util.Property;
31 import android.view.animation.Interpolator;
32 
33 import androidx.annotation.NonNull;
34 import androidx.annotation.Nullable;
35 
36 import com.android.internal.graphics.ColorUtils;
37 import com.android.internal.policy.ScreenDecorationsUtils;
38 import com.android.internal.protolog.common.ProtoLog;
39 import com.android.wm.shell.protolog.ShellProtoLogGroup;
40 import com.android.wm.shell.R;
41 
42 /**
43  * Drawable to draw the region that the target will have once it is dropped.
44  */
45 public class DropOutlineDrawable extends Drawable {
46 
47     private static final int BOUNDS_DURATION = 200;
48     private static final int ALPHA_DURATION = 135;
49 
50     private final IntProperty<DropOutlineDrawable> ALPHA =
51             new IntProperty<DropOutlineDrawable>("alpha") {
52         @Override
53         public void setValue(DropOutlineDrawable d, int alpha) {
54             d.setAlpha(alpha);
55         }
56 
57         @Override
58         public Integer get(DropOutlineDrawable d) {
59             return d.getAlpha();
60         }
61     };
62 
63     private final Property<DropOutlineDrawable, Rect> BOUNDS =
64             new Property<DropOutlineDrawable, Rect>(Rect.class, "bounds") {
65         @Override
66         public void set(DropOutlineDrawable d, Rect bounds) {
67             d.setRegionBounds(bounds);
68         }
69 
70         @Override
71         public Rect get(DropOutlineDrawable d) {
72             return d.getRegionBounds();
73         }
74     };
75 
76     private final RectEvaluator mRectEvaluator = new RectEvaluator(new Rect());
77     private ObjectAnimator mBoundsAnimator;
78     private ObjectAnimator mAlphaAnimator;
79 
80     private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
81     private final Rect mBounds = new Rect();
82     private final float mCornerRadius;
83     private final int mMaxAlpha;
84     private int mColor;
85 
DropOutlineDrawable(Context context)86     public DropOutlineDrawable(Context context) {
87         super();
88         // TODO(b/169894807): Use corner specific radii and maybe lower radius for non-edge corners
89         mCornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(context);
90         mColor = context.getColor(R.color.drop_outline_background);
91         mMaxAlpha = Color.alpha(mColor);
92         // Initialize as hidden
93         ALPHA.set(this, 0);
94     }
95 
96     @Override
setColorFilter(@ullable ColorFilter colorFilter)97     public void setColorFilter(@Nullable ColorFilter colorFilter) {
98         // Do nothing
99     }
100 
101     @Override
setAlpha(int alpha)102     public void setAlpha(int alpha) {
103         mColor = ColorUtils.setAlphaComponent(mColor, alpha);
104         mPaint.setColor(mColor);
105         invalidateSelf();
106     }
107 
108     @Override
getAlpha()109     public int getAlpha() {
110         return Color.alpha(mColor);
111     }
112 
113     @Override
getOpacity()114     public int getOpacity() {
115         return PixelFormat.TRANSLUCENT;
116     }
117 
118     @Override
onBoundsChange(Rect bounds)119     protected void onBoundsChange(Rect bounds) {
120         invalidateSelf();
121     }
122 
123     @Override
draw(@onNull Canvas canvas)124     public void draw(@NonNull Canvas canvas) {
125         canvas.drawRoundRect(mBounds.left, mBounds.top, mBounds.right, mBounds.bottom,
126                 mCornerRadius, mCornerRadius, mPaint);
127     }
128 
setRegionBounds(Rect bounds)129     public void setRegionBounds(Rect bounds) {
130         mBounds.set(bounds);
131         invalidateSelf();
132     }
133 
getRegionBounds()134     public Rect getRegionBounds() {
135         return mBounds;
136     }
137 
startBoundsAnimation(Rect toBounds, Interpolator interpolator)138     ObjectAnimator startBoundsAnimation(Rect toBounds, Interpolator interpolator) {
139         ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP, "Animate bounds: from=%s to=%s",
140                 mBounds, toBounds);
141         if (mBoundsAnimator != null) {
142             mBoundsAnimator.cancel();
143         }
144         mBoundsAnimator = ObjectAnimator.ofObject(this, BOUNDS, mRectEvaluator,
145                 mBounds, toBounds);
146         mBoundsAnimator.setDuration(BOUNDS_DURATION);
147         mBoundsAnimator.setInterpolator(interpolator);
148         mBoundsAnimator.start();
149         return mBoundsAnimator;
150     }
151 
startVisibilityAnimation(boolean visible, Interpolator interpolator)152     ObjectAnimator startVisibilityAnimation(boolean visible, Interpolator interpolator) {
153         ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP, "Animate alpha: from=%d to=%d",
154                 Color.alpha(mColor), visible ? mMaxAlpha : 0);
155         if (mAlphaAnimator != null) {
156             mAlphaAnimator.cancel();
157         }
158         mAlphaAnimator = ObjectAnimator.ofInt(this, ALPHA, Color.alpha(mColor),
159                 visible ? mMaxAlpha : 0);
160         mAlphaAnimator.setDuration(ALPHA_DURATION);
161         mAlphaAnimator.setInterpolator(interpolator);
162         mAlphaAnimator.start();
163         return mAlphaAnimator;
164     }
165 }
166