Проблема с окрашиванием текста в EditText

Есть вот такой код для окраски текста:

public class MainActivity extends AppCompatActivity {

    private EditText mEditText;
    private static final Map<Character, Integer> COLORS_MAP = new HashMap<>();

    @Override protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // просто какие-то цвета
        COLORS_MAP.put('a', Color.RED);
        COLORS_MAP.put('b', Color.GREEN);
        COLORS_MAP.put('c', Color.BLUE);
        COLORS_MAP.put('d', Color.MAGENTA);
        COLORS_MAP.put('e', Color.BLUE / 2 + Color.GREEN / 2 - Color.RED / 4);
        COLORS_MAP.put('f', Color.LTGRAY + Color.YELLOW);
        COLORS_MAP.put('g', Color.BLUE + Color.CYAN);
        COLORS_MAP.put('h', Color.YELLOW);
        COLORS_MAP.put('i', Color.DKGRAY + Color.MAGENTA / 16);
        COLORS_MAP.put('j', Color.RED + Color.GREEN);
        COLORS_MAP.put('k', Color.CYAN);

        mEditText = findViewById(R.id.editText);
        mEditText.addTextChangedListener(new TextWatcher() {
            boolean lock = false;
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                if (lock)
                    return;
                if (before == count)
                    return;
                SpannableStringBuilder sb = new SpannableStringBuilder(s);
                for (int i = 0; i < sb.length(); i++) {
                    Integer color = pickColorByChar(sb.charAt(i));
                    if (color == null)
                        color = mEditText.getTextColors().getDefaultColor();
                    sb.setSpan(new ForegroundColorSpan(color), i, i + 1, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
                }
                lock = true;
                mEditText.setText(sb);
                lock = false;
                mEditText.setSelection(start + count);
            }
            @Override
            public void afterTextChanged(Editable s) {}
        });
    }

    @Nullable
    public Integer pickColorByChar(char c) {
        return COLORS_MAP.get(c);
    }
}

Мне в нём не нравится производительность, а именно то, что при каждом вводе символа приходится пробегать текст заново и для каждого символа проставлять цвета.

Почему это надо делать? Потому что следующий код работает не так, как надо:

public class MainActivity extends AppCompatActivity {

    private EditText mEditText;
    private static final Map<Character, Integer> COLORS_MAP = new HashMap<>();

    @Override protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // просто какие-то цвета
        COLORS_MAP.put('a', Color.RED);
        COLORS_MAP.put('b', Color.GREEN);
        COLORS_MAP.put('c', Color.BLUE);
        COLORS_MAP.put('d', Color.MAGENTA);
        COLORS_MAP.put('e', Color.BLUE / 2 + Color.GREEN / 2 - Color.RED / 4);
        COLORS_MAP.put('f', Color.LTGRAY + Color.YELLOW);
        COLORS_MAP.put('g', Color.BLUE + Color.CYAN);
        COLORS_MAP.put('h', Color.YELLOW);
        COLORS_MAP.put('i', Color.DKGRAY + Color.MAGENTA / 16);
        COLORS_MAP.put('j', Color.RED + Color.GREEN);
        COLORS_MAP.put('k', Color.CYAN);

        mEditText = findViewById(R.id.editText);
        mEditText.addTextChangedListener(new TextWatcher() {
            boolean lock = false;
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                if (lock)
                    return;
                if (count < before)
                    return;
                int curPos = start + before;
                char curChar = s.charAt(curPos);
                SpannableStringBuilder sb = new SpannableStringBuilder(s);
                Integer color = pickColorByChar(curChar);
                if (color == null)
                    color = mEditText.getTextColors().getDefaultColor();
                sb.setSpan(new ForegroundColorSpan(color), curPos, curPos + 1, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
                lock = true;
                mEditText.setText(sb);
                lock = false;
                mEditText.setSelection(start + count);
            }
            @Override
            public void afterTextChanged(Editable s) {}
        });
    }

    @Nullable
    public Integer pickColorByChar(char c) {
        return COLORS_MAP.get(c);
    }
}

А именно: при чередовании двух каких-либо символов, все символы в одном слове, написанные до текущего, окрашиваются в цвет предыдущего символа.

введите сюда описание изображения

Почему так происходит?


Ответы (0 шт):