diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java index 2674ca4d159aa..547aad64fc3e5 100644 --- a/core/java/android/widget/CompoundButton.java +++ b/core/java/android/widget/CompoundButton.java @@ -80,6 +80,8 @@ public abstract class CompoundButton extends Button implements Checkable { // to sanitize autofill requests. private boolean mCheckedFromResource = false; + private CharSequence mCustomStateDescription = null; + private static final int[] CHECKED_STATE_SET = { R.attr.state_checked }; @@ -156,6 +158,44 @@ public abstract class CompoundButton extends Button implements Checkable { return mChecked; } + /** @hide */ + @NonNull + protected CharSequence getButtonStateDescription() { + if (isChecked()) { + return getResources().getString(R.string.checked); + } else { + return getResources().getString(R.string.not_checked); + } + } + + /** + * 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); + } + } + + /** @hide **/ + protected void setDefaultStateDescritption() { + if (mCustomStateDescription == null) { + super.setStateDescription(getButtonStateDescription()); + } + } + /** *
Changes the checked state of this button.
* @@ -167,8 +207,6 @@ public abstract class CompoundButton extends Button implements Checkable { mCheckedFromResource = false; mChecked = checked; refreshDrawableState(); - notifyViewAccessibilityStateChangedIfNeeded( - AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); // Avoid infinite recursions if setChecked() is called from a listener if (mBroadcasting) { @@ -189,6 +227,8 @@ public abstract class CompoundButton extends Button implements Checkable { mBroadcasting = false; } + // setStateDescription will not send out event if the description is unchanged. + setDefaultStateDescritption(); } /** diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java index d57b3bc7ad3b4..ac2336c4a10f5 100644 --- a/core/java/android/widget/Switch.java +++ b/core/java/android/widget/Switch.java @@ -52,7 +52,6 @@ import android.view.VelocityTracker; import android.view.ViewConfiguration; import android.view.ViewStructure; import android.view.accessibility.AccessibilityEvent; -import android.view.accessibility.AccessibilityNodeInfo; import android.view.inspector.InspectableProperty; import com.android.internal.R; @@ -852,6 +851,9 @@ public class Switch extends CompoundButton { public void setTextOn(CharSequence textOn) { mTextOn = textOn; requestLayout(); + // Default state is derived from on/off-text, so state has to be updated when on/off-text + // are updated. + setDefaultStateDescritption(); } /** @@ -872,6 +874,9 @@ public class Switch extends CompoundButton { public void setTextOff(CharSequence textOff) { mTextOff = textOff; requestLayout(); + // Default state is derived from on/off-text, so state has to be updated when on/off-text + // are updated. + setDefaultStateDescritption(); } /** @@ -1161,6 +1166,17 @@ public class Switch extends CompoundButton { setChecked(!isChecked()); } + /** @hide **/ + @Override + @NonNull + protected CharSequence getButtonStateDescription() { + if (isChecked()) { + return mTextOn == null ? getResources().getString(R.string.capital_on) : mTextOn; + } else { + return mTextOff == null ? getResources().getString(R.string.capital_off) : mTextOff; + } + } + @Override public void setChecked(boolean checked) { super.setChecked(checked); @@ -1514,23 +1530,6 @@ public class Switch extends CompoundButton { } } - /** @hide */ - @Override - public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) { - super.onInitializeAccessibilityNodeInfoInternal(info); - CharSequence switchText = isChecked() ? mTextOn : mTextOff; - if (!TextUtils.isEmpty(switchText)) { - CharSequence oldText = info.getText(); - if (TextUtils.isEmpty(oldText)) { - info.setText(switchText); - } else { - StringBuilder newText = new StringBuilder(); - newText.append(oldText).append(' ').append(switchText); - info.setText(newText); - } - } - } - private static final FloatProperty