This is most simplified example I can show here:
Fragment (in case you need it, but NOT IMPORTANT!!)
class EgFragment:Fragment() {
private lateinit var viewModel: EgViewModel
private lateinit var binding: EgBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = EgBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel = ViewModelProvider(this, ViewModelFactory(requireContext(), this))
.get(EgViewModel::class.java)
binding.setLifecycleOwner(viewLifecycleOwner)
binding.vm = viewModel
}
}
View Model
class EgViewModel: ViewModel() {
val emailInput:MutableLiveData<String> = MutableLiveData("")
val phoneInput:MutableLiveData<String> = MutableLiveData("")
val phoneEnabled:MutableLiveData<Boolean> = MutableLiveData(false)
}
Layout/XML
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="vm"
type="air.EgViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="@+id/email"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@={vm.emailInput}"
app:layout_constraintBottom_toTopOf="@id/phone"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/phone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:enabled="@{vm.emailInput.length()>6}"
android:text="@={vm.phoneInput}"
app:layout_constraintTop_toBottomOf="@id/email" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
OK, this is very simple layout, take note of this line:
android:enabled="@{vm.emailInput.length()>6}"
With this example, after I typing more than 7 chars in email
, it automatically enable 2nd EditText (phone
).
I DO NOT NEED ANY onTextChangeListener
nor onPropertyChangeListener
for this case.
QUESTION:
How to move this line of condition
vm.emailInput.length()>6
into viewModel and remain everything the same without adding any listener?
I TRIED:
Trial 01:
viewModel:
fun updatePhoneEnabled(): Boolean {
return emailInput.value?.length ?: 0 > 6
}
xml:
<EditText
android:id="@+id/phone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:enabled="@{vm.updatePhoneEnabled()}"
android:text="@={vm.phoneInput}"
app:layout_constraintTop_toBottomOf="@id/email" />
This is definitly not working because it will check on init only and not check on every typing.
Trial 02:
xml phone I changed to following:
<EditText
android:id="@+id/phone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:enabled="@{vm.emailInput != null ? vm.updatePhoneEnabled() : false}"
android:text="@={vm.phoneInput}"
app:layout_constraintTop_toBottomOf="@id/email" />
This is looks weired but working solution, because char typed is updating emailInput , thus, it triggered the check on every typing. However, in real scenario, the null-checker that I put in front will be inappropriate. Refer example below.
Why I want to do this
Because my teammate is writing a line of code in this way: (of course this is in real project and I trying to ask question in most simple way)
android:clickable="@{viewmodel.timer <= 0L && viewmodel.taskState == TaskState.NORMAL && (viewmodel.gameInfo.data != null ? viewmodel.parseStringToInt(viewmodel.gameInfo.data.fishAvailable) : 0) > 0}"
I do not know how do you guys think but I honestly do not prefer all condition checking appended in this way. Hopefully I am clear. Please help. Thanks.
You can observe a livedata using Transformations and perform simple actions over the value Check the official docs for more information
You can do the following in your case
val isEnabled = Transformations.map(emailInput) {
it?.apply {
length > 6
}
}
and in your XML file, you can use the isEnabled
just like any other livedata
<EditText
android:id="@+id/phone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:enabled="@{vm.isEnabled}"
android:text="@={vm.phoneInput}"
app:layout_constraintTop_toBottomOf="@id/email" />