Untuk ViewModel, LiveData, dan Data binding
Saya membutuhkan fungsi ini untuk EditTextdengan dukungan multiline di aplikasi catatan saya. Saya ingin kursor di akhir teks ketika pengguna menavigasi ke fragmen yang memiliki teks catatan.
Solusi yang disarankan oleh djleop datang mendekat. Tetapi masalah dengan ini adalah bahwa, jika pengguna meletakkan kursor di suatu tempat di tengah teks untuk mengedit dan mulai mengetik, kursor akan melompat ke ujung teks lagi. Ini terjadi karena LiveDataakan memancarkan nilai baru dan kursor akan melompat ke ujung teks lagi sehingga pengguna tidak dapat mengedit teks di suatu tempat di tengah.
Untuk mengatasi ini, saya menggunakan MediatorLiveDatadan menetapkan panjang Stringhanya sekali menggunakan bendera. Ini akan menyebabkan LiveData membaca nilai hanya sekali, yaitu ketika pengguna menavigasi ke fragmen. Setelah itu pengguna dapat menempatkan kursor di mana saja mereka ingin mengedit teks di sana.
ViewModel
private var accessedPosition: Boolean = false
val cursorPosition = MediatorLiveData<Event<Int>>().apply {
addSource(yourObject) { value ->
if(!accessedPosition) {
setValue(Event(yourObject.note.length))
accessedPosition = true
}
}
}
Di sini, yourObjectadalah LiveData lain yang diambil dari database yang menyimpan teks String yang Anda tampilkan di EditText.
Kemudian ikat ini MediatorLiveDatake EditText Anda menggunakan adaptor yang mengikat.
XML
Menggunakan pengikatan data dua arah untuk menampilkan teks serta menerima input teks.
<!-- android:text must be placed before cursorPosition otherwise we'll get IndexOutOfBounds exception-->
<EditText
android:text="@={viewModel.noteText}"
cursorPosition="@{viewModel.cursorPosition}" />
Binding Adapter
@BindingAdapter("cursorPosition")
fun bindCursorPosition(editText: EditText, event: Event<Int>?) {
event?.getContentIfNotHandled()?.let { editText.setSelection(it) }
}
Event kelas
The Eventkelas di sini adalah seperti SingleLiveEvent ditulis oleh Jose Alcérreca dari Google. Saya menggunakannya di sini untuk menjaga rotasi layar. Menggunakan single Eventakan memastikan bahwa kursor tidak akan melompat ke akhir teks ketika pengguna mengedit teks di suatu tempat di tengah dan layar berputar. Ini akan mempertahankan posisi yang sama ketika layar berputar.
Inilah Eventkelasnya:
open class Event<out T>(private val content: T) {
var hasBeenHandled = false
private set // Allow external read but not write
/**
* Returns the content and prevents its use again.
*/
fun getContentIfNotHandled(): T? {
return if (hasBeenHandled) {
null
} else {
hasBeenHandled = true
content
}
}
/**
* Returns the content, even if it's already been handled.
*/
fun peekContent(): T = content
}
Ini adalah solusi yang berfungsi untuk saya dan memberikan pengalaman pengguna yang baik. Semoga ini membantu dalam proyek Anda juga.