1 /*
2  * Copyright (C) 2021 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 package com.android.keyguard;
17 
18 import static com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.ColorId.NUM_PAD_BUTTON;
19 import static com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.ColorId.NUM_PAD_KEY;
20 
21 import android.content.Context;
22 import android.content.res.ColorStateList;
23 import android.content.res.Configuration;
24 import android.graphics.drawable.Drawable;
25 import android.graphics.drawable.GradientDrawable;
26 import android.graphics.drawable.VectorDrawable;
27 import android.util.AttributeSet;
28 import android.view.MotionEvent;
29 
30 import androidx.annotation.Nullable;
31 
32 import com.android.settingslib.Utils;
33 import com.android.systemui.R;
34 
35 /**
36  * Similar to the {@link NumPadKey}, but displays an image.
37  */
38 public class NumPadButton extends AlphaOptimizedImageButton implements NumPadAnimationListener {
39 
40     @Nullable
41     private NumPadAnimator mAnimator;
42     private int mOrientation;
43     private int mStyleAttr;
44     private boolean mIsTransparentMode;
45 
NumPadButton(Context context, AttributeSet attrs)46     public NumPadButton(Context context, AttributeSet attrs) {
47         super(context, attrs);
48         mStyleAttr = attrs.getStyleAttribute();
49         setupAnimator();
50     }
51 
52     @Override
onConfigurationChanged(Configuration newConfig)53     protected void onConfigurationChanged(Configuration newConfig) {
54         mOrientation = newConfig.orientation;
55     }
56 
57     @Override
onMeasure(int widthMeasureSpec, int heightMeasureSpec)58     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
59         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
60 
61         // Set width/height to the same value to ensure a smooth circle for the bg, but shrink
62         // the height to match the old pin bouncer.
63         // This is only used for PIN/PUK; the main PIN pad now uses ConstraintLayout, which will
64         // force our width/height to conform to the ratio in the layout.
65         int width = getMeasuredWidth();
66 
67         boolean shortenHeight = mAnimator == null
68                 || mOrientation == Configuration.ORIENTATION_LANDSCAPE;
69         int height = shortenHeight ? (int) (width * .66f) : width;
70 
71         setMeasuredDimension(getMeasuredWidth(), height);
72     }
73 
74     @Override
onLayout(boolean changed, int l, int t, int r, int b)75     protected void onLayout(boolean changed, int l, int t, int r, int b) {
76         super.onLayout(changed, l, t, r, b);
77         int width = r - l;
78         int height = b - t;
79         if (mAnimator != null) mAnimator.onLayout(width, height);
80     }
81 
82     @Override
onTouchEvent(MotionEvent event)83     public boolean onTouchEvent(MotionEvent event) {
84         switch(event.getActionMasked()) {
85             case MotionEvent.ACTION_DOWN:
86                 if (mAnimator != null) mAnimator.expand();
87                 break;
88             case MotionEvent.ACTION_UP:
89             case MotionEvent.ACTION_CANCEL:
90                 if (mAnimator != null) mAnimator.contract();
91                 break;
92         }
93         return super.onTouchEvent(event);
94     }
95 
96     /**
97      * Reload colors from resources.
98      **/
reloadColors()99     public void reloadColors() {
100         if (mAnimator != null) mAnimator.reloadColors(getContext());
101 
102         int textColorResId = mIsTransparentMode ? NUM_PAD_KEY : NUM_PAD_BUTTON;
103         int imageColor = Utils.getColorAttrDefaultColor(getContext(), textColorResId);
104         ((VectorDrawable) getDrawable()).setTintList(ColorStateList.valueOf(imageColor));
105     }
106 
107     @Override
setProgress(float progress)108     public void setProgress(float progress) {
109         if (mAnimator != null) {
110             mAnimator.setProgress(progress);
111         }
112     }
113 
114     /**
115      * Set whether button is transparent mode.
116      *
117      * @param isTransparentMode
118      */
setTransparentMode(boolean isTransparentMode)119     public void setTransparentMode(boolean isTransparentMode) {
120         if (mIsTransparentMode == isTransparentMode) {
121             return;
122         }
123 
124         mIsTransparentMode = isTransparentMode;
125 
126         if (isTransparentMode) {
127             setBackgroundColor(getResources().getColor(android.R.color.transparent));
128         } else {
129             setBackground(getContext().getDrawable(R.drawable.num_pad_key_background));
130         }
131         setupAnimator();
132         reloadColors();
133         requestLayout();
134     }
135 
136     /**
137      * Set up the animator for the NumPadButton.
138      */
setupAnimator()139     private void setupAnimator() {
140         Drawable background = getBackground();
141         if (background instanceof GradientDrawable) {
142             mAnimator = new NumPadAnimator(getContext(), background.mutate(),
143                     mStyleAttr, getDrawable());
144         } else {
145             mAnimator = null;
146         }
147     }
148 }
149