基于推文长度的 EditText 过滤

EditText Filtering Based on Tweet Length

我正在尝试弄清楚如何将编辑文本字段限制为 140 个 Twitter 字符,同时不允许用户输入超过限制。我以为我可以使用下面的代码,但是,我发现它只会在光标位于 editText 字段的末尾时才阻止键入。尽我所能,我无法弄清楚 source 和 dest 的逻辑,以及如何将它们连接成将在 editText 字段中显示的完整字符串。这就是我试图对 fullTextString 执行的操作。

请注意,这并不像限制编辑文本字段的长度那么简单。 Twitter 将 link(例如 "t.co")视为 22 个字符,而不是 3 个字符。我还没有看到任何其他工作示例。

github 此处提供了一个快速克隆的完整示例: https://github.com/tylerjroach/TwitterEditTextLengthFilter

public class TwitterLengthFilter implements InputFilter {
Validator tweetValidator = new Validator();
private final int max;

public TwitterLengthFilter(int max) {
    this.max = max;
}

public CharSequence filter(CharSequence source, int start, int end, Spanned dest,
                           int dstart, int dend) {

    String destString = dest.subSequence(0, dstart).toString();
    String sourceString = source.subSequence(start, end).toString();
    String fullTextString = destString + sourceString;

    if (fullTextString.length() == 0) {
        return "";
    } else if (tweetValidator.getTweetLength(fullTextString) <= max) {
        return null; //keep original
    } else {
        CharSequence returnSource = "";
        for (int i=0; i<sourceString.length(); i++) {
            if (tweetValidator.getTweetLength(destString + source.subSequence(0, i + 1)) <= max) {
                returnSource = source.subSequence(0, i + 1);
            }
        }
        return returnSource;
    }
}

}

尝试将此添加到您的编辑文本中 XML:

android:maxLength="140"

在详细了解过滤方法后,我终于弄明白了。我敢肯定它可以更有效率,但它现在有效。我很乐意提出任何让它变得更好的建议。

This method is called when the buffer is going to replace the range dstart … dend of dest with the new text from the range start … end of source. Return the CharSequence that you would like to have placed there instead, including an empty string if appropriate, or null to accept the original replacement. Be careful to not to reject 0-length replacements, as this is what happens when you delete text. Also beware that you should not attempt to make any changes to dest from this method; you may only examine it for context. Note: If source is an instance of Spanned or Spannable, the span objects in the source should be copied into the filtered result (i.e. the non-null return value). copySpansFrom(Spanned, int, int, Class, Spannable, int) can be used for convenience.

public class TwitterLengthFilter implements InputFilter {
Validator tweetValidator = new Validator();
private final int max;

public TwitterLengthFilter(int max) {
    this.max = max;
}

public CharSequence filter(CharSequence source, int start, int end, Spanned dest,
                           int dstart, int dend) {

    StringBuilder destination = new StringBuilder(dest);
    String sourceString = source.subSequence(start, end).toString();
    String fullTextString = destination.replace(dstart, dend, sourceString).toString();

    Log.v("Full text", fullTextString);

    if (fullTextString.length() == 0) {
        return "";
    } else if (tweetValidator.getTweetLength(fullTextString) <= max) {
        return null; //keep original
    } else {
        CharSequence returnSource = "";
        for (int i=0; i<sourceString.length(); i++) {
            String iterateSource = source.subSequence(0, i + 1).toString();
            StringBuilder iteratedDestination = new StringBuilder(dest);
            iteratedDestination.replace(dstart, dend, iterateSource);
            if (tweetValidator.getTweetLength(iteratedDestination.toString()) <= max) {
                returnSource = source.subSequence(0, i + 1);
            }
        }
        return returnSource;
    }
}