ViewModel, LiveData और डेटा बाइंडिंग के लिए
मुझे EditText
अपने नोट्स ऐप में बहुस्तरीय समर्थन के लिए इस कार्यक्षमता की आवश्यकता थी । मुझे पाठ के अंत में कर्सर चाहिए था जब उपयोगकर्ता उस टुकड़े पर नेविगेट करता है जिसमें नोट पाठ होता है।
Djleop द्वारा सुझाया गया समाधान करीब आता है। लेकिन इसके साथ समस्या यह है कि यदि उपयोगकर्ता संपादन के लिए कर्सर को टेक्स्ट के बीच में कहीं रख देता है और टाइप करना शुरू कर देता है, तो कर्सर फिर से टेक्स्ट के अंत में कूद जाएगा। ऐसा इसलिए हुआ क्योंकि LiveData
नए मान का उत्सर्जन होगा और कर्सर पाठ के अंत में फिर से कूद जाएगा जिसके परिणामस्वरूप उपयोगकर्ता पाठ को बीच में कहीं संपादित करने में सक्षम नहीं होगा।
इसे हल करने के लिए, मैं इसका उपयोग करता हूं MediatorLiveData
और इसे String
केवल एक ध्वज का उपयोग करते हुए लंबाई बताता हूं । यह LiveData को केवल एक बार मान पढ़ने के लिए कारण होगा, जब उपयोगकर्ता टुकड़ा करने के लिए नेविगेट करता है। इसके बाद उपयोगकर्ता कर्सर को कहीं भी रख सकता है जहाँ वे पाठ को संपादित करना चाहते हैं।
ViewModel
private var accessedPosition: Boolean = false
val cursorPosition = MediatorLiveData<Event<Int>>().apply {
addSource(yourObject) { value ->
if(!accessedPosition) {
setValue(Event(yourObject.note.length))
accessedPosition = true
}
}
}
यहां, yourObject
एक और LiveData डेटाबेस से पुनर्प्राप्त किया गया है जो स्ट्रिंग पाठ रखता है जिसे आप प्रदर्शित कर रहे हैं EditText
।
फिर इसे MediatorLiveData
बाइंडिंग अडैप्टर का उपयोग करके अपने एडिटटेक्स्ट से बांधें ।
एक्सएमएल
पाठ को प्रदर्शित करने के साथ-साथ पाठ इनपुट को स्वीकार करने के लिए दो-तरफ़ा डेटा बाइंडिंग का उपयोग करता है।
<!-- android:text must be placed before cursorPosition otherwise we'll get IndexOutOfBounds exception-->
<EditText
android:text="@={viewModel.noteText}"
cursorPosition="@{viewModel.cursorPosition}" />
बाइंडिंग एडॉप्टर
@BindingAdapter("cursorPosition")
fun bindCursorPosition(editText: EditText, event: Event<Int>?) {
event?.getContentIfNotHandled()?.let { editText.setSelection(it) }
}
Event
कक्षा
Event
वर्ग एक की तरह है SingleLiveEvent गूगल से जोस Alcérreca ने लिखा है। मैं इसे स्क्रीन रोटेशन की देखभाल के लिए यहां उपयोग करता हूं। सिंगल का उपयोग करने Event
से यह सुनिश्चित हो जाएगा कि जब उपयोगकर्ता टेक्स्ट को बीच में कहीं संपादित कर रहा हो और स्क्रीन घूम जाए तो टेक्स्ट टेक्स्ट के अंत में नहीं जाएगा। स्क्रीन के घूमने पर यह उसी स्थिति को बनाए रखेगा।
यहाँ Event
वर्ग है:
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
}
यह वह समाधान है जो मेरे लिए काम करता है और अच्छा उपयोगकर्ता अनुभव प्रदान करता है। आशा है कि यह आपकी परियोजनाओं में भी मदद करता है।