ViewModel, LiveData ve Data bağlama için
EditText
Notlar 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, LiveData
yeni 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 MediatorLiveData
ve bu uzunluğunu atamak String
bir 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, yourObject
gö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 Event
sı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, Event
kullanı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 Event
sı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.