InputFilter not behaving correctly

Asked by At

I have the following input filter on my Xamarin.Android app. When created, it sets if the input is caps only, alpha only, numeric only, alpha with separators etc - it's fairly flexible. The code is a direct port of some Java code found on here.

public ICharSequence FilterFormatted(ICharSequence source, int start, int end, ISpanned dest, int dstart, int dend)
    {
        if (source is SpannableStringBuilder)
        {
            var sourceAsSpannableBuilder = (SpannableStringBuilder)source;
            for (var i = end - 1; i >= start; i--)
            {
                if (!isCharacterOk(source.CharAt(i)))
                {
                    sourceAsSpannableBuilder.Delete(i, i + 1);
                }
            }
            return source;
        }
        else
        {
            var filteredStringBuilder = new SpannableStringBuilder();
            for (int i = start; i < end; i++)
            {
                var currentChar = source.CharAt(i);
                if (isCharacterOk(currentChar))
                {
                    filteredStringBuilder.Append(currentChar);
                }
            }
            return filteredStringBuilder;
        }
    }

The isCharacterOK method checks if the character is correct or not (for example the filter for caps only checks if the character is Upper and if Alpha is set). It works happily.

The filter works fine for code going forward (for example, if I type ASDFGjhkl, only ASDFG show in the edittext).

The problem is when I press delete, the dest seems to still include hjkl which means I need to hit delete 5 times before the letter G is removed.

Have I stumbled on a Xamarin bug, an android oddity or is this correct behavior? It seems very strange that dest is somehow picking up characters not in the EditText widget.

1 Answers

1
Leo Zhu - MSFT On Best Solutions

you could change like this:

if (source is SpannableStringBuilder)
    {
        var sourceAsSpannableBuilder = (SpannableStringBuilder)source;
        for (var i = end - 1; i >= start; i--)
        {
            if (!isCharacterOk(source.CharAt(i)))
            {
                sourceAsSpannableBuilder.Delete(i, i + 1);
                //return the new SpannableStringBuilder.
                sourceAsSpannableBuilder = new SpannableStringBuilder(sourceAsSpannableBuilder);
            }
        }
        return sourceAsSpannableBuilder;
    }

the effect like below:

enter image description here