Fix [a11y] Wi-Fi Easy Connect Talkback issues

1. Remove android:contentDescription from ButtonPreference layout file
   'wifi_button_preference_widget.xml' because it should be a more
   general purpose component. Add ButtonPreference#setButtonContentDescription
   for this change.
2. Add a LinearLayout to group title & summary for better Talkback UX
3. Set android:contentDescription for Wi-Fi enrollee scan button
4. setTitle for Talkback actionbar back button of WifiDppQrCodeGeneratorFragment &
   WifiDppQrCodeScannerFragment
5. Auto trigger Talkback to speak title & summary in WifiDppAddDeviceFragment &
   WifiDppChooseSavedWifiNetworkFragment
6. Auto trigger Talkback to speak summary change in WifiDppAddDeviceFragment
7. Auto trigger Talkback to speak error message in WifiDppQrCodeScannerFragment

Bug: 126007405
Bug: 124424996
Bug: 124424445
Test: manual test

Change-Id: I54a3f033bb8871c47be12115ae8f97691fd83302
This commit is contained in:
Arc Wang
2019-03-06 12:29:45 +08:00
parent b249fb7d13
commit 70e3580f5d
10 changed files with 104 additions and 33 deletions

View File

@@ -49,6 +49,7 @@ public class ButtonPreference extends Preference {
private ImageButton mImageButton;
private Drawable mButtonIcon;
private View.OnClickListener mClickListener;
private String mContentDescription;
// Used for dummy pref.
public ButtonPreference(Context context, AttributeSet attrs) {
@@ -57,6 +58,7 @@ public class ButtonPreference extends Preference {
mImageButton = null;
mButtonIcon = null;
mClickListener = null;
mContentDescription = null;
}
public ButtonPreference(Context context) {
@@ -83,6 +85,7 @@ public class ButtonPreference extends Preference {
if (mImageButton != null) {
mImageButton.setImageDrawable(mButtonIcon);
mImageButton.setOnClickListener(mClickListener);
mImageButton.setContentDescription(mContentDescription);
}
setButtonVisibility();
}
@@ -96,9 +99,9 @@ public class ButtonPreference extends Preference {
/**
* Sets the drawable to be displayed in button.
*/
public ButtonPreference setButtonIcon(@DrawableRes int iconResId) {
public void setButtonIcon(@DrawableRes int iconResId) {
if (iconResId == 0) {
return this;
return;
}
try {
@@ -107,17 +110,26 @@ public class ButtonPreference extends Preference {
} catch (Resources.NotFoundException exception) {
Log.e(TAG, "Resource does not exist: " + iconResId);
}
return this;
}
/**
* Register a callback to be invoked when button is clicked.
*/
public ButtonPreference setButtonOnClickListener(View.OnClickListener listener) {
public void setButtonOnClickListener(View.OnClickListener listener) {
if (listener != mClickListener) {
mClickListener = listener;
notifyChanged();
}
return this;
}
/**
* A content description briefly describes the button and is primarily used for accessibility
* support to determine how a button should be presented to the user.
*/
public void setButtonContentDescription(String contentDescription) {
if (contentDescription != mContentDescription) {
mContentDescription = contentDescription;
notifyChanged();
}
}
}

View File

@@ -247,6 +247,7 @@ public class WifiSettings extends RestrictedSettingsFragment
getContext().startActivity(
WifiDppUtils.getEnrolleeQrCodeScannerIntent(/* ssid */ null));
});
mAddPreference.setButtonContentDescription(getString(R.string.wifi_dpp_scan_qr_code));
mStatusMessagePreference = (LinkablePreference) findPreference(PREF_KEY_STATUS_MESSAGE);
mUserBadgeCache = new AccessPointPreference.UserBadgeCache(getPackageManager());

View File

@@ -29,6 +29,7 @@ import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ProgressBar;
@@ -99,6 +100,7 @@ public class WifiDppAddDeviceFragment extends WifiDppQrCodeBaseFragment {
if (!isConfigurationChange) {
mLatestStatusCode = WifiDppUtils.EASY_CONNECT_EVENT_SUCCESS;
changeFocusAndAnnounceChange(mButtonRight, mTitle);
}
}
@@ -168,15 +170,17 @@ public class WifiDppAddDeviceFragment extends WifiDppQrCodeBaseFragment {
mButtonLeft.setVisibility(View.INVISIBLE);
}
if (!isConfigurationChange) {
mLatestStatusCode = code;
}
if (isGoingInitiator()) {
mSummary.setText(R.string.wifi_dpp_sharing_wifi_with_this_device);
}
mProgressBar.setVisibility(isGoingInitiator() ? View.VISIBLE : View.INVISIBLE);
mButtonRight.setVisibility(isGoingInitiator() ? View.INVISIBLE : View.VISIBLE);
if (!isConfigurationChange) {
mLatestStatusCode = code;
changeFocusAndAnnounceChange(mButtonRight, mSummary);
}
}
private boolean hasRetryButton(int code) {
@@ -277,6 +281,7 @@ public class WifiDppAddDeviceFragment extends WifiDppQrCodeBaseFragment {
mButtonRight.setVisibility(View.INVISIBLE);
startWifiDppConfiguratorInitiator();
updateSummary();
mTitleSummaryContainer.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
});
if (savedInstanceState != null) {
@@ -288,6 +293,8 @@ public class WifiDppAddDeviceFragment extends WifiDppQrCodeBaseFragment {
} else {
showErrorUi(mLatestStatusCode, /* isConfigurationChange */ true);
}
} else {
changeFocusAndAnnounceChange(mButtonRight, mTitleSummaryContainer);
}
}
@@ -354,4 +361,17 @@ public class WifiDppAddDeviceFragment extends WifiDppQrCodeBaseFragment {
mSummary.setText(getString(R.string.wifi_dpp_add_device_to_wifi, getSsid()));
}
}
/**
* This fragment will change UI display and text messages for events. To improve Talkback user
* experienience, using this method to focus on a right component and announce a changed text
* after an UI changing event.
*
* @param focusView The UI component which will be focused
* @param announceView The UI component's text will be talked
*/
private void changeFocusAndAnnounceChange(View focusView, View announceView) {
focusView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
announceView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
}
}

View File

@@ -23,6 +23,7 @@ import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.widget.Button;
import android.widget.ListView;
@@ -105,5 +106,11 @@ public class WifiDppChooseSavedWifiNetworkFragment extends WifiDppQrCodeBaseFrag
mButtonRight = view.findViewById(R.id.button_right);
mButtonRight.setVisibility(View.GONE);
if (savedInstanceState == null) {
// For Talkback to describe this fragment
mTitleSummaryContainer.sendAccessibilityEvent(
AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
}
}
}

View File

@@ -38,6 +38,7 @@ public abstract class WifiDppQrCodeBaseFragment extends InstrumentedFragment {
private ImageView mDevicesCheckCircleGreenHeaderIcon;
protected TextView mTitle;
protected TextView mSummary;
protected View mTitleSummaryContainer;
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
@@ -48,6 +49,10 @@ public abstract class WifiDppQrCodeBaseFragment extends InstrumentedFragment {
view.findViewById(R.id.devices_check_circle_green_icon);
mTitle = view.findViewById(android.R.id.title);
mSummary = view.findViewById(android.R.id.summary);
// This is the LinearLayout which groups mTitle and mSummary for Talkback to announce the
// content in a way that reflects its natural groupings.
mTitleSummaryContainer = view.findViewById(R.id.title_summary_container);
}
protected void setHeaderIconImageResource(int resId) {

View File

@@ -60,6 +60,14 @@ public class WifiDppQrCodeGeneratorFragment extends WifiDppQrCodeBaseFragment {
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// setTitle for Talkback
final WifiNetworkConfig wifiNetworkConfig = getWifiNetworkConfigFromHostActivity();
if (wifiNetworkConfig.isHotspot()) {
getActivity().setTitle(R.string.wifi_dpp_share_hotspot);
} else {
getActivity().setTitle(R.string.wifi_dpp_share_wifi);
}
setHasOptionsMenu(true);
final ActionBar actionBar = getActivity().getActionBar();
if (actionBar != null) {

View File

@@ -41,6 +41,7 @@ import android.view.TextureView;
import android.view.TextureView.SurfaceTextureListener;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.widget.ProgressBar;
import android.widget.TextView;
@@ -174,6 +175,13 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// setTitle for Talkback
if (mIsConfiguratorMode) {
getActivity().setTitle(R.string.wifi_dpp_add_device_to_network);
} else {
getActivity().setTitle(R.string.wifi_dpp_scan_qr_code);
}
final ActionBar actionBar = getActivity().getActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
@@ -380,6 +388,7 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
public void showErrorMessage(String message) {
mErrorMessage.setVisibility(View.VISIBLE);
mErrorMessage.setText(message);
mErrorMessage.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
mHandler.removeMessages(MESSAGE_HIDE_ERROR_MESSAGE);
mHandler.sendEmptyMessageDelayed(MESSAGE_HIDE_ERROR_MESSAGE,
@@ -410,6 +419,8 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
mProgressBar.setVisibility(View.VISIBLE);
startWifiDppEnrolleeInitiator((WifiQrCode)msg.obj);
updateEnrolleeSummary();
mSummary.sendAccessibilityEvent(
AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
}
break;