Search code examples
androidtextview

Android TextView setText() vs append() and Editable.Factory


To create a new Editable from a TextView, you need an Editable.Factory:

private final Editable.Factory editableFactory = new Editable.Factory() {
    @Override
    public Editable newEditable(CharSequence source) {
        Log.d("TAG", "newEditable() is called");
    }
};

myTextView.setEditableFactory(editableFactory);

I noticed that newEditable() is only called if append() is called but not when setText() is called, some thing like this:

myTextView.setText("some text");    // does not work
myTextView.append("some text");     // works

Any Idea why this behavior? Thanks


Solution

  • Checkout the append method in TextView.java at line 5731:

    Convenience method to append the specified text to the TextView's display buffer, upgrading it to {@link android.widget.TextView.BufferType#EDITABLE} if it was not already editable.

    append(CharSequence text) will call append(text, 0, text.length()) which contains the following:

    if (!(mText instanceof Editable)) {
        setText(mText, BufferType.EDITABLE);
    }
    

    setText(CharSequence text, BufferType type) calls setText(CharSequence text, BufferType type, boolean notifyBefore, int oldlen).
    This method contains some if statements that will change the functionality depending on the type.
    Line 6156:

    if (type == BufferType.EDITABLE || getKeyListener() != null || needEditableForNotification) {
        createEditorIfNeeded();
        mEditor.forgetUndoRedo();
        Editable t = mEditableFactory.newEditable(text);
        text = t;
        setFilters(t, mFilters);
        InputMethodManager imm = getInputMethodManager();
        if (imm != null) imm.restartInput(this);
    

    Therefore you should be able to use public void setText(CharSequence text, BufferType type) too if you wanted.