1/* 2 * Copyright (C) 2012 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 17package com.android.keyguard; 18 19import android.content.Context; 20import android.content.res.TypedArray; 21import android.text.SpannableStringBuilder; 22import android.text.style.TextAppearanceSpan; 23import android.util.AttributeSet; 24import android.view.HapticFeedbackConstants; 25import android.view.View; 26import android.widget.Button; 27import android.widget.TextView; 28 29import com.android.internal.widget.LockPatternUtils; 30 31public class NumPadKey extends Button { 32 // list of "ABC", etc per digit, starting with '0' 33 static String sKlondike[]; 34 35 int mDigit = -1; 36 int mTextViewResId; 37 TextView mTextView = null; 38 boolean mEnableHaptics; 39 40 private View.OnClickListener mListener = new View.OnClickListener() { 41 @Override 42 public void onClick(View thisView) { 43 if (mTextView == null) { 44 if (mTextViewResId > 0) { 45 final View v = NumPadKey.this.getRootView().findViewById(mTextViewResId); 46 if (v != null && v instanceof TextView) { 47 mTextView = (TextView) v; 48 } 49 } 50 } 51 // check for time-based lockouts 52 if (mTextView != null && mTextView.isEnabled()) { 53 mTextView.append(String.valueOf(mDigit)); 54 } 55 doHapticKeyClick(); 56 } 57 }; 58 59 public NumPadKey(Context context) { 60 this(context, null); 61 } 62 63 public NumPadKey(Context context, AttributeSet attrs) { 64 this(context, attrs, 0); 65 } 66 67 public NumPadKey(Context context, AttributeSet attrs, int defStyle) { 68 super(context, attrs, defStyle); 69 70 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.NumPadKey); 71 mDigit = a.getInt(R.styleable.NumPadKey_digit, mDigit); 72 setTextViewResId(a.getResourceId(R.styleable.NumPadKey_textView, 0)); 73 74 setOnClickListener(mListener); 75 setOnHoverListener(new LiftToActivateListener(context)); 76 setAccessibilityDelegate(new ObscureSpeechDelegate(context)); 77 78 mEnableHaptics = new LockPatternUtils(context).isTactileFeedbackEnabled(); 79 80 SpannableStringBuilder builder = new SpannableStringBuilder(); 81 builder.append(String.valueOf(mDigit)); 82 if (mDigit >= 0) { 83 if (sKlondike == null) { 84 sKlondike = context.getResources().getStringArray( 85 R.array.lockscreen_num_pad_klondike); 86 } 87 if (sKlondike != null && sKlondike.length > mDigit) { 88 final String extra = sKlondike[mDigit]; 89 final int extraLen = extra.length(); 90 if (extraLen > 0) { 91 builder.append(" "); 92 builder.append(extra); 93 builder.setSpan( 94 new TextAppearanceSpan(context, R.style.TextAppearance_NumPadKey_Klondike), 95 builder.length()-extraLen, builder.length(), 0); 96 } 97 } 98 } 99 setText(builder); 100 } 101 102 @Override 103 public void onDetachedFromWindow() { 104 super.onDetachedFromWindow(); 105 106 // Reset the "announced headset" flag when detached. 107 ObscureSpeechDelegate.sAnnouncedHeadset = false; 108 } 109 110 public void setTextView(TextView tv) { 111 mTextView = tv; 112 } 113 114 public void setTextViewResId(int resId) { 115 mTextView = null; 116 mTextViewResId = resId; 117 } 118 119 // Cause a VIRTUAL_KEY vibration 120 public void doHapticKeyClick() { 121 if (mEnableHaptics) { 122 performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, 123 HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING 124 | HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); 125 } 126 } 127} 128