简体   繁体   中英

Move Cursor to next line in a MultiLine EditText after re-attaching TextWatcher

I'm trying to implement a coding IDE in an Android App. I created a Multi Line EditText to write code in. To change colors of keywords, I replace the text in TextWatcher's afterTextChanged() method. The problem is that on typing enter, the cursor does not move to the next line. If I remove the code that's below, everything works fine (typing and moving to new lines).

@Override
public void afterTextChanged(Editable s) {
    String replaceText = codeEditText.getText().toString();
    // Some logic that changes contents of replaceText
    codeEditText.removeTextChangedListener(this);
    codeEditText.setText(Html.fromHtml(replaceText));
    codeEditText.setSelection(codeEditText.length(), codeEditText.length());
    codeEditText.addTextChangedListener(this);
}

I've also tried using s.replace(0, s.length(), Html.fromHtml(replaceText)); , but it doesn't work either. Is there a better way to change the value of EditText from within the TextWatcher, besides the two above (detaching-reattaching, s.replace).

If anyone has similar issues, or is interested -

I figured out the problem, it wasn't with the listener but more so with the HTML parsing portion. Html.fromHtml() has trouble with \\n characters. Even after replacing all the \\n 's with <br> tags, the error persisted. After moving to an approach where I used SpannableStringBuilder to change keyword colors, everything fell into place.

@Override
public void afterTextChanged(Editable s) {
    SpannableStringBuilder ssb = new SpannableStringBuilder(s.toString());

    for (int i = 0; i<keyWords.size(); i++){
        String keyword = keyWords.get(i);
        Pattern pattern = Pattern.compile("\\b"+keyword+"\\b");
        Matcher matcher = pattern.matcher(ssb);
        while(matcher.find()){
            // Have to create a new instance of FgColor for this to work!!
            // KeywordColors is a Hashmap mapping keywords to the color they should be highlighted with
            ForegroundColorSpan fg = new ForegroundColorSpan(keywordColors.get(keyword).getForegroundColor());
            ssb.setSpan(fg, matcher.start(), matcher.end(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
    }

    codeEditText.removeTextChangedListener(this);
    codeEditText.setText(ssb);
    codeEditText.addTextChangedListener(this);

    codeEditText.setSelection(codeEditText.getText().length());

}

Another thing I noticed was when I used one FGspan for multiple words, only the latest word it was applied to actually got colored. So to solve this, create new instances of FGspan for each new word to highlight.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM