• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.text.method;
18 
19 import android.view.KeyEvent;
20 import android.view.View;
21 import android.text.Editable;
22 import android.text.InputFilter;
23 import android.text.Selection;
24 import android.text.Spannable;
25 import android.text.SpannableStringBuilder;
26 import android.text.Spanned;
27 
28 /**
29  * For numeric text entry
30  */
31 public abstract class NumberKeyListener extends BaseKeyListener
32     implements InputFilter
33 {
34     /**
35      * You can say which characters you can accept.
36      */
getAcceptedChars()37     protected abstract char[] getAcceptedChars();
38 
lookup(KeyEvent event, Spannable content)39     protected int lookup(KeyEvent event, Spannable content) {
40         return event.getMatch(getAcceptedChars(), getMetaState(content));
41     }
42 
filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend)43     public CharSequence filter(CharSequence source, int start, int end,
44                                Spanned dest, int dstart, int dend) {
45         char[] accept = getAcceptedChars();
46         boolean filter = false;
47 
48         int i;
49         for (i = start; i < end; i++) {
50             if (!ok(accept, source.charAt(i))) {
51                 break;
52             }
53         }
54 
55         if (i == end) {
56             // It was all OK.
57             return null;
58         }
59 
60         if (end - start == 1) {
61             // It was not OK, and there is only one char, so nothing remains.
62             return "";
63         }
64 
65         SpannableStringBuilder filtered =
66             new SpannableStringBuilder(source, start, end);
67         i -= start;
68         end -= start;
69 
70         int len = end - start;
71         // Only count down to i because the chars before that were all OK.
72         for (int j = end - 1; j >= i; j--) {
73             if (!ok(accept, source.charAt(j))) {
74                 filtered.delete(j, j + 1);
75             }
76         }
77 
78         return filtered;
79     }
80 
ok(char[] accept, char c)81     protected static boolean ok(char[] accept, char c) {
82         for (int i = accept.length - 1; i >= 0; i--) {
83             if (accept[i] == c) {
84                 return true;
85             }
86         }
87 
88         return false;
89     }
90 
91     @Override
onKeyDown(View view, Editable content, int keyCode, KeyEvent event)92     public boolean onKeyDown(View view, Editable content,
93                              int keyCode, KeyEvent event) {
94         int selStart, selEnd;
95 
96         {
97             int a = Selection.getSelectionStart(content);
98             int b = Selection.getSelectionEnd(content);
99 
100             selStart = Math.min(a, b);
101             selEnd = Math.max(a, b);
102         }
103 
104         if (selStart < 0 || selEnd < 0) {
105             selStart = selEnd = 0;
106             Selection.setSelection(content, 0);
107         }
108 
109         int i = event != null ? lookup(event, content) : 0;
110         int repeatCount = event != null ? event.getRepeatCount() : 0;
111         if (repeatCount == 0) {
112             if (i != 0) {
113                 if (selStart != selEnd) {
114                     Selection.setSelection(content, selEnd);
115                 }
116 
117                 content.replace(selStart, selEnd, String.valueOf((char) i));
118 
119                 adjustMetaAfterKeypress(content);
120                 return true;
121             }
122         } else if (i == '0' && repeatCount == 1) {
123             // Pretty hackish, it replaces the 0 with the +
124 
125             if (selStart == selEnd && selEnd > 0 &&
126                     content.charAt(selStart - 1) == '0') {
127                 content.replace(selStart - 1, selEnd, String.valueOf('+'));
128                 adjustMetaAfterKeypress(content);
129                 return true;
130             }
131         }
132 
133         adjustMetaAfterKeypress(content);
134         return super.onKeyDown(view, content, keyCode, event);
135     }
136 }
137