@TestTargetNew( level = TestLevel.COMPLETE, method = "onKeyUp", args = { android.view.View.class, android.text.Editable.class, int.class, android.view.KeyEvent.class }) public void testReleaseKey() { final CharSequence str = "123456"; final MetaKeyKeyListener numberKeyListener = new DateKeyListener(); final View view = new ImageView(getContext()); final Editable content = Editable.Factory.getInstance().newEditable(str); content.setSpan(Selection.SELECTION_START, 0, 0, Spanned.SPAN_POINT_POINT); content.setSpan(Selection.SELECTION_END, 0, 0, Spanned.SPAN_POINT_POINT); numberKeyListener.onKeyUp( view, content, KeyEvent.KEYCODE_0, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0)); assertEquals(str.charAt(0), content.charAt(0)); content.setSpan(Selection.SELECTION_START, 1, 1, Spanned.SPAN_POINT_POINT); content.setSpan(Selection.SELECTION_END, 1, 1, Spanned.SPAN_POINT_POINT); numberKeyListener.onKeyUp( view, content, KeyEvent.KEYCODE_2, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_2)); assertEquals(str.charAt(1), content.charAt(1)); content.setSpan(Selection.SELECTION_START, 3, 3, Spanned.SPAN_POINT_POINT); content.setSpan(Selection.SELECTION_END, 3, 3, Spanned.SPAN_POINT_POINT); numberKeyListener.onKeyUp( view, content, KeyEvent.KEYCODE_3, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_3)); assertEquals(str.charAt(3), content.charAt(3)); }
@Override public void onTextChanged(CharSequence s, int start, int before, int count) { Editable text = getText(); if (text == null) return; clearSelections(); updateHint(); TokenImageSpan[] spans = text.getSpans(start - before, start - before + count, TokenImageSpan.class); for (TokenImageSpan token : spans) { int position = start + count; if (text.getSpanStart(token) < position && position <= text.getSpanEnd(token)) { // We may have to manually reverse the auto-complete and remove the extra ,'s int spanStart = text.getSpanStart(token); int spanEnd = text.getSpanEnd(token); removeToken(token, text); // The end of the span is the character index after it spanEnd--; if (spanEnd >= 0 && text.charAt(spanEnd) == ',') { text.delete(spanEnd, spanEnd + 1); } if (spanStart >= 0 && text.charAt(spanStart) == ',') { text.delete(spanStart, spanStart + 1); } } } }
public static void format(Editable text) { // Here, "root" means the position of "'": // 0'3, 0'90, and +81'-90 // (dash will be deleted soon, so it is actually +81'90). int rootIndex = 1; int length = text.length(); if (length > 3 && text.subSequence(0, 3).toString().equals("+81")) { rootIndex = 3; } else if (length < 1 || text.charAt(0) != '0') { return; } CharSequence saved = text.subSequence(0, length); // Strip the dashes first, as we're going to add them back int i = 0; while (i < text.length()) { if (text.charAt(i) == '-') { text.delete(i, i + 1); } else { i++; } } length = text.length(); int dashposition; i = rootIndex; int base = 0; while (i < length) { char ch = text.charAt(i); if (!Character.isDigit(ch)) { text.replace(0, length, saved); return; } short value = FORMAT_MAP[base + ch - '0']; if (value < 0) { if (value <= -100) { text.replace(0, length, saved); return; } int dashPos2 = rootIndex + (Math.abs(value) % 10); if (length > dashPos2) { text.insert(dashPos2, "-"); } int dashPos1 = rootIndex + (Math.abs(value) / 10); if (length > dashPos1) { text.insert(dashPos1, "-"); } break; } else { base = value; i++; } } if (length > 3 && rootIndex == 3) { text.insert(rootIndex, "-"); } }
public void handleTag( final boolean opening, final String tag, final Editable output, final XMLReader xmlReader) { if (TAG_DEL.equalsIgnoreCase(tag)) { if (opening) startSpan(new StrikethroughSpan(), output); else endSpan(StrikethroughSpan.class, output); return; } if (TAG_UL.equalsIgnoreCase(tag) || TAG_OL.equalsIgnoreCase(tag)) { if (opening) { listElements.add(new ListSeparator(TAG_OL.equalsIgnoreCase(tag))); } else if (!listElements.isEmpty()) { listElements.removeLast(); } if (!opening && listElements.isEmpty()) output.append('\n'); return; } if (TAG_LI.equalsIgnoreCase(tag) && opening && !listElements.isEmpty()) { listElements.getLast().append(output, listElements.size()); return; } if (TAG_CODE.equalsIgnoreCase(tag)) { if (opening) startSpan(new TypefaceSpan("monospace"), output); else endSpan(TypefaceSpan.class, output); } if (TAG_PRE.equalsIgnoreCase(tag)) { output.append('\n'); if (opening) startSpan(new TypefaceSpan("monospace"), output); else endSpan(TypefaceSpan.class, output); } if ((TAG_ROOT.equalsIgnoreCase(tag) || TAG_HTML.equalsIgnoreCase(tag)) && !opening) { // Remove leading newlines while (output.length() > 0 && output.charAt(0) == '\n') output.delete(0, 1); // Remove trailing newlines int last = output.length() - 1; while (last >= 0 && output.charAt(last) == '\n') { output.delete(last, last + 1); last = output.length() - 1; } QuoteSpan[] quoteSpans = output.getSpans(0, output.length(), QuoteSpan.class); for (QuoteSpan span : quoteSpans) { int start = output.getSpanStart(span); int end = output.getSpanEnd(span); output.removeSpan(span); output.setSpan(new ReplySpan(), start, end, SPAN_EXCLUSIVE_EXCLUSIVE); } } }
private void sanitizeBetween() { // Find the last chip. MemberChip[] recips = getSortedRecipients(); if (recips != null && recips.length > 0) { MemberChip last = recips[recips.length - 1]; MemberChip beforeLast = null; if (recips.length > 1) { beforeLast = recips[recips.length - 2]; } int startLooking = 0; int end = getSpannable().getSpanStart(last); if (beforeLast != null) { startLooking = getSpannable().getSpanEnd(beforeLast); Editable text = getText(); if (startLooking == -1 || startLooking > text.length() - 1) { // There is nothing after this chip. return; } if (text.charAt(startLooking) == ' ') { startLooking++; } } if (startLooking >= 0 && end >= 0 && startLooking < end) { getText().delete(startLooking, end); } } }
public static char[] getPassword(Editable s) { int length = s.length(); char[] password = new char[length]; for (int i = 0; i < length; i++) { password[i] = s.charAt(i); } return password; }
/** * 移除字符</br> * * @param c */ private void removeChar(char c) { Editable editable = mEditText.getText(); if (editable.length() <= 0) { return; } if (editable.charAt(editable.length() - 1) == c) { editable.delete(editable.length() - 1, editable.length()); } }
private int findLineEnd(Editable text, int current) { if (DBG) { Log.d(LOG_TAG, "--- findLineEnd: curr:" + current + ", length:" + text.length()); } int pos = current; for (; pos < text.length(); pos++) { if (pos > 0 && text.charAt(pos - 1) == '\n') { break; } } return pos; }
public void insertMention(int uid) { UserVM user = users().get(uid); String name = user.getName().get(); String nick = user.getNick().get(); Editable text = messageEditText.getText(); if (text.length() > 0 && text.charAt(text.length() - 1) != ' ') text.append(" "); String mentionString = ((nick != null && !nick.isEmpty()) ? "@" + nick : name) + ": "; text.append(mentionString); messageEditText.requestFocus(); keyboardUtils.setImeVisibility(messageEditText, true); }
public String getUnmaskedText() { Editable text = super.getText(); if (mask != null && !mask.isEmpty()) { Editable unMaskedText = new SpannableStringBuilder(); for (Integer index : listValidCursorPositions) { if (text != null) { unMaskedText.append(text.charAt(index)); } } if (format != null && !format.isEmpty()) return formatText(unMaskedText.toString(), format); else return unMaskedText.toString().trim(); } return text.toString().trim(); }
@Override public void onTextChanged(CharSequence s, int start, int before, int count) { if (mIsUpdating) { mIsUpdating = false; return; } Editable editable = mEditText.getText(); String string = s.toString(); int end = count + start; String inserted = string.substring(start, end); if (mAcceptOnlyNumbers && !inserted.matches("[0-9]*") && !string.equalsIgnoreCase("")) { mIsUpdating = true; editable.delete(start, end); // TODO // I need a solution to not set text "again". Changes keyboard and selection mIsUpdating = true; mEditText.setText(mEditText.getText()); mEditText.setSelection(end - 1); return; } int currentLength = s.length(), maxLength = mMask.length(); if (currentLength > maxLength) { mIsUpdating = true; editable.delete(maxLength, currentLength); // TODO // I need a solution to not set text "again". Changes keyboard and selection mIsUpdating = true; mEditText.setText(mEditText.getText()); mEditText.setSelection(maxLength); return; } for (int i = start; i < editable.length(); i++) { char c = mMask.charAt(i); char editableC = editable.charAt(i); if (c != '#' && c != editableC) { mIsUpdating = true; editable.insert(i, String.valueOf(c)); } } }
public boolean onKeyDown(View view, Editable content, int keyCode, KeyEvent event) { int selStart, selEnd; int pref = 0; if (view != null) { pref = TextKeyListener.getInstance().getPrefs(view.getContext()); } { int a = Selection.getSelectionStart(content); int b = Selection.getSelectionEnd(content); selStart = Math.min(a, b); selEnd = Math.max(a, b); } int activeStart = content.getSpanStart(TextKeyListener.ACTIVE); int activeEnd = content.getSpanEnd(TextKeyListener.ACTIVE); // now for the multitap cases... // Try to increment the character we were working on before // if we have one and it's still the same key. int rec = (content.getSpanFlags(TextKeyListener.ACTIVE) & Spannable.SPAN_USER) >>> Spannable.SPAN_USER_SHIFT; if (activeStart == selStart && activeEnd == selEnd && selEnd - selStart == 1 && rec >= 0 && rec < sRecs.size()) { if (keyCode == KeyEvent.KEYCODE_STAR) { char current = content.charAt(selStart); if (Character.isLowerCase(current)) { content.replace(selStart, selEnd, String.valueOf(current).toUpperCase()); removeTimeouts(content); new Timeout(content); // for its side effects return true; } if (Character.isUpperCase(current)) { content.replace(selStart, selEnd, String.valueOf(current).toLowerCase()); removeTimeouts(content); new Timeout(content); // for its side effects return true; } } if (sRecs.indexOfKey(keyCode) == rec) { String val = sRecs.valueAt(rec); char ch = content.charAt(selStart); int ix = val.indexOf(ch); if (ix >= 0) { ix = (ix + 1) % (val.length()); content.replace(selStart, selEnd, val, ix, ix + 1); removeTimeouts(content); new Timeout(content); // for its side effects return true; } } // Is this key one we know about at all? If so, acknowledge // that the selection is our fault but the key has changed // or the text no longer matches, so move the selection over // so that it inserts instead of replaces. rec = sRecs.indexOfKey(keyCode); if (rec >= 0) { Selection.setSelection(content, selEnd, selEnd); selStart = selEnd; } } else { rec = sRecs.indexOfKey(keyCode); } if (rec >= 0) { // We have a valid key. Replace the selection or insertion point // with the first character for that key, and remember what // record it came from for next time. String val = sRecs.valueAt(rec); int off = 0; if ((pref & TextKeyListener.AUTO_CAP) != 0 && TextKeyListener.shouldCap(mCapitalize, content, selStart)) { for (int i = 0; i < val.length(); i++) { if (Character.isUpperCase(val.charAt(i))) { off = i; break; } } } if (selStart != selEnd) { Selection.setSelection(content, selEnd); } content.setSpan(OLD_SEL_START, selStart, selStart, Spannable.SPAN_MARK_MARK); content.replace(selStart, selEnd, val, off, off + 1); int oldStart = content.getSpanStart(OLD_SEL_START); selEnd = Selection.getSelectionEnd(content); if (selEnd != oldStart) { Selection.setSelection(content, oldStart, selEnd); content.setSpan( TextKeyListener.LAST_TYPED, oldStart, selEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); content.setSpan( TextKeyListener.ACTIVE, oldStart, selEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE | (rec << Spannable.SPAN_USER_SHIFT)); } removeTimeouts(content); new Timeout(content); // for its side effects // Set up the callback so we can remove the timeout if the // cursor moves. if (content.getSpanStart(this) < 0) { KeyListener[] methods = content.getSpans(0, content.length(), KeyListener.class); for (Object method : methods) { content.removeSpan(method); } content.setSpan(this, 0, content.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE); } return true; } return super.onKeyDown(view, content, keyCode, event); }