Kotlin addTextChangeListener แลมด้า?


109

คุณสร้างนิพจน์แลมบ์ดาสำหรับ EditText addTextChangeListener ใน Kotlin ได้อย่างไร ด้านล่างแสดงข้อผิดพลาด:

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

3
มันให้ข้อผิดพลาดอะไร?
voddan

คำตอบ:


257

addTextChangedListener()ใช้TextWatcherซึ่งเป็นอินเทอร์เฟซที่มี 3 วิธี สิ่งที่คุณเขียนจะใช้ได้ผลTextWatcherก็ต่อเมื่อมีเพียง 1 วิธีเท่านั้น ฉันจะเดาข้อผิดพลาดที่คุณได้รับเกี่ยวข้องกับแลมด้าของคุณที่ไม่ได้ใช้อีก 2 วิธี คุณมี 2 ตัวเลือกนับจากนี้

  1. ทิ้งแลมด้าและใช้คลาสภายในที่ไม่ระบุชื่อ
    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. สร้างวิธีการขยายเพื่อให้คุณสามารถใช้นิพจน์แลมบ์ดา:
    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())
          }
        })
    }

จากนั้นใช้ส่วนขยายดังนี้:

editText.afterTextChanged { doSomethingWithText(it) }

4
ไม่แน่ใจว่าเป็นความชอบส่วนตัวหรือสไตล์ที่ดีกว่า แต่ฟังก์ชันส่วนขยายของคุณสามารถแปลงเป็นเนื้อความนิพจน์ได้ ( fun foo() = ...)
เอฟจอร์จ

7
@ mEQ5aNLrK3lqs3kfSa5HbvsTWe0nIu คุณคิดถูกแล้วที่แปลงได้ อย่างไรก็ตามสำหรับฟังก์ชันที่ยาวกว่าหนึ่งบรรทัดฉันชอบให้มีวงเล็บล้อมรอบเพื่อทำเครื่องหมายอย่างชัดเจนว่าฟังก์ชันเริ่มต้นและหยุด ฉันเชื่อว่ามันช่วยเพิ่มความสามารถในการอ่าน แต่มันเป็นสไตล์ที่ชอบ ฉันคิดว่ามันสามารถโต้แย้งได้ทั้งสองทาง :)
Andrew Orobator

2
หมดความสนใจ: โทรafterTextChanged.invoke(...)แทนทำไมafterTextChanged(...)?
Felix D.

สิ่งนี้ได้ผลสำหรับฉัน ฉันชอบตัวเลือกที่ 2 สำหรับการใช้ซ้ำ
Onie Maniego

24

เก่าไปหน่อย แต่เมื่อใช้ส่วนขยายของ Kotlin Android คุณสามารถทำสิ่งนั้นได้:

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

ไม่จำเป็นต้องใช้รหัสเพิ่มเติมเพียงเพิ่ม:

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

4
มันไม่ได้ผลสำหรับฉันแม้ว่าจะปรับโครงสร้างเป็น android X แล้วก็ตามเดาว่าฉันทำอะไรผิดหรือเปล่า?
Nícolas Schirmer

3
ไม่ทำงานสำหรับฉันเช่นกัน ดูเหมือนว่า KTX จะไม่มีส่วนขยายนี้อีกต่อไปอย่างไรก็ตาม KAndroid โซลูชันทำงานได้อย่างสมบูรณ์แบบ
Igor Wojda

2
ด้วย ktx: 1.0.1 คุณสามารถใช้developer.android.com/reference/kotlin/androidx/core/widget/…
ingyesid

implementation "androidx.core:core-ktx:1.2.0"->edt.addTextChangedListener(afterTextChanged = { /*dosomething*/ })
Dr.jacky

24

เพิ่มการพึ่งพา ktx หลักนี้

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

คุณก็ต้องทำ

passwordEditText.doAfterTextChanged{ }


14

ทดสอบ:

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

    }

})

12

หวังว่า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

ถ้าคุณใช้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


4

ขอโทษที่มาสาย!

หากคุณเพิ่มลงimplementation 'androidx.core:core-ktx:1.1.0'ในไฟล์ build.gradle ของโมดูลคุณสามารถใช้ไฟล์

etPlayer1.doOnTextChanged { text, start, count, after -> // Do stuff }

2

อีกทางเลือกหนึ่งคือKAndroidห้องสมุด -

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

แล้วคุณจะทำอะไรแบบนี้ ...

editText.textWatcher { afterTextChanged { doSomething() } }

เห็นได้ชัดว่าการใช้ไลบรารีทั้งหมดเพื่อแก้ปัญหาของคุณนั้นมากเกินไป แต่ยังมาพร้อมกับส่วนขยายที่มีประโยชน์อื่น ๆ อีกมากมายที่กำจัดโค้ดสำเร็จรูปใน Android SDK


2

คุณสามารถใช้พารามิเตอร์ที่มีชื่อของ 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

เพิ่มการพึ่งพาหลัก ktx

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

และคุณสามารถใช้แบบนี้ได้

    edit_text.addTextChangedListener { it: Editable? ->
      // Do your stuff here
    }

-9

นี่ดูเรียบร้อย:

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

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

1
ฉันไม่รู้จริงๆกับพวกคุณ แต่คำตอบของฉันได้ผลสำหรับฉันและสั้นกว่าคำตอบด้านบนและด้านล่าง ..
LEMUEL ADANE

1
สิ่งนี้ทำงานตามที่รหัสตั้งใจจะให้ดำเนินการเมื่อกดเสร็จสิ้น ฉันแก้ไขรหัสโดยวางขนมปังนอกเงื่อนไขและดูเหมือนว่าจะเริ่มทำงานเมื่อกด TAB / DONE / etc เท่านั้น แต่ไม่ใช่อักขระอื่น
Onie Maniego
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.