1313import android .view .KeyEvent ;
1414import android .view .View ;
1515import android .widget .TextView ;
16-
1716import androidx .appcompat .widget .AppCompatEditText ;
18-
1917import io .reactivex .rxjava3 .processors .BehaviorProcessor ;
2018import kotlinx .coroutines .flow .Flow ;
2119import kotlinx .coroutines .reactive .ReactiveFlowKt ;
22-
2320import static android .content .ContentValues .TAG ;
2421
2522public class MaskedEditText extends AppCompatEditText implements TextWatcher {
2623
27- public static final String SPACE = " " ;
28- private final OnEditorActionListener onEditorActionListener = new OnEditorActionListener () {
29- @ Override
30- public boolean onEditorAction (TextView v , int actionId ,KeyEvent event ) {
31- switch (actionId ) {
32- // case EditorInfo.IME_ACTION_NEXT:
33- // fixing actionNext
34- // return false;
35- default :
36- return true ;
37- }
38- }
39- };
24+ public static final String SPACE = " " ;
4025 private String mask ;
4126 private char charRepresentation ;
4227 private boolean keepHint ;
@@ -53,12 +38,12 @@ public boolean onEditorAction(TextView v, int actionId,KeyEvent event) {
5338 private int lastValidMaskPosition ;
5439 private boolean selectionChanged ;
5540 private OnFocusChangeListener focusChangeListener ;
56- private String allowedChars ;
57- private String deniedChars ;
58- private BehaviorProcessor <String > rawTextState = BehaviorProcessor .create ();
41+ private String allowedChars ;
42+ private String deniedChars ;
43+ private BehaviorProcessor <String > rawTextState = BehaviorProcessor .create ();
5944 private boolean blockFurtherSelectionChanges = false ;
60-
61- public MaskedEditText (Context context ) {
45+
46+ public MaskedEditText (Context context ) {
6247 super (context );
6348 init ();
6449 }
@@ -70,9 +55,8 @@ public MaskedEditText(Context context, AttributeSet attrs) {
7055 TypedArray attributes = context .obtainStyledAttributes (attrs , R .styleable .MaskedEditText );
7156 mask = attributes .getString (R .styleable .MaskedEditText_mask );
7257
73- allowedChars = attributes .getString (R .styleable .MaskedEditText_allowed_chars );
74- deniedChars = attributes .getString (R .styleable .MaskedEditText_denied_chars );
75- boolean enableImeAction = attributes .getBoolean (R .styleable .MaskedEditText_enable_ime_action , false );
58+ allowedChars = attributes .getString (R .styleable .MaskedEditText_allowed_chars );
59+ deniedChars = attributes .getString (R .styleable .MaskedEditText_denied_chars );
7660
7761 String representation = attributes .getString (R .styleable .MaskedEditText_char_representation );
7862
@@ -86,12 +70,19 @@ public MaskedEditText(Context context, AttributeSet attrs) {
8670
8771 cleanUp ();
8872
89- // Ignoring enter key presses if needed
90- if (!enableImeAction ) {
91- setOnEditorActionListener (onEditorActionListener );
92- } else {
93- setOnEditorActionListener (null );
94- }
73+ // Ignoring enter key presses
74+ setOnEditorActionListener (new OnEditorActionListener () {
75+ @ Override
76+ public boolean onEditorAction (TextView v , int actionId ,KeyEvent event ) {
77+ switch (actionId ) {
78+ // case EditorInfo.IME_ACTION_NEXT:
79+ // fixing actionNext
80+ // return false;
81+ default :
82+ return true ;
83+ }
84+ }
85+ });
9586 attributes .recycle ();
9687 }
9788
@@ -107,9 +98,9 @@ public Parcelable onSaveInstanceState() {
10798
10899 @ Override
109100 public void onRestoreInstanceState (Parcelable state ) {
110- if (!(state instanceof Bundle )) {
111- super .onRestoreInstanceState (state );
112- return ;
101+ if (!(state instanceof Bundle )) {
102+ super .onRestoreInstanceState (state );
103+ return ;
113104 }
114105
115106 Bundle bundle = (Bundle ) state ;
@@ -136,21 +127,19 @@ public void setOnFocusChangeListener(OnFocusChangeListener listener) {
136127
137128 private void cleanUp () {
138129 initialized = false ;
139- if (mask == null || mask .isEmpty ()){
140- return ;
141- }
130+
142131 generatePositionArrays ();
143- if (! shouldKeepText || rawText == null ) {
144- rawText = new RawText ();
145- selection = rawToMask [0 ];
146- }
132+
133+ rawText = new RawText ();
134+ selection = rawToMask [0 ];
135+
147136 editingBefore = true ;
148137 editingOnChanged = true ;
149138 editingAfter = true ;
150139 if (hasHint () && rawText .length () == 0 ) {
151- this .setText (makeMaskedTextWithHint ());
140+ this .setText (makeMaskedTextWithHint ());
152141 } else {
153- this .setText (makeMaskedText ());
142+ this .setText (makeMaskedText ());
154143 }
155144 editingBefore = false ;
156145 editingOnChanged = false ;
@@ -191,14 +180,6 @@ public MaskedEditText(Context context, AttributeSet attrs, int defStyle) {
191180 init ();
192181 }
193182
194- public void setShouldKeepText (boolean shouldKeepText ) {
195- this .shouldKeepText = shouldKeepText ;
196- }
197-
198- public boolean isKeepingText () {
199- return shouldKeepText ;
200- }
201-
202183 public void setMask (String mask ) {
203184 this .mask = mask ;
204185 cleanUp ();
@@ -208,13 +189,6 @@ public String getMask() {
208189 return this .mask ;
209190 }
210191
211- public void setImeActionEnabled (boolean isEnabled ) {
212- if (isEnabled )
213- setOnEditorActionListener (onEditorActionListener );
214- else
215- setOnEditorActionListener (null );
216- }
217-
218192 public String getRawText () {
219193 return this .rawText .getText ();
220194 }
@@ -228,14 +202,14 @@ public char getCharRepresentation() {
228202 return this .charRepresentation ;
229203 }
230204
231- /**
232- * Generates positions for values characters. For instance:
233- * Input data: mask = "+7(###)###-##-##
234- * After method execution:
235- * rawToMask = [3, 4, 5, 6, 8, 9, 11, 12, 14, 15]
236- * maskToRaw = [-1, -1, -1, 0, 1, 2, -1, 3, 4, 5, -1, 6, 7, -1, 8, 9]
237- * charsInMask = "+7()- " (and space, yes)
238- */
205+ /**
206+ * Generates positions for values characters. For instance:
207+ * Input data: mask = "+7(###)###-##-##
208+ * After method execution:
209+ * rawToMask = [3, 4, 5, 6, 8, 9, 11, 12, 14, 15]
210+ * maskToRaw = [-1, -1, -1, 0, 1, 2, -1, 3, 4, 5, -1, 6, 7, -1, 8, 9]
211+ * charsInMask = "+7()- " (and space, yes)
212+ */
239213 private void generatePositionArrays () {
240214 int [] aux = new int [mask .length ()];
241215 maskToRaw = new int [mask .length ()];
@@ -263,7 +237,9 @@ private void generatePositionArrays() {
263237 char [] charsInMask = charsInMaskAux .toCharArray ();
264238
265239 rawToMask = new int [charIndex ];
266- System .arraycopy (aux , 0 , rawToMask , 0 , charIndex );
240+ for (int i = 0 ; i < charIndex ; i ++) {
241+ rawToMask [i ] = aux [i ];
242+ }
267243 }
268244
269245 private void init () {
@@ -272,7 +248,7 @@ private void init() {
272248
273249 @ Override
274250 public void beforeTextChanged (CharSequence s , int start , int count ,
275- int after ) {
251+ int after ) {
276252 if (!editingBefore ) {
277253 editingBefore = true ;
278254 if (start > lastValidMaskPosition ) {
@@ -334,11 +310,11 @@ public void onTextChanged(CharSequence s, int start, int before, int count) {
334310 public void afterTextChanged (Editable s ) {
335311 if (!editingAfter && editingBefore && editingOnChanged ) {
336312 editingAfter = true ;
337- if (hasHint () && (keepHint || rawText .length () == 0 )) {
338- setText (makeMaskedTextWithHint ());
313+ if (hasHint () && (keepHint || rawText .length () == 0 )) {
314+ setText (makeMaskedTextWithHint ());
339315 } else {
340- setText (makeMaskedText ());
341- }
316+ setText (makeMaskedText ());
317+ }
342318
343319 selectionChanged = false ;
344320 setSelection (selection );
@@ -367,8 +343,8 @@ protected void onSelectionChanged(int selStart, int selEnd) {
367343
368344 if (initialized ){
369345 if (!selectionChanged ) {
370- selStart = fixSelection (selStart );
371- selEnd = fixSelection (selEnd );
346+ selStart = fixSelection (selStart );
347+ selEnd = fixSelection (selEnd );
372348
373349 // exactly in this order. If getText.length() == 0 then selStart will be -1
374350 if (selStart > getText ().length ()) selStart = getText ().length ();
@@ -432,46 +408,46 @@ private int lastValidPosition() {
432408
433409
434410 private String makeMaskedText () {
435- int maskedTextLength ;
436- if (rawText .length () < rawToMask .length ) {
437- maskedTextLength = rawToMask [rawText .length ()];
438- } else {
439- maskedTextLength = mask .length ();
440- }
411+ int maskedTextLength ;
412+ if (rawText .length () < rawToMask .length ) {
413+ maskedTextLength = rawToMask [rawText .length ()];
414+ } else {
415+ maskedTextLength = mask .length ();
416+ }
441417 char [] maskedText = new char [maskedTextLength ]; //mask.replace(charRepresentation, ' ').toCharArray();
442- for (int i = 0 ; i < maskedText .length ; i ++) {
443- int rawIndex = maskToRaw [i ];
444- if (rawIndex == -1 ) {
445- maskedText [i ] = mask .charAt (i );
446- } else {
447- maskedText [i ] = rawText .charAt (rawIndex );
448- }
449- }
418+ for (int i = 0 ; i < maskedText .length ; i ++) {
419+ int rawIndex = maskToRaw [i ];
420+ if (rawIndex == -1 ) {
421+ maskedText [i ] = mask .charAt (i );
422+ } else {
423+ maskedText [i ] = rawText .charAt (rawIndex );
424+ }
425+ }
450426 return new String (maskedText );
451427 }
452428
453- private CharSequence makeMaskedTextWithHint () {
454- SpannableStringBuilder ssb = new SpannableStringBuilder ();
455- int mtrv ;
456- int maskFirstChunkEnd = rawToMask [0 ];
457- for (int i = 0 ; i < mask .length (); i ++) {
458- mtrv = maskToRaw [i ];
459- if (mtrv != -1 ) {
460- if (mtrv < rawText .length ()) {
461- ssb .append (rawText .charAt (mtrv ));
462- } else {
463- ssb .append (getHint ().charAt (maskToRaw [i ]));
464- }
465- } else {
466- ssb .append (mask .charAt (i ));
467- }
468- if ((keepHint && rawText .length () < rawToMask .length && i >= rawToMask [rawText .length ()])
469- || (!keepHint && i >= maskFirstChunkEnd )) {
470- ssb .setSpan (new ForegroundColorSpan (getCurrentHintTextColor ()), i , i + 1 , 0 );
471- }
472- }
473- return ssb ;
474- }
429+ private CharSequence makeMaskedTextWithHint () {
430+ SpannableStringBuilder ssb = new SpannableStringBuilder ();
431+ int mtrv ;
432+ int maskFirstChunkEnd = rawToMask [0 ];
433+ for (int i = 0 ; i < mask .length (); i ++) {
434+ mtrv = maskToRaw [i ];
435+ if (mtrv != -1 ) {
436+ if (mtrv < rawText .length ()) {
437+ ssb .append (rawText .charAt (mtrv ));
438+ } else {
439+ ssb .append (getHint ().charAt (maskToRaw [i ]));
440+ }
441+ } else {
442+ ssb .append (mask .charAt (i ));
443+ }
444+ if ((keepHint && rawText .length () < rawToMask .length && i >= rawToMask [rawText .length ()])
445+ || (!keepHint && i >= maskFirstChunkEnd )) {
446+ ssb .setSpan (new ForegroundColorSpan (getCurrentHintTextColor ()), i , i + 1 , 0 );
447+ }
448+ }
449+ return ssb ;
450+ }
475451
476452 private Range calculateRange (int start , int end ) {
477453 Range range = new Range ();
@@ -493,23 +469,23 @@ private Range calculateRange(int start, int end) {
493469 }
494470
495471 private String clear (String string ) {
496- if (deniedChars != null ){
497- for (char c : deniedChars .toCharArray ()){
498- string = string .replace (Character .toString (c ), "" );
499- }
500- }
501-
502- if (allowedChars != null ){
503- StringBuilder builder = new StringBuilder (string .length ());
504-
505- for (char c : string .toCharArray () ){
506- if (allowedChars .contains (String .valueOf (c ) )){
507- builder .append (c );
508- }
509- }
510-
511- string = builder .toString ();
512- }
472+ if (deniedChars != null ){
473+ for (char c : deniedChars .toCharArray ()){
474+ string = string .replace (Character .toString (c ), "" );
475+ }
476+ }
477+
478+ if (allowedChars != null ){
479+ StringBuilder builder = new StringBuilder (string .length ());
480+
481+ for (char c : string .toCharArray () ){
482+ if (allowedChars .contains (String .valueOf (c ) )){
483+ builder .append (c );
484+ }
485+ }
486+
487+ string = builder .toString ();
488+ }
513489
514490 return string ;
515491 }
0 commit comments