I didn't want to create a question for this, but I can't figure out what's happening.
I have a checkbox where the enabled state is bound to a variable, checkboxEnabled in a ViewModel. This variable is set to true, but the checkbox is somehow disabled.
Debugging steps:
- When I get the enabled state of the checkbox view from my fragment in
OnResume, it also saystrue, even though the checkbox is clearly disabled. - When I get the enabled state of the checkbox view in an onClickListener of another view, it does say
false. However, thecheckboxEnabledvariable in my ViewModel is stilltruehere. - If I enable the checkbox in
onViewCreated, it is still disabled. - I've tried working with different bindings between the xml and
MyViewModel, none of which seem to work, so it might be an issue with the databinding.
Why is my checkbox disabled if I don't set checkboxEnabled to false anywhere in my code? Could it just be an issue linking the view model with the xml?
fragment_my.xml:
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MyFragment">
<data>
<variable
name="viewModel"
type=".MyViewModel" />
</data>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingStart="@dimen/activity_horizontal_margin"
android:paddingEnd="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin" >
<CheckBox
android:id="@ id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:checked="@={viewModel.checkboxChecked}"
android:enabled="@{viewModel.checkboxEnabled}"
android:text="This is a checkbox" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Start"
android:id="@ id/start_button"
android:layout_below="@id/checkbox" />
</RelativeLayout>
</layout>
MyFragment.kt:
class MyFragment() : Fragment() {
private lateinit var viewModel: MyViewModel
private var _binding: FragmentMyBinding? = null
private val binding get() = _binding!!
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel = ViewModelProvider(this).get(MyViewModel::class.java )
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
_binding = FragmentMyBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val checkbox = view.findViewById<CheckBox>(R.id.checkbox)
checkbox.isEnabled = true // doesn't stay enabled
startButton = view.findViewById(R.id.start_button)
startButton.setOnClickListener {
Log.d("Checkbox enabled", "${checkbox.isEnabled}") // logs `false`
Log.d("ViewModel checkbox enabled", "${viewModel.checkboxEnabled}") // logs `true`
}
}
override fun onResume() {
super.onResume()
val checkbox = activity?.findViewById<CheckBox>(R.id.checkbox)
Log.d("Resumed", "${checkbox?.isEnabled}") // logs `true`
}
}
And MyViewModel.kt:
class SensorGnssFragmentViewModel(application: Application) : AndroidViewModel(application) {
var checkboxChecked = false
var checkboxEnabled = true
...
}
CodePudding user response:
I think you have forgotten to pass the viewModel object to the layout with data binding like that _binding.viewModel = viewModel
Also, I'm confused with using onCreate and onCreateView, you can unify them to guarantee that viewModel is initialized and passed to the layout.
So, update the onCreateView to be like that..
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
viewModel = ViewModelProvider(this).get(MyViewModel::class.java )
_binding = FragmentMyBinding.inflate(inflater, container, false)
_binding.viewModel = viewModel
return binding.root
}
Another trick can help..
Try to replace the Boolean variables in the viewModel with ObservableBoolean to be:
val checkboxEnabled : ObservableBoolean = ObservableBoolean()
So, If you want to change check/enable the check box, just set and unset the observable object like that..
override fun onResume() {
super.onResume()
viewModel.checkboxEnabled.set(true)
}
