ViewModel, LiveData ve Data bağlama için
EditTextNotlar uygulamamda çok satırlı destek için bu işlevselliğe ihtiyacım vardı . Kullanıcı not metni olan parçaya gittiğinde imlecin metnin sonunda olmasını istedim.
Djleop tarafından önerilen çözüm yaklaşıyor. Ancak bununla ilgili sorun, kullanıcı imleci düzenleme için metnin ortasına yerleştirir ve yazmaya başlarsa, imlecin metnin sonuna tekrar atlamasıdır. Bunun nedeni, LiveDatayeni değeri yayacağı ve imlecin metnin sonuna atlayacağı ve kullanıcının metni ortada bir yerde düzenleyememesine neden olacağı için oldu.
Bunu çözmek için kullandığım MediatorLiveDatave bu uzunluğunu atamak Stringbir bayrak kullanarak yalnızca bir kez. Bu, LiveData'nın değeri yalnızca bir kez, yani kullanıcı parçaya gittiğinde okumasına neden olur. Bundan sonra kullanıcı imleci oradaki metni düzenlemek istediği herhangi bir yere yerleştirebilir.
ViewModel
private var accessedPosition: Boolean = false
val cursorPosition = MediatorLiveData<Event<Int>>().apply {
addSource(yourObject) { value ->
if(!accessedPosition) {
setValue(Event(yourObject.note.length))
accessedPosition = true
}
}
}
Burada, yourObjectgörüntülediğiniz Dize metnini tutan veritabanından alınan başka bir LiveData EditText.
Ardından MediatorLiveData, ciltleme bağdaştırıcısını kullanarak bunu EditText'inize bağlayın.
XML
Metni görüntülemek ve metin girişini kabul etmek için iki yönlü veri bağlama kullanır.
<!-- android:text must be placed before cursorPosition otherwise we'll get IndexOutOfBounds exception-->
<EditText
android:text="@={viewModel.noteText}"
cursorPosition="@{viewModel.cursorPosition}" />
Ciltleme Adaptörü
@BindingAdapter("cursorPosition")
fun bindCursorPosition(editText: EditText, event: Event<Int>?) {
event?.getContentIfNotHandled()?.let { editText.setSelection(it) }
}
Event sınıf
Buradaki Eventsınıf , Google'dan Jose Alcérreca tarafından yazılmış bir SingleLiveEvent gibidir . Burada ekran döndürme ile ilgilenmek için kullanıyorum. Single'ı kullanmak, Eventkullanıcı metni ortada bir yerde düzenlerken ve ekran döndüğünde imlecin metnin sonuna atlamamasını sağlar. Ekran döndüğünde aynı konumu koruyacaktır.
İşte Eventsınıf:
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
}
Bu benim için çalışan ve iyi bir kullanıcı deneyimi sağlayan bir çözümdür. Umarım projelerinize de yardımcı olur.