web-dev-qa-db-ja.com

Kotlin addTextChangeListener lambda?

KotlinでEditText addTextChangeListenerのラムダ式を作成するにはどうすればよいですか?以下にエラーを示します。

passwordEditText.addTextChangedListener { charSequence  ->
    try {
        password = charSequence.toString()
    } catch (error: Throwable) {
        raise(error)
    }
}
63
LEMUEL ADANE

addTextChangedListener()は、3つのメソッドを持つインターフェースである TextWatcher を取ります。あなたが書いたものはTextWatcherにメソッドが1つしかない場合にのみ機能します。取得しているエラーは、ラムダが他の2つのメソッドを実装していないことに関連していると推測します。今後2つのオプションがあります。

1)ラムダを捨てて、匿名の内部クラスを使用する

editText.addTextChangedListener(object : TextWatcher {
  override fun afterTextChanged(p0: Editable?) {
  }

  override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
  }

  override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
  }
})

2)ラムダ式を使用できるように、拡張メソッドを作成します。

fun EditText.afterTextChanged(afterTextChanged: (String) -> Unit) {
    this.addTextChangedListener(object : TextWatcher {
      override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
      }

      override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
      }

      override fun afterTextChanged(editable: Editable?) {
        afterTextChanged.invoke(editable.toString())
      }
    })
}

そして、次のように拡張機能を使用します。

editText.afterTextChanged { doSomethingWithText(it) }
174
Andrew Orobator

このKotlinサンプルが明確にする助けになることを願っています:

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
   }
}

このXMLレイアウトの場合:

<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>

そして、この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
10
Hasan A Yousef

少し古いですが、Kotlin Android拡張機能を使用すると、次のようなことができます。

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

追加のコードは必要ありません。追加するだけです:

implementation 'androidx.core:core-ktx:1.0.0'
8
Efi MK

implementation 'androidx.core:core-ktx:1.1.0-alpha05'を使用する場合、使用できます

For Android.widget.TextView
TextWatcher 
TextView.doBeforeTextChanged(crossinline action: (text: CharSequence?, start: Int, count: Int, after: Int) -> Unit)
Add an action which will be invoked before the text changed.

TextWatcher 
TextView.doOnTextChanged(crossinline action: (text: CharSequence?, start: Int, count: Int, after: Int) -> Unit)
Add an action which will be invoked when the text is changing.

TextWatcher 
TextView.doAfterTextChanged(crossinline action: (text: Editable?) -> Unit)

https://developer.Android.com/reference/kotlin/androidx/core/widget/package-summary#extension-functions

2
ingyesid

試して :

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) {

    }

})
2
Reza Khammary

別の代替手段はKAndroidライブラリです-

implementation 'com.pawegio.kandroid:kandroid:0.8.7@aar'

次に、このようなことをすることができます...

editText.textWatcher { afterTextChanged { doSomething() } }

ライブラリ全体を使用して問題を解決することは明らかに過剰ですが、Android SDKの定型コードを排除するその他の便利な拡張機能も付属しています。

2
nsc9012

Kotlinの名前付きパラメーターを使用できます。

private val beforeTextChangedStub: (CharSequence, Int, Int, Int) -> Unit = { _, _, _, _ -> }
private val onTextChangedStub: (CharSequence, Int, Int, Int) -> Unit = { _, _, _, _ -> }
private val afterTextChangedStub: (Editable) -> Unit = {}

fun EditText.addChangedListener(
        beforeTextChanged: (CharSequence, Int, Int, Int) -> Unit = beforeTextChangedStub,
        onTextChanged: (CharSequence, Int, Int, Int) -> Unit = onTextChangedStub,
        afterTextChanged: (Editable) -> Unit = afterTextChangedStub
) = addTextChangedListener(object : TextWatcher {
    override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {
        beforeTextChanged(charSequence, i, i1, i2)
    }

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

    override fun afterTextChanged(editable: Editable) {
        afterTextChanged(editable)
    }
})
1
Dmitrii Bychkov