android together Kotlin addTextChangeListener لامدا؟




kotlin ide (7)

كيف يمكنك بناء تعبير لامدا ل addTextChangeListener EditText في Kotlin؟ أدناه يعطي خطأ:

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

قديم بعض الشيء ، ولكن باستخدام ملحقات Kotlin Android ، يمكنك القيام بشيء من هذا القبيل:

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

لا حاجة إلى رمز إضافي ، فقط أضف:

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

نأمل أن تساعد عينة 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

قم بتجريبه :

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

    }

})

إذا كنت تستخدم 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)

developer.android.com/reference/kotlin/androidx/core/widget/…


بديل آخر هو مكتبة KAndroid -

implementation 'com.pawegio.kandroid:kandroid:[email protected]'

ثم يمكنك أن تفعل شيئا مثل هذا ...

editText.textWatcher { afterTextChanged { doSomething() } }

من الواضح أنه من المفرط استخدام مكتبة بأكملها لحل مشكلتك ، ولكنها تأتي أيضًا مع مجموعة من الإضافات المفيدة الأخرى التي تقضي على كود boilerplate في Android SDK.


addTextChangedListener() يأخذ TextWatcher وهو واجهة مع 3 طرق. ما كتبته لن يعمل إلا إذا كان TextWatcher يحتوي على طريقة واحدة فقط. سأخمن أن الخطأ الذي تتعرض له يتعلق بعدم استخدام lambda للطريقتين الأخريين. لديك 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) قم بإنشاء طريقة تمديد حتى تتمكن من استخدام تعبير lambda:

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

هذا يبدو أنيق:

passwordEditText.setOnEditorActionListener { 
    textView, keyCode, keyEvent ->
    val DONE = 6

    if (keyCode == DONE) {                       
         // your code here
    }
    false
}