Search code examples
androidxamarin.androidandroid-widgetandroid-preferences

Android Checkbox in Custom Preference not updating


I'm attempting to implement a custom CheckBoxPreference - one where, if a user clicks on the actual checkbox it toggles the state, but if they click on the name it opens a preference fragment instead. To do so I've overridden the OnBindView(View view) method, removed the view's Click listener, and am attempting to add an OnClickListener to each of its child views individually. However, the OnClickListener bound to the Android.Support.V7.Widget.AppCompatCheckBox does not update the checkbox's visible state, even though the preference itself has succesfully been saved

protected override void OnBindView(View view)
{       
    base.OnBindView(view);
    view.Clickable = false;
    ViewGroup vg = (ViewGroup)view;
    for (int i = 0; i < vg.ChildCount - 1; i++)
    {
        vg.GetChildAt(i).SetOnClickListener(new DoOpenFragment(this));
    }
    vg.GetChildAt(vg.ChildCount - 1).SetOnClickListener(new DoCheckBoxClick(this)); 
}

private class DoCheckBoxClick : Java.Lang.Object, View.IOnClickListener
{
    private OpenFragmentCheckboxPreference Pref;
    public DoCheckBoxClick(OpenFragmentCheckboxPreference pref)
    {
        Pref = pref;
    }
    public void OnClick(View v)
    {
        var b0 = Pref.GetPersistedBoolean(true);
        Pref.PersistBoolean(!b0);
        var cb = ((v as ViewGroup).GetChildAt(0) as Android.Support.V7.Widget.AppCompatCheckBox);
        var b1 = Pref.GetPersistedBoolean(true);
        cb.Checked = b1;
        Pref.NotifyChanged();
        cb.Invalidate();
    }
}

As you can see, I try to use both the Preference's NotifyChanged method and the actual CheckBox widget's Invalidate method, but neither works. (The extra, unnecessary variables are just for debugging). Any idea what call I might be missing that would actually cause the checkbox to be redrawn and display its correct state? Thank you!


Solution

  • Figured it out - I should have been setting CheckBox.Checked in OnBindView, NOT in the OnClick Listener:

        protected override void OnBindView(View view)
        {
            base.OnBindView(view);
            view.Clickable = false;
            for (int i = 0; i < vg.ChildCount - 1; i++)
            {
                vg.GetChildAt(i).SetOnClickListener(new DoOpenFragment(this));
            }
            ((vg.GetChildAt(vg.ChildCount - 1) as ViewGroup).GetChildAt(0) as Android.Support.V7.Widget.AppCompatCheckBox).Checked = GetPersistedBoolean(true);
            vg.GetChildAt(vg.ChildCount - 1).SetOnClickListener(new DoCheckBoxClick(this));
        }
    
        private class DoCheckBoxClick : Java.Lang.Object, View.IOnClickListener
        {
            private OpenFragmentCheckboxPreference Pref;
            public DoCheckBoxClick(OpenFragmentCheckboxPreference pref)
            {
                Pref = pref;
            }
            public void OnClick(View v)
            {
                var b0 = Pref.GetPersistedBoolean(true);
                Pref.PersistBoolean(!b0);
                Pref.NotifyChanged();
            }
        }