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, thecheckboxEnabled
variable in my ViewModel is stilltrue
here. - 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)
}