【问题标题】:EditText Filtering Based on Tweet Length基于推文长度的 EditText 过滤
【发布时间】:2015-06-11 05:29:32
【问题描述】:

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

注意,这并不像限制编辑文本字段的长度那么简单。 Twitter 将诸如“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;
    }
}

}

【问题讨论】:

  • 你试过android:maxLength="140"吗?
  • 这行不通。示例:“t.co”是 22 个字符,而不是 3 个字符。仅根据感知长度进行过滤是行不通的。

标签: java android twitter


【解决方案1】:

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

android:maxLength="140"

【讨论】:

  • 正如我上面所说的“注意,这并不像限制编辑文本字段的长度那么简单。Twitter 将“t.co”等链接视为 22 个字符,而不是 3 个。我没有没有看到任何其他有效的例子。”大多数实现都这样做,这是不正确的。在任何有链接的情况下,这样做都会失败。
  • 你可以试试TextWatcher,在TextWatcher的onTextChanged中如果有链接,重新计算edittext的maxLength。
  • 嗯,我认为 onTextChanged 为时已晚。如果我是正确的,过滤应该在任何东西到达 textWatcher 之前发生。尝试删除 textWatcher 中的字符(如果达到限制)将创建一个无限循环。
  • 然后使用 beforeTextChanged
  • 我刚刚检查并能够验证 TextFilter 在调用“beforeTextChanged”之前运行。修改 beforetextchanged 中的文本将创建一个无限循环。见这里:stackoverflow.com/questions/476848/…。我仍在尝试使用 InputFilter 文档来确定需要做什么。
【解决方案2】:

在阅读了更多关于过滤方法的内容后,我终于能够弄清楚了。我相信它可能会更有效,但它现在有效。我希望有任何建议让它变得更好。

当缓冲区要将范围 dstart ... dend of dest 替换为范围 start ... end of source 的新文本时,将调用此方法。返回您希望放置在那里的 CharSequence,如果合适,包括一个空字符串,或 null 以接受原始替换。小心不要拒绝 0 长度的替换,因为这是删除文本时发生的情况。另请注意,您不应尝试从此方法对 dest 进行任何更改;你只能检查它的上下文。注意:如果 source 是 Spanned 或 Spannable 的实例,则应将 source 中的 span 对象复制到过滤结果中(即非空返回值)。为了方便,可以使用copySpansFrom(Spanned, int, int, Class, Spannable, int)。

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;
    }
}

【讨论】:

    猜你喜欢
    • 2012-09-01
    • 2015-04-08
    • 1970-01-01
    • 2018-03-25
    • 2014-02-20
    • 2020-09-03
    • 1970-01-01
    • 2012-07-15
    • 1970-01-01
    相关资源
    最近更新 更多