Skip to content

Commit 2b8e9e7

Browse files
committed
Improved efficiency && Improved experience consistency
1 parent 1e109a6 commit 2b8e9e7

File tree

1 file changed

+101
-77
lines changed

1 file changed

+101
-77
lines changed

core/src/main/java/me/dkzwm/widget/fet/FormattedEditText.java

Lines changed: 101 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ public class FormattedEditText extends AppCompatEditText {
7070
public static final int GRAVITY_BOTTOM = 2;
7171
private static final Object SELECTION_SPAN = new Object();
7272
private static final InputFilter[] EMPTY_FILTERS = new InputFilter[0];
73+
private static final IPlaceholderSpan[] EMPTY_SPANS = new IPlaceholderSpan[0];
7374
private static final Spanned EMPTY_SPANNED = new SpannedString("");
7475
private static final char DEFAULT_PLACE_HOLDER = ' ';
7576
private static final char DEFAULT_MARK = '*';
@@ -306,12 +307,10 @@ public boolean onTouchEvent(MotionEvent event) {
306307
&& Math.abs(mDownPoint[1] - y) <= mTouchSlop) {
307308
if (mClearClickListener != null) {
308309
if (!mClearClickListener.onClearClick(this, mClearDrawable)) {
309-
event.setAction(MotionEvent.ACTION_CANCEL);
310-
clearText();
310+
clearTextInTouch(event);
311311
}
312312
} else {
313-
event.setAction(MotionEvent.ACTION_CANCEL);
314-
clearText();
313+
clearTextInTouch(event);
315314
}
316315
super.onTouchEvent(event);
317316
return true;
@@ -401,7 +400,8 @@ public int getHintColor() {
401400
return mHintColor;
402401
}
403402

404-
private void clearText() {
403+
private void clearTextInTouch(MotionEvent event) {
404+
event.setAction(MotionEvent.ACTION_CANCEL);
405405
Editable editable = getText();
406406
if (editable != null) {
407407
editable.clear();
@@ -714,7 +714,7 @@ private void formatTextWhenDelete(final Editable editable, int start, int before
714714
if (mMode < MODE_MASK) {
715715
final boolean deletedLast = start >= editable.length();
716716
if (!deletedLast) {
717-
formatDefined(editable, start);
717+
formatDefined(editable, start, true);
718718
} else {
719719
for (int i = start; i > 0; i--) {
720720
final char sub = editable.charAt(i - 1);
@@ -758,7 +758,7 @@ private void formatTextWhenAppend(final Editable editable, int start, int before
758758
if (mMode < MODE_MASK) {
759759
boolean appendedLast = start > mHolders[mHolders.length - 1].index;
760760
if (!appendedLast) {
761-
formatDefined(editable, start);
761+
formatDefined(editable, start, false);
762762
}
763763
} else {
764764
formatMask(editable, start, false);
@@ -815,95 +815,63 @@ private char findPlaceholder(int index) {
815815
return 0;
816816
}
817817

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;
826822
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()) {
829825
break;
830826
}
831-
char placeholder = findPlaceholder(indexInEditable);
827+
char placeholder = findPlaceholder(indexInText);
832828
if (placeholder != 0) {
833-
editable.insert(indexInEditable, String.valueOf(placeholder));
829+
editable.insert(indexInText, String.valueOf(placeholder));
834830
editable.setSpan(
835831
new PlaceholderSpan(),
836-
indexInEditable,
837-
indexInEditable + 1,
832+
indexInText,
833+
indexInText + 1,
838834
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+
}
840843
} else {
841-
indexInEditable += 1;
844+
indexInText += 1;
842845
}
843846
}
847+
if (deletion && start == 0 && selectionIndex != -1) {
848+
editable.setSpan(
849+
SELECTION_SPAN, selectionIndex, selectionIndex, Spanned.SPAN_MARK_MARK);
850+
}
844851
}
845852

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;
880857
}
881-
if (delete
858+
if (deletion
882859
&& start == editable.length()
883860
&& ((mMode == MODE_MASK && mEmptyPlaceholder == 0)
884861
|| (mMode == MODE_HINT && mHintText == null))) {
885862
return;
886863
}
887864
int indexInStyle = start + rangeCountEscapeChar(start);
888865
int indexInText = start;
866+
int selectionIndex = -1;
889867
boolean nextCharIsText = false;
890-
boolean havingRealText = false;
891-
boolean beenResetSpan = false;
892868
final int styleLength = mFormatStyle.length();
893869
while (indexInStyle < styleLength) {
894870
char charInStyle = mFormatStyle.charAt(indexInStyle);
895871
if (!nextCharIsText && isMaskChar(charInStyle)) {
896872
if (indexInText >= editable.length()) {
897873
if (mMode == MODE_MASK) {
898874
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-
}
907875
editable.insert(indexInText, String.valueOf(mEmptyPlaceholder));
908876
editable.setSpan(
909877
new EmptyPlaceholderSpan(),
@@ -919,14 +887,6 @@ private void formatMask(final Editable editable, int start, boolean delete) {
919887
if (mHintText == null) {
920888
break;
921889
}
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-
}
930890
editable.insert(
931891
indexInText, mHintText.subSequence(indexInText, indexInText + 1));
932892
editable.setSpan(
@@ -943,7 +903,6 @@ private void formatMask(final Editable editable, int start, boolean delete) {
943903
} else if (isMismatchMask(charInStyle, editable.charAt(indexInText))) {
944904
editable.delete(indexInText, indexInText + 1);
945905
} else {
946-
havingRealText = true;
947906
indexInText += 1;
948907
indexInStyle += 1;
949908
}
@@ -960,8 +919,73 @@ private void formatMask(final Editable editable, int start, boolean delete) {
960919
nextCharIsText = false;
961920
indexInText += 1;
962921
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);
963986
}
964987
}
988+
return start;
965989
}
966990

967991
private boolean isNeedClearText() {

0 commit comments

Comments
 (0)