EditText Filtering Based on Tweet Length

93 Views Asked by At

I am trying to figure out how to limit an edit text field to 140 twitter characters, without allowing the user to type over the limit. I thought I had it working with the code below, however, I discovered it only prevents typing if the cursor is at the end of the editText field. As much as I have tried, I cannot figure out the logic of source and dest, and how to concatenate them into the complete string that would be shown in the editText field. This is what I was attempting to do the the fullTextString.

Note, this is not as simple as limiting the length of the edit text field. Twitter considers a link such as "t.co" as 22 characters, not 3. I haven't seen any other working examples.

A full example to quickly clone is on github here: 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;
    }
}

}

2

There are 2 best solutions below

0
On BEST ANSWER

After reading more into the filter method I was finally able to figure it out. I'm sure it could be more efficient, but it works for now. I would love any suggestions to make it better.

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

Try adding this to your edit text XML:

android:maxLength="140"