Đối với ràng buộc ViewModel, LiveData và dữ liệu
Tôi cần chức năng này EditText
với sự hỗ trợ đa dòng trong ứng dụng ghi chú của tôi. Tôi muốn con trỏ ở cuối văn bản khi người dùng điều hướng đến đoạn có văn bản ghi chú.
Các giải pháp được đề xuất bởi djleop đến gần. Nhưng vấn đề với điều này là, nếu người dùng đặt con trỏ ở đâu đó ở giữa văn bản để chỉnh sửa và bắt đầu nhập, con trỏ sẽ lại nhảy đến cuối văn bản. Điều này xảy ra vìLiveData
sẽ phát ra giá trị mới và con trỏ sẽ nhảy đến cuối văn bản một lần nữa dẫn đến việc người dùng không thể chỉnh sửa văn bản ở đâu đó ở giữa.
Để giải quyết điều này, tôi sử dụng MediatorLiveData
và gán cho nó độ dài String
chỉ một lần bằng cách sử dụng cờ. Điều này sẽ khiến LiveData chỉ đọc giá trị một lần, nghĩa là khi người dùng điều hướng đến đoạn. Sau đó, người dùng có thể đặt con trỏ bất cứ nơi nào họ muốn chỉnh sửa văn bản ở đó.
ViewModel
private var accessedPosition: Boolean = false
val cursorPosition = MediatorLiveData<Event<Int>>().apply {
addSource(yourObject) { value ->
if(!accessedPosition) {
setValue(Event(yourObject.note.length))
accessedPosition = true
}
}
}
Đây yourObject
là một LiveData khác được lấy từ cơ sở dữ liệu chứa văn bản Chuỗi mà bạn đang hiển thị trong EditText
.
Sau đó liên kết nó MediatorLiveData
với EditText của bạn bằng cách sử dụng bộ điều hợp liên kết.
XML
Sử dụng ràng buộc dữ liệu hai chiều để hiển thị văn bản cũng như chấp nhận nhập văn bản.
<!-- android:text must be placed before cursorPosition otherwise we'll get IndexOutOfBounds exception-->
<EditText
android:text="@={viewModel.noteText}"
cursorPosition="@{viewModel.cursorPosition}" />
Bộ điều hợp đóng sách
@BindingAdapter("cursorPosition")
fun bindCursorPosition(editText: EditText, event: Event<Int>?) {
event?.getContentIfNotHandled()?.let { editText.setSelection(it) }
}
Event
lớp học
Các Event
lớp học ở đây cũng giống như một SingleLiveEvent được viết bởi Jose Alcérreca từ Google. Tôi sử dụng nó ở đây để chăm sóc xoay màn hình. Sử dụng một lần duy nhất Event
sẽ đảm bảo rằng con trỏ sẽ không nhảy đến cuối văn bản khi người dùng đang chỉnh sửa văn bản ở đâu đó ở giữa và màn hình xoay. Nó sẽ duy trì cùng một vị trí khi màn hình xoay.
Đây là Event
lớp học:
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
}
Đây là giải pháp phù hợp với tôi và cung cấp trải nghiệm người dùng tốt. Hy vọng nó sẽ giúp trong các dự án của bạn quá.