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 android.content.Context; 19 import android.content.res.ColorStateList; 20 import android.content.res.Configuration; 21 import android.graphics.drawable.Drawable; 22 import android.graphics.drawable.GradientDrawable; 23 import android.graphics.drawable.VectorDrawable; 24 import android.util.AttributeSet; 25 import android.view.MotionEvent; 26 import android.view.accessibility.AccessibilityNodeInfo; 27 28 import androidx.annotation.DrawableRes; 29 import androidx.annotation.Nullable; 30 31 import com.android.systemui.Flags; 32 import com.android.systemui.bouncer.shared.constants.PinBouncerConstants.Color; 33 import com.android.systemui.res.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 46 @DrawableRes 47 private int mDrawableForTransparentMode = 0; 48 49 @DrawableRes 50 private int mDefaultDrawable = 0; 51 NumPadButton(Context context, AttributeSet attrs)52 public NumPadButton(Context context, AttributeSet attrs) { 53 super(context, attrs); 54 mStyleAttr = attrs.getStyleAttribute(); 55 setupAnimator(); 56 } 57 58 @Override onConfigurationChanged(Configuration newConfig)59 protected void onConfigurationChanged(Configuration newConfig) { 60 mOrientation = newConfig.orientation; 61 } 62 63 @Override onMeasure(int widthMeasureSpec, int heightMeasureSpec)64 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 65 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 66 67 // Set width/height to the same value to ensure a smooth circle for the bg, but shrink 68 // the height to match the old pin bouncer. 69 // This is only used for PIN/PUK; the main PIN pad now uses ConstraintLayout, which will 70 // force our width/height to conform to the ratio in the layout. 71 int width = getMeasuredWidth(); 72 73 boolean shortenHeight = mAnimator == null 74 || mOrientation == Configuration.ORIENTATION_LANDSCAPE; 75 int height = shortenHeight ? (int) (width * .66f) : width; 76 77 setMeasuredDimension(getMeasuredWidth(), height); 78 } 79 80 @Override onLayout(boolean changed, int l, int t, int r, int b)81 protected void onLayout(boolean changed, int l, int t, int r, int b) { 82 super.onLayout(changed, l, t, r, b); 83 int width = r - l; 84 int height = b - t; 85 if (mAnimator != null) mAnimator.onLayout(width, height); 86 } 87 88 @Override onTouchEvent(MotionEvent event)89 public boolean onTouchEvent(MotionEvent event) { 90 switch(event.getActionMasked()) { 91 case MotionEvent.ACTION_DOWN: 92 if (mAnimator != null) mAnimator.expand(); 93 break; 94 case MotionEvent.ACTION_UP: 95 case MotionEvent.ACTION_CANCEL: 96 if (mAnimator != null) mAnimator.contract(); 97 break; 98 } 99 return super.onTouchEvent(event); 100 } 101 102 /** 103 * Reload colors from resources. 104 **/ reloadColors()105 public void reloadColors() { 106 if (mAnimator != null) mAnimator.reloadColors(getContext()); 107 108 int textColorResId = mIsTransparentMode ? Color.actionWithAutoConfirm : Color.action; 109 int imageColor = getContext().getColor(textColorResId); 110 ((VectorDrawable) getDrawable()).setTintList(ColorStateList.valueOf(imageColor)); 111 } 112 113 @Override setProgress(float progress)114 public void setProgress(float progress) { 115 if (mAnimator != null) { 116 mAnimator.setProgress(progress); 117 } 118 } 119 120 /** 121 * Set whether button is transparent mode. 122 * 123 * @param isTransparentMode 124 */ setTransparentMode(boolean isTransparentMode)125 public void setTransparentMode(boolean isTransparentMode) { 126 if (mIsTransparentMode == isTransparentMode) { 127 return; 128 } 129 130 mIsTransparentMode = isTransparentMode; 131 132 if (isTransparentMode) { 133 if (mDrawableForTransparentMode != 0) { 134 setImageResource(mDrawableForTransparentMode); 135 } 136 setBackgroundColor(getResources().getColor(android.R.color.transparent)); 137 } else { 138 if (mDefaultDrawable != 0) { 139 setImageResource(mDefaultDrawable); 140 } 141 Drawable bgDrawable = getContext().getDrawable(R.drawable.num_pad_key_background); 142 if (Flags.bouncerUiRevamp2() && bgDrawable != null) { 143 bgDrawable.setTint(Color.actionBg); 144 } 145 setBackground(bgDrawable); 146 } 147 setupAnimator(); 148 reloadColors(); 149 requestLayout(); 150 } 151 152 /** 153 * Set up the animator for the NumPadButton. 154 */ setupAnimator()155 private void setupAnimator() { 156 Drawable background = getBackground(); 157 if (background instanceof GradientDrawable) { 158 mAnimator = new NumPadAnimator(getContext(), background.mutate(), 159 mStyleAttr, getDrawable()); 160 } else { 161 mAnimator = null; 162 } 163 } 164 165 @Override onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info)166 public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { 167 super.onInitializeAccessibilityNodeInfo(info); 168 info.setTextEntryKey(true); 169 } 170 171 /** 172 * Drawable to use when transparent mode is enabled 173 */ setDrawableForTransparentMode(@rawableRes int drawableResId)174 public void setDrawableForTransparentMode(@DrawableRes int drawableResId) { 175 mDrawableForTransparentMode = drawableResId; 176 } 177 178 /** 179 * Drawable to use when transparent mode is not enabled. 180 */ setDefaultDrawable(@rawableRes int drawableResId)181 public void setDefaultDrawable(@DrawableRes int drawableResId) { 182 mDefaultDrawable = drawableResId; 183 setImageResource(mDefaultDrawable); 184 } 185 } 186