Merge "change CompoundButton button to use the accessibility state API"

This commit is contained in:
Yinglei Wang
2019-11-20 18:37:31 +00:00
committed by Android (Google) Code Review
5 changed files with 88 additions and 20 deletions

View File

@@ -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());
}
}
/**
* <p>Changes the checked state of this button.</p>
*
@@ -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();
}
/**

View File

@@ -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<Switch> THUMB_POS = new FloatProperty<Switch>("thumbPos") {
@Override
public Float get(Switch object) {

View File

@@ -17,6 +17,7 @@
package android.widget;
import android.annotation.FloatRange;
import android.annotation.NonNull;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
@@ -24,6 +25,8 @@ import android.graphics.drawable.LayerDrawable;
import android.util.AttributeSet;
import android.view.inspector.InspectableProperty;
import com.android.internal.R;
/**
* Displays checked/unchecked states as a button
* with a "light" indicator and by default accompanied with the text "ON" or "OFF".
@@ -103,6 +106,9 @@ public class ToggleButton extends CompoundButton {
*/
public void setTextOn(CharSequence textOn) {
mTextOn = textOn;
// Default state is derived from on/off-text, so state has to be updated when on/off-text
// are updated.
setDefaultStateDescritption();
}
/**
@@ -122,6 +128,9 @@ public class ToggleButton extends CompoundButton {
*/
public void setTextOff(CharSequence textOff) {
mTextOff = textOff;
// Default state is derived from on/off-text, so state has to be updated when on/off-text
// are updated.
setDefaultStateDescritption();
}
/**
@@ -172,4 +181,15 @@ public class ToggleButton extends CompoundButton {
public CharSequence getAccessibilityClassName() {
return ToggleButton.class.getName();
}
/** @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;
}
}
}

View File

@@ -3042,6 +3042,11 @@
<!-- Default text for a button that can be toggled on and off. -->
<string name="capital_off">OFF</string>
<!-- Default state for CompoundButton for on and off. [CHAR LIMIT=32] -->
<string name="checked">checked</string>
<!-- Default text for a button that can be toggled on and off. [CHAR LIMIT=32] -->
<string name="not_checked">not checked</string>
<!-- Title of intent resolver dialog when selecting an application to run. -->
<string name="whichApplication">Complete action using</string>
<!-- Title of intent resolver dialog when selecting an application to run

View File

@@ -670,14 +670,18 @@
<java-symbol type="string" name="capability_desc_canPerformGestures" />
<java-symbol type="string" name="capability_title_canPerformGestures" />
<java-symbol type="string" name="captive_portal_logged_in_detailed" />
<java-symbol type="string" name="capital_off" />
<java-symbol type="string" name="capital_on" />
<java-symbol type="string" name="cfTemplateForwarded" />
<java-symbol type="string" name="cfTemplateForwardedTime" />
<java-symbol type="string" name="cfTemplateNotForwarded" />
<java-symbol type="string" name="cfTemplateRegistered" />
<java-symbol type="string" name="cfTemplateRegisteredTime" />
<java-symbol type="string" name="chooseActivity" />
<java-symbol type="string" name="checked" />
<java-symbol type="string" name="config_default_dns_server" />
<java-symbol type="string" name="config_ethernet_iface_regex" />
<java-symbol type="string" name="not_checked" />
<java-symbol type="array" name="config_ethernet_interfaces" />
<java-symbol type="array" name="config_wakeonlan_supported_interfaces" />
<java-symbol type="string" name="cellbroadcast_default_package" />