ispite
ispite

Reputation: 107

onTextChanged fires twice due to two super class overrides

I make custom view and adding a TextWatcher, but the onTextChanged method is also on TextView. And when i override it, it applies to 2 super classes. Is it possible override only one super class?

class PhoneEditText(context: Context, attrs: AttributeSet?) : AppCompatEditText(context, attrs!!),
    TextWatcher {

    override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}

    override fun onTextChanged(charSequence: CharSequence, start: Int, before: Int, count: Int) {
        Timber.d("onTextChanged count = $count")
    }

    override fun afterTextChanged(editable: Editable) {}

enter image description here

Upvotes: 0

Views: 62

Answers (3)

Yogesh Rewani
Yogesh Rewani

Reputation: 299

class PhoneEditText(context: Context, attrs: AttributeSet?) : AppCompatEditText(context, attrs!!),
TextWatcher {

private val textWatcherDelegate = TextWatcherDelegate()

init {
    addTextChangedListener(textWatcherDelegate)
}

override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}

override fun onTextChanged(charSequence: CharSequence, start: Int, before: Int, count: Int) {
    textWatcherDelegate.onTextChanged(charSequence, start, before, count)
}

override fun afterTextChanged(editable: Editable) {}

private inner class TextWatcherDelegate : TextWatcher {
    override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}

    override fun onTextChanged(charSequence: CharSequence, start: Int, before: Int, count: Int) {
        Timber.d("onTextChanged count = $count")
        // Your custom onTextChanged logic
    }

    override fun afterTextChanged(editable: Editable) {}
}

}

By doing this, you can have custom behavior for the onTextChanged method within the TextWatcher interface without affecting the superclass implementations.

Upvotes: 1

Tenfour04
Tenfour04

Reputation: 93609

I don’t recommend this pattern of a class implementing its own listener. It leads to confusion and complicated code as you are discovering. This class represents a TextView, so you would never be passing around an instance of it to use as a TextWatcher to attach to other TextViews. Therefore, it doesn’t make logical sense for it to implement TextWatcher. That would be publicly exposing its inner workings which violates the encapsulation principle of OOP. If you want it to use a TextWatcher for the TextView’s own features, you can create an anonymous inner class for that purpose and attach that to this class.

Upvotes: 1

Vahid Hossein Pour
Vahid Hossein Pour

Reputation: 76

you are inheriting from both AppCompatEditText and implementing the TextWatcher interface this means you are extending the behavior of both the AppCompatEditText class and the TextWatcher interface when you override methods like onTextChanged in your custom class, you are actually overriding them for both the superclasses/interfaces you are extending/implementing.

class PhoneEditText(context: Context, attrs: AttributeSet?) : AppCompatEditText(context, attrs!!),
    TextWatcher {

    private var phoneTextWatcher: TextWatcher? = null

    init {
        phoneTextWatcher = object : TextWatcher {
            override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}

            override fun onTextChanged(charSequence: CharSequence, start: Int, before: Int, count: Int) {
                Timber.d("PhoneEditText onTextChanged count = $count")
            }

            override fun afterTextChanged(editable: Editable) {}
        }

        addTextChangedListener(phoneTextWatcher)
    }

    // Rest of your class implementation...
}

Upvotes: 1

Related Questions