@@ -70,6 +70,7 @@ public class FormattedEditText extends AppCompatEditText {
70
70
public static final int GRAVITY_BOTTOM = 2 ;
71
71
private static final Object SELECTION_SPAN = new Object ();
72
72
private static final InputFilter [] EMPTY_FILTERS = new InputFilter [0 ];
73
+ private static final IPlaceholderSpan [] EMPTY_SPANS = new IPlaceholderSpan [0 ];
73
74
private static final Spanned EMPTY_SPANNED = new SpannedString ("" );
74
75
private static final char DEFAULT_PLACE_HOLDER = ' ' ;
75
76
private static final char DEFAULT_MARK = '*' ;
@@ -306,12 +307,10 @@ public boolean onTouchEvent(MotionEvent event) {
306
307
&& Math .abs (mDownPoint [1 ] - y ) <= mTouchSlop ) {
307
308
if (mClearClickListener != null ) {
308
309
if (!mClearClickListener .onClearClick (this , mClearDrawable )) {
309
- event .setAction (MotionEvent .ACTION_CANCEL );
310
- clearText ();
310
+ clearTextInTouch (event );
311
311
}
312
312
} else {
313
- event .setAction (MotionEvent .ACTION_CANCEL );
314
- clearText ();
313
+ clearTextInTouch (event );
315
314
}
316
315
super .onTouchEvent (event );
317
316
return true ;
@@ -401,7 +400,8 @@ public int getHintColor() {
401
400
return mHintColor ;
402
401
}
403
402
404
- private void clearText () {
403
+ private void clearTextInTouch (MotionEvent event ) {
404
+ event .setAction (MotionEvent .ACTION_CANCEL );
405
405
Editable editable = getText ();
406
406
if (editable != null ) {
407
407
editable .clear ();
@@ -714,7 +714,7 @@ private void formatTextWhenDelete(final Editable editable, int start, int before
714
714
if (mMode < MODE_MASK ) {
715
715
final boolean deletedLast = start >= editable .length ();
716
716
if (!deletedLast ) {
717
- formatDefined (editable , start );
717
+ formatDefined (editable , start , true );
718
718
} else {
719
719
for (int i = start ; i > 0 ; i --) {
720
720
final char sub = editable .charAt (i - 1 );
@@ -758,7 +758,7 @@ private void formatTextWhenAppend(final Editable editable, int start, int before
758
758
if (mMode < MODE_MASK ) {
759
759
boolean appendedLast = start > mHolders [mHolders .length - 1 ].index ;
760
760
if (!appendedLast ) {
761
- formatDefined (editable , start );
761
+ formatDefined (editable , start , false );
762
762
}
763
763
} else {
764
764
formatMask (editable , start , false );
@@ -815,95 +815,63 @@ private char findPlaceholder(int index) {
815
815
return 0 ;
816
816
}
817
817
818
- private void formatDefined (Editable editable , int start ) {
819
- IPlaceholderSpan [] spans =
820
- editable .getSpans (start , editable .length (), IPlaceholderSpan .class );
821
- for (IPlaceholderSpan s : spans ) {
822
- int spanStart = editable .getSpanStart (s );
823
- editable .delete (spanStart , spanStart + 1 );
824
- }
825
- int indexInEditable = start ;
818
+ private void formatDefined (Editable editable , int start , boolean deletion ) {
819
+ start = clearPlaceholders (editable , start );
820
+ int selectionIndex = -1 ;
821
+ int indexInText = start ;
826
822
final int maxPos = mHolders [mHolders .length - 1 ].index ;
827
- while (indexInEditable < maxPos ) {
828
- if (indexInEditable >= editable .length ()) {
823
+ while (indexInText < maxPos ) {
824
+ if (indexInText >= editable .length ()) {
829
825
break ;
830
826
}
831
- char placeholder = findPlaceholder (indexInEditable );
827
+ char placeholder = findPlaceholder (indexInText );
832
828
if (placeholder != 0 ) {
833
- editable .insert (indexInEditable , String .valueOf (placeholder ));
829
+ editable .insert (indexInText , String .valueOf (placeholder ));
834
830
editable .setSpan (
835
831
new PlaceholderSpan (),
836
- indexInEditable ,
837
- indexInEditable + 1 ,
832
+ indexInText ,
833
+ indexInText + 1 ,
838
834
Spanned .SPAN_EXCLUSIVE_EXCLUSIVE );
839
- indexInEditable += 1 ;
835
+ indexInText += 1 ;
836
+ if (selectionIndex == -1 ) {
837
+ if (indexInText == start + 1 ) {
838
+ selectionIndex = indexInText ;
839
+ }
840
+ } else if (indexInText == selectionIndex + 1 ) {
841
+ selectionIndex = indexInText ;
842
+ }
840
843
} else {
841
- indexInEditable += 1 ;
844
+ indexInText += 1 ;
842
845
}
843
846
}
847
+ if (deletion && start == 0 && selectionIndex != -1 ) {
848
+ editable .setSpan (
849
+ SELECTION_SPAN , selectionIndex , selectionIndex , Spanned .SPAN_MARK_MARK );
850
+ }
844
851
}
845
852
846
- private void formatMask (final Editable editable , int start , boolean delete ) {
847
- IPlaceholderSpan [] spans ;
848
- if (start > 0 ) {
849
- spans = editable .getSpans (0 , start , IPlaceholderSpan .class );
850
- if (spans .length > 0 ) {
851
- if (spans .length == start ) {
852
- start = 0 ;
853
- } else {
854
- mComparator .mEditable = editable ;
855
- Arrays .sort (spans , mComparator );
856
- mComparator .mEditable = null ;
857
- int last = start - 1 ;
858
- for (int i = spans .length - 1 ; i >= 0 ; i --) {
859
- int spanStart = editable .getSpanStart (spans [i ]);
860
- if (last != spanStart ) {
861
- last += 1 ;
862
- break ;
863
- }
864
- last = spanStart - 1 ;
865
- }
866
- start = last ;
867
- }
868
- }
869
- }
870
- spans = editable .getSpans (start , editable .length (), IPlaceholderSpan .class );
871
- if (spans .length > 0 ) {
872
- if (spans .length == editable .length () - start ) {
873
- editable .delete (start , editable .length ());
874
- if (start == 0 && isNeedClearText ()) {
875
- return ;
876
- }
877
- } else {
878
- clearNonEmptySpans (editable , spans );
879
- }
853
+ private void formatMask (final Editable editable , int start , boolean deletion ) {
854
+ start = clearPlaceholders (editable , start );
855
+ if (start == -1 ) {
856
+ return ;
880
857
}
881
- if (delete
858
+ if (deletion
882
859
&& start == editable .length ()
883
860
&& ((mMode == MODE_MASK && mEmptyPlaceholder == 0 )
884
861
|| (mMode == MODE_HINT && mHintText == null ))) {
885
862
return ;
886
863
}
887
864
int indexInStyle = start + rangeCountEscapeChar (start );
888
865
int indexInText = start ;
866
+ int selectionIndex = -1 ;
889
867
boolean nextCharIsText = false ;
890
- boolean havingRealText = false ;
891
- boolean beenResetSpan = false ;
892
868
final int styleLength = mFormatStyle .length ();
893
869
while (indexInStyle < styleLength ) {
894
870
char charInStyle = mFormatStyle .charAt (indexInStyle );
895
871
if (!nextCharIsText && isMaskChar (charInStyle )) {
896
872
if (indexInText >= editable .length ()) {
897
873
if (mMode == MODE_MASK ) {
898
874
if (mEmptyPlaceholder != 0 ) {
899
- if (delete && start == 0 && !havingRealText && !beenResetSpan ) {
900
- beenResetSpan = true ;
901
- editable .setSpan (
902
- SELECTION_SPAN ,
903
- indexInText ,
904
- indexInText ,
905
- Spanned .SPAN_MARK_MARK );
906
- }
907
875
editable .insert (indexInText , String .valueOf (mEmptyPlaceholder ));
908
876
editable .setSpan (
909
877
new EmptyPlaceholderSpan (),
@@ -919,14 +887,6 @@ private void formatMask(final Editable editable, int start, boolean delete) {
919
887
if (mHintText == null ) {
920
888
break ;
921
889
}
922
- if (delete && start == 0 && !havingRealText && !beenResetSpan ) {
923
- beenResetSpan = true ;
924
- editable .setSpan (
925
- SELECTION_SPAN ,
926
- indexInText ,
927
- indexInText ,
928
- Spanned .SPAN_MARK_MARK );
929
- }
930
890
editable .insert (
931
891
indexInText , mHintText .subSequence (indexInText , indexInText + 1 ));
932
892
editable .setSpan (
@@ -943,7 +903,6 @@ private void formatMask(final Editable editable, int start, boolean delete) {
943
903
} else if (isMismatchMask (charInStyle , editable .charAt (indexInText ))) {
944
904
editable .delete (indexInText , indexInText + 1 );
945
905
} else {
946
- havingRealText = true ;
947
906
indexInText += 1 ;
948
907
indexInStyle += 1 ;
949
908
}
@@ -960,8 +919,73 @@ private void formatMask(final Editable editable, int start, boolean delete) {
960
919
nextCharIsText = false ;
961
920
indexInText += 1 ;
962
921
indexInStyle += 1 ;
922
+ if (selectionIndex == -1 || indexInText == selectionIndex + 1 ) {
923
+ selectionIndex = indexInText ;
924
+ }
925
+ }
926
+ }
927
+ if (deletion && start == 0 && selectionIndex != -1 ) {
928
+ editable .setSpan (
929
+ SELECTION_SPAN , selectionIndex , selectionIndex , Spanned .SPAN_MARK_MARK );
930
+ }
931
+ }
932
+
933
+ private int clearPlaceholders (Editable editable , int start ) {
934
+ IPlaceholderSpan [] spans ;
935
+ if (start > 0 ) {
936
+ IPlaceholderSpan [] left = editable .getSpans (0 , start , IPlaceholderSpan .class );
937
+ IPlaceholderSpan [] right ;
938
+ if (start >= editable .length ()) {
939
+ right = EMPTY_SPANS ;
940
+ } else {
941
+ right = editable .getSpans (start , editable .length (), IPlaceholderSpan .class );
942
+ }
943
+ if (left .length == start ) {
944
+ start = 0 ;
945
+ spans = new IPlaceholderSpan [left .length + right .length ];
946
+ System .arraycopy (left , 0 , spans , 0 , left .length );
947
+ System .arraycopy (right , 0 , spans , left .length , right .length );
948
+ } else if (left .length > 0 ) {
949
+ mComparator .mEditable = editable ;
950
+ Arrays .sort (left , mComparator );
951
+ mComparator .mEditable = null ;
952
+ int last = start - 1 ;
953
+ int index ;
954
+ for (index = left .length - 1 ; index >= 0 ; index --) {
955
+ int spanStart = editable .getSpanStart (left [index ]);
956
+ if (last != spanStart ) {
957
+ last += 1 ;
958
+ index += 1 ;
959
+ break ;
960
+ }
961
+ last = spanStart - 1 ;
962
+ }
963
+ start = last ;
964
+ int leftLength = left .length - index ;
965
+ if (leftLength == 0 ) {
966
+ spans = right ;
967
+ } else {
968
+ spans = new IPlaceholderSpan [leftLength + right .length ];
969
+ System .arraycopy (left , index , spans , 0 , leftLength );
970
+ System .arraycopy (right , 0 , spans , leftLength , right .length );
971
+ }
972
+ } else {
973
+ spans = right ;
974
+ }
975
+ } else {
976
+ spans = editable .getSpans (0 , editable .length (), IPlaceholderSpan .class );
977
+ }
978
+ if (spans .length > 0 ) {
979
+ if (spans .length == editable .length () - start ) {
980
+ editable .delete (start , editable .length ());
981
+ if (start == 0 && isNeedClearText ()) {
982
+ return -1 ;
983
+ }
984
+ } else {
985
+ clearNonEmptySpans (editable , spans );
963
986
}
964
987
}
988
+ return start ;
965
989
}
966
990
967
991
private boolean isNeedClearText () {
0 commit comments