Kotlin addTextChangeListener lambda?

Solution 1:

addTextChangedListener() takes a TextWatcher which is an interface with 3 methods. What you wrote would only work if TextWatcher had only 1 method. I'm going to guess the error you're getting relates to your lambda not implementing the other 2 methods. You have 2 options going forward.

  1. Ditch the lambda and just use an anonymous inner class
    editText.addTextChangedListener(object : TextWatcher {
      override fun afterTextChanged(s: Editable?) {
      }
    
      override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
      }
    
      override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
      }
    })
  1. Create an extension method so you can use a lambda expression:
    fun EditText.afterTextChanged(afterTextChanged: (String) -> Unit) {
        this.addTextChangedListener(object : TextWatcher {
          override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
          }
    
          override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
          }
    
          override fun afterTextChanged(editable: Editable?) {
            afterTextChanged.invoke(editable.toString())
          }
        })
    }

And then use the extension like so:

editText.afterTextChanged { doSomethingWithText(it) }

Solution 2:

Add this core ktx dependence

implementation 'androidx.core:core-ktx:1.0.0'

You simply have to do

passwordEditText.doAfterTextChanged{ }

Solution 3:

A bit old, but using Kotlin Android extensions you can do something like that:

editTextRequest.textChangedListener {
            afterTextChanged {
                // Do something here...
            }
}

No extra code needed, just add:

implementation 'androidx.core:core-ktx:1.0.0'

Solution 4:

hope this Kotlin sample help making it clear:

class MainFragment : Fragment() {

    private lateinit var viewModel: MainViewModel

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                          savedInstanceState: Bundle?): View {
    val view = inflater.inflate(R.layout.main_fragment, container, false)

    view.user.addTextChangedListener(object : TextWatcher {
        override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {

        }

        override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {

        }

        override fun afterTextChanged(s: Editable) {
                userLayout.error =
                        if (s.length > userLayout.counterMaxLength) {
                            "Max character length is: ${userLayout.counterMaxLength}"
                        } else null
        }
    })
    return view
}

override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)
    viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
    // TODO: Use the ViewModel
   }
}

With this XML layout:

<android.support.design.widget.TextInputLayout
    android:id="@+id/userLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:counterMaxLength="5"
    app:counterEnabled="true"
    android:hint="user_name">

    <android.support.design.widget.TextInputEditText
        android:id="@+id/user"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</android.support.design.widget.TextInputLayout>

And this Gradle:

android {
    compileSdkVersion 'android-P'
...
}
    api 'com.android.support:design:28.0.0-alpha1'

    implementation 'com.android.support:appcompat-v7:28.0.0-alpha1' // appcompat library

Solution 5:

Test it :

passwordEditText.addTextChangedListener(object:TextWatcher{
    override fun afterTextChanged(s: Editable?) { }

    override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { }

    override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { }
})