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.content.res.TypedArray; 22 import android.graphics.drawable.Drawable; 23 import android.graphics.drawable.GradientDrawable; 24 import android.graphics.drawable.VectorDrawable; 25 import android.util.AttributeSet; 26 import android.view.MotionEvent; 27 28 import androidx.annotation.Nullable; 29 30 /** 31 * Similar to the {@link NumPadKey}, but displays an image. 32 */ 33 public class NumPadButton extends AlphaOptimizedImageButton implements NumPadAnimationListener { 34 35 @Nullable 36 private NumPadAnimator mAnimator; 37 private int mOrientation; 38 NumPadButton(Context context, AttributeSet attrs)39 public NumPadButton(Context context, AttributeSet attrs) { 40 super(context, attrs); 41 42 Drawable background = getBackground(); 43 if (background instanceof GradientDrawable) { 44 mAnimator = new NumPadAnimator(context, background.mutate(), 45 attrs.getStyleAttribute(), getDrawable()); 46 } else { 47 mAnimator = null; 48 } 49 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 78 if (mAnimator != null) mAnimator.onLayout(b - t); 79 } 80 81 @Override onTouchEvent(MotionEvent event)82 public boolean onTouchEvent(MotionEvent event) { 83 switch(event.getActionMasked()) { 84 case MotionEvent.ACTION_DOWN: 85 if (mAnimator != null) mAnimator.expand(); 86 break; 87 case MotionEvent.ACTION_UP: 88 case MotionEvent.ACTION_CANCEL: 89 if (mAnimator != null) mAnimator.contract(); 90 break; 91 } 92 return super.onTouchEvent(event); 93 } 94 95 /** 96 * Reload colors from resources. 97 **/ reloadColors()98 public void reloadColors() { 99 if (mAnimator != null) mAnimator.reloadColors(getContext()); 100 101 int[] customAttrs = {android.R.attr.textColorPrimaryInverse}; 102 TypedArray a = getContext().obtainStyledAttributes(customAttrs); 103 int imageColor = a.getColor(0, 0); 104 a.recycle(); 105 ((VectorDrawable) getDrawable()).setTintList(ColorStateList.valueOf(imageColor)); 106 } 107 108 @Override setProgress(float progress)109 public void setProgress(float progress) { 110 if (mAnimator != null) { 111 mAnimator.setProgress(progress); 112 } 113 } 114 } 115