1 /* 2 * Copyright (C) 2006 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 android.widget; 18 19 import android.content.Context; 20 import android.graphics.Rect; 21 import android.text.Editable; 22 import android.text.InputFilter; 23 import android.text.Selection; 24 import android.text.Spannable; 25 import android.text.Spanned; 26 import android.text.TextWatcher; 27 import android.text.method.DialerKeyListener; 28 import android.text.method.KeyListener; 29 import android.text.method.TextKeyListener; 30 import android.util.AttributeSet; 31 import android.view.KeyEvent; 32 import android.view.View; 33 34 /** 35 * This widget is a layout that contains several specifically-named child views that 36 * handle keyboard entry interpreted as standard phone dialpad digits. 37 * 38 * @deprecated Use a custom view or layout to handle this functionality instead 39 */ 40 @Deprecated 41 public class DialerFilter extends RelativeLayout 42 { DialerFilter(Context context)43 public DialerFilter(Context context) { 44 super(context); 45 } 46 DialerFilter(Context context, AttributeSet attrs)47 public DialerFilter(Context context, AttributeSet attrs) { 48 super(context, attrs); 49 } 50 51 @Override onFinishInflate()52 protected void onFinishInflate() { 53 super.onFinishInflate(); 54 55 // Setup the filter view 56 mInputFilters = new InputFilter[] { new InputFilter.AllCaps() }; 57 58 mHint = (EditText) findViewById(com.android.internal.R.id.hint); 59 if (mHint == null) { 60 throw new IllegalStateException("DialerFilter must have a child EditText named hint"); 61 } 62 mHint.setFilters(mInputFilters); 63 64 mLetters = mHint; 65 mLetters.setKeyListener(TextKeyListener.getInstance()); 66 mLetters.setMovementMethod(null); 67 mLetters.setFocusable(false); 68 69 // Setup the digits view 70 mPrimary = (EditText) findViewById(com.android.internal.R.id.primary); 71 if (mPrimary == null) { 72 throw new IllegalStateException("DialerFilter must have a child EditText named primary"); 73 } 74 mPrimary.setFilters(mInputFilters); 75 76 mDigits = mPrimary; 77 mDigits.setKeyListener(DialerKeyListener.getInstance()); 78 mDigits.setMovementMethod(null); 79 mDigits.setFocusable(false); 80 81 // Look for an icon 82 mIcon = (ImageView) findViewById(com.android.internal.R.id.icon); 83 84 // Setup focus & highlight for this view 85 setFocusable(true); 86 87 // XXX Force the mode to QWERTY for now, since 12-key isn't supported 88 mIsQwerty = true; 89 setMode(DIGITS_AND_LETTERS); 90 } 91 92 /** 93 * Only show the icon view when focused, if there is one. 94 */ 95 @Override onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect)96 protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) { 97 super.onFocusChanged(focused, direction, previouslyFocusedRect); 98 99 if (mIcon != null) { 100 mIcon.setVisibility(focused ? View.VISIBLE : View.GONE); 101 } 102 } 103 104 isQwertyKeyboard()105 public boolean isQwertyKeyboard() { 106 return mIsQwerty; 107 } 108 109 @Override onKeyDown(int keyCode, KeyEvent event)110 public boolean onKeyDown(int keyCode, KeyEvent event) { 111 boolean handled = false; 112 113 switch (keyCode) { 114 case KeyEvent.KEYCODE_DPAD_UP: 115 case KeyEvent.KEYCODE_DPAD_DOWN: 116 case KeyEvent.KEYCODE_DPAD_LEFT: 117 case KeyEvent.KEYCODE_DPAD_RIGHT: 118 case KeyEvent.KEYCODE_ENTER: 119 case KeyEvent.KEYCODE_DPAD_CENTER: 120 break; 121 122 case KeyEvent.KEYCODE_DEL: 123 switch (mMode) { 124 case DIGITS_AND_LETTERS: 125 handled = mDigits.onKeyDown(keyCode, event); 126 handled &= mLetters.onKeyDown(keyCode, event); 127 break; 128 129 case DIGITS_AND_LETTERS_NO_DIGITS: 130 handled = mLetters.onKeyDown(keyCode, event); 131 if (mLetters.getText().length() == mDigits.getText().length()) { 132 setMode(DIGITS_AND_LETTERS); 133 } 134 break; 135 136 case DIGITS_AND_LETTERS_NO_LETTERS: 137 if (mDigits.getText().length() == mLetters.getText().length()) { 138 mLetters.onKeyDown(keyCode, event); 139 setMode(DIGITS_AND_LETTERS); 140 } 141 handled = mDigits.onKeyDown(keyCode, event); 142 break; 143 144 case DIGITS_ONLY: 145 handled = mDigits.onKeyDown(keyCode, event); 146 break; 147 148 case LETTERS_ONLY: 149 handled = mLetters.onKeyDown(keyCode, event); 150 break; 151 } 152 break; 153 154 default: 155 //mIsQwerty = msg.getKeyIsQwertyKeyboard(); 156 157 switch (mMode) { 158 case DIGITS_AND_LETTERS: 159 handled = mLetters.onKeyDown(keyCode, event); 160 161 // pass this throw so the shift state is correct (for example, 162 // on a standard QWERTY keyboard, * and 8 are on the same key) 163 if (KeyEvent.isModifierKey(keyCode)) { 164 mDigits.onKeyDown(keyCode, event); 165 handled = true; 166 break; 167 } 168 169 // Only check to see if the digit is valid if the key is a printing key 170 // in the TextKeyListener. This prevents us from hiding the digits 171 // line when keys like UP and DOWN are hit. 172 // XXX note that KEYCODE_TAB is special-cased here for 173 // devices that share tab and 0 on a single key. 174 boolean isPrint = event.isPrintingKey(); 175 if (isPrint || keyCode == KeyEvent.KEYCODE_SPACE 176 || keyCode == KeyEvent.KEYCODE_TAB) { 177 char c = event.getMatch(DialerKeyListener.CHARACTERS); 178 if (c != 0) { 179 handled &= mDigits.onKeyDown(keyCode, event); 180 } else { 181 setMode(DIGITS_AND_LETTERS_NO_DIGITS); 182 } 183 } 184 break; 185 186 case DIGITS_AND_LETTERS_NO_LETTERS: 187 case DIGITS_ONLY: 188 handled = mDigits.onKeyDown(keyCode, event); 189 break; 190 191 case DIGITS_AND_LETTERS_NO_DIGITS: 192 case LETTERS_ONLY: 193 handled = mLetters.onKeyDown(keyCode, event); 194 break; 195 } 196 } 197 198 if (!handled) { 199 return super.onKeyDown(keyCode, event); 200 } else { 201 return true; 202 } 203 } 204 205 @Override onKeyUp(int keyCode, KeyEvent event)206 public boolean onKeyUp(int keyCode, KeyEvent event) { 207 boolean a = mLetters.onKeyUp(keyCode, event); 208 boolean b = mDigits.onKeyUp(keyCode, event); 209 return a || b; 210 } 211 getMode()212 public int getMode() { 213 return mMode; 214 } 215 216 /** 217 * Change the mode of the widget. 218 * 219 * @param newMode The mode to switch to. 220 */ setMode(int newMode)221 public void setMode(int newMode) { 222 switch (newMode) { 223 case DIGITS_AND_LETTERS: 224 makeDigitsPrimary(); 225 mLetters.setVisibility(View.VISIBLE); 226 mDigits.setVisibility(View.VISIBLE); 227 break; 228 229 case DIGITS_ONLY: 230 makeDigitsPrimary(); 231 mLetters.setVisibility(View.GONE); 232 mDigits.setVisibility(View.VISIBLE); 233 break; 234 235 case LETTERS_ONLY: 236 makeLettersPrimary(); 237 mLetters.setVisibility(View.VISIBLE); 238 mDigits.setVisibility(View.GONE); 239 break; 240 241 case DIGITS_AND_LETTERS_NO_LETTERS: 242 makeDigitsPrimary(); 243 mLetters.setVisibility(View.INVISIBLE); 244 mDigits.setVisibility(View.VISIBLE); 245 break; 246 247 case DIGITS_AND_LETTERS_NO_DIGITS: 248 makeLettersPrimary(); 249 mLetters.setVisibility(View.VISIBLE); 250 mDigits.setVisibility(View.INVISIBLE); 251 break; 252 253 } 254 int oldMode = mMode; 255 mMode = newMode; 256 onModeChange(oldMode, newMode); 257 } 258 makeLettersPrimary()259 private void makeLettersPrimary() { 260 if (mPrimary == mDigits) { 261 swapPrimaryAndHint(true); 262 } 263 } 264 makeDigitsPrimary()265 private void makeDigitsPrimary() { 266 if (mPrimary == mLetters) { 267 swapPrimaryAndHint(false); 268 } 269 } 270 swapPrimaryAndHint(boolean makeLettersPrimary)271 private void swapPrimaryAndHint(boolean makeLettersPrimary) { 272 Editable lettersText = mLetters.getText(); 273 Editable digitsText = mDigits.getText(); 274 KeyListener lettersInput = mLetters.getKeyListener(); 275 KeyListener digitsInput = mDigits.getKeyListener(); 276 277 if (makeLettersPrimary) { 278 mLetters = mPrimary; 279 mDigits = mHint; 280 } else { 281 mLetters = mHint; 282 mDigits = mPrimary; 283 } 284 285 mLetters.setKeyListener(lettersInput); 286 mLetters.setText(lettersText); 287 lettersText = mLetters.getText(); 288 Selection.setSelection(lettersText, lettersText.length()); 289 290 mDigits.setKeyListener(digitsInput); 291 mDigits.setText(digitsText); 292 digitsText = mDigits.getText(); 293 Selection.setSelection(digitsText, digitsText.length()); 294 295 // Reset the filters 296 mPrimary.setFilters(mInputFilters); 297 mHint.setFilters(mInputFilters); 298 } 299 300 getLetters()301 public CharSequence getLetters() { 302 if (mLetters.getVisibility() == View.VISIBLE) { 303 return mLetters.getText(); 304 } else { 305 return ""; 306 } 307 } 308 getDigits()309 public CharSequence getDigits() { 310 if (mDigits.getVisibility() == View.VISIBLE) { 311 return mDigits.getText(); 312 } else { 313 return ""; 314 } 315 } 316 getFilterText()317 public CharSequence getFilterText() { 318 if (mMode != DIGITS_ONLY) { 319 return getLetters(); 320 } else { 321 return getDigits(); 322 } 323 } 324 append(String text)325 public void append(String text) { 326 switch (mMode) { 327 case DIGITS_AND_LETTERS: 328 mDigits.getText().append(text); 329 mLetters.getText().append(text); 330 break; 331 332 case DIGITS_AND_LETTERS_NO_LETTERS: 333 case DIGITS_ONLY: 334 mDigits.getText().append(text); 335 break; 336 337 case DIGITS_AND_LETTERS_NO_DIGITS: 338 case LETTERS_ONLY: 339 mLetters.getText().append(text); 340 break; 341 } 342 } 343 344 /** 345 * Clears both the digits and the filter text. 346 */ clearText()347 public void clearText() { 348 Editable text; 349 350 text = mLetters.getText(); 351 text.clear(); 352 353 text = mDigits.getText(); 354 text.clear(); 355 356 // Reset the mode based on the hardware type 357 if (mIsQwerty) { 358 setMode(DIGITS_AND_LETTERS); 359 } else { 360 setMode(DIGITS_ONLY); 361 } 362 } 363 setLettersWatcher(TextWatcher watcher)364 public void setLettersWatcher(TextWatcher watcher) { 365 CharSequence text = mLetters.getText(); 366 Spannable span = (Spannable)text; 367 span.setSpan(watcher, 0, text.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE); 368 } 369 setDigitsWatcher(TextWatcher watcher)370 public void setDigitsWatcher(TextWatcher watcher) { 371 CharSequence text = mDigits.getText(); 372 Spannable span = (Spannable)text; 373 span.setSpan(watcher, 0, text.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE); 374 } 375 setFilterWatcher(TextWatcher watcher)376 public void setFilterWatcher(TextWatcher watcher) { 377 if (mMode != DIGITS_ONLY) { 378 setLettersWatcher(watcher); 379 } else { 380 setDigitsWatcher(watcher); 381 } 382 } 383 removeFilterWatcher(TextWatcher watcher)384 public void removeFilterWatcher(TextWatcher watcher) { 385 Spannable text; 386 if (mMode != DIGITS_ONLY) { 387 text = mLetters.getText(); 388 } else { 389 text = mDigits.getText(); 390 } 391 text.removeSpan(watcher); 392 } 393 394 /** 395 * Called right after the mode changes to give subclasses the option to 396 * restyle, etc. 397 */ onModeChange(int oldMode, int newMode)398 protected void onModeChange(int oldMode, int newMode) { 399 } 400 401 /** This mode has both lines */ 402 public static final int DIGITS_AND_LETTERS = 1; 403 /** This mode is when after starting in {@link #DIGITS_AND_LETTERS} mode the filter 404 * has removed all possibility of the digits matching, leaving only the letters line */ 405 public static final int DIGITS_AND_LETTERS_NO_DIGITS = 2; 406 /** This mode is when after starting in {@link #DIGITS_AND_LETTERS} mode the filter 407 * has removed all possibility of the letters matching, leaving only the digits line */ 408 public static final int DIGITS_AND_LETTERS_NO_LETTERS = 3; 409 /** This mode has only the digits line */ 410 public static final int DIGITS_ONLY = 4; 411 /** This mode has only the letters line */ 412 public static final int LETTERS_ONLY = 5; 413 414 EditText mLetters; 415 EditText mDigits; 416 EditText mPrimary; 417 EditText mHint; 418 InputFilter mInputFilters[]; 419 ImageView mIcon; 420 int mMode; 421 private boolean mIsQwerty; 422 } 423