How to change/override the Checkbox content description value, when accessibility turned on?

Viewed 1106

I have a checkbox in my activity and provided android:contentDescription="selected". Also in java class provided as below.

checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
    @Override
    public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
        checkbox.setContentDescription(b ? "Selected" : "Not Selected");
    }
});

When i turn on talkback and selected the checkbox, then it says "Checked/Not Checked" instead of "Selected/Not Selected".

It is taking default values of OS (Varies in different manufacturers and OS version) but not provided values. Is there any way, we can fix this issue?

1 Answers

So I ran into this issue a while back and found a rather hacky workaround. Create and use a subclass of CheckBox like this and replace the strings:

public class CustomCheckBox extends CheckBox {

    // constructors...

    @Override
    public CharSequence getAccessibilityClassName() {
        // override to disable the "checkbox" readout
        return CustomCheckBox.class.getSimpleName();
    }

    @Override
    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
        super.onInitializeAccessibilityNodeInfo(info);
        // by setting checkable to false the default checked/unchecked readouts are disabled
        info.setCheckable(false);
        // ...and then you can set whatever you want as a text
        info.setText(getStateDescription());
    }

    @Override
    public void setChecked(boolean checked) {
        if (checked == isChecked()) return;
        super.setChecked(checked);
        // since we've disabled the checked/unchecked readouts
        // we are forced to manually announce changes to the state
        announceForAccessibility(getStateDescription());
    }

    private String getStateDescription() {
        if (isChecked()) {
            return "Custom checked description";
        } else {
            return "Custom unchecked description";
        }
    }
}

Also I should start this off by saying I haven't tried the stuff mentioned below, but it seems that Android R (API 30) adds an official way to override this by adding setStateDescription(CharSequence) to CompoundButton Source Doc

/**
 * This function is called when an instance or subclass sets the state description. Once this
 * is called and the argument is not null, the app developer will be responsible for updating
 * state description when checked state changes and we will not set state description
 * in {@link #setChecked}. App developers can restore the default behavior by setting the
 * argument to null. If {@link #setChecked} is called first and then setStateDescription is
 * called, two state change events will be merged by event throttling and we can still get
 * the correct state description.
 *
 * @param stateDescription The state description.
 */
@Override
public void setStateDescription(@Nullable CharSequence stateDescription) {
    mCustomStateDescription = stateDescription;
    if (stateDescription == null) {
        setDefaultStateDescritption();
    } else {
        super.setStateDescription(stateDescription);
    }
}
Related