From ce25af48383b26535ec07312ab0db6928bba1fe3 Mon Sep 17 00:00:00 2001 From: Julia Reynolds Date: Wed, 8 Jul 2015 16:56:31 -0400 Subject: [PATCH] Talkback improvements for Settings screens. Bug: 21164141 Change-Id: I7444261ccf967f6db70c9fe44a00bd3f19ceb975 --- res/layout/master_clear.xml | 3 +- res/layout/master_clear_confirm.xml | 1 + res/values/strings.xml | 8 ++++ .../AccessiblePreferenceCategory.java | 43 +++++++++++++++++++ .../ConfirmDeviceCredentialBaseFragment.java | 12 ++++++ .../android/settings/ConfirmLockPassword.java | 1 + .../android/settings/ConfirmLockPattern.java | 1 + src/com/android/settings/MasterClear.java | 18 ++++++++ .../android/settings/MasterClearConfirm.java | 14 ++++++ src/com/android/settings/Utils.java | 17 ++++++++ .../settings/accounts/AccountSettings.java | 10 ++++- .../accounts/AccountSyncSettings.java | 14 ++++++ 12 files changed, 139 insertions(+), 3 deletions(-) create mode 100644 src/com/android/settings/AccessiblePreferenceCategory.java diff --git a/res/layout/master_clear.xml b/res/layout/master_clear.xml index 5ad921a99fe..5d844b1f97f 100644 --- a/res/layout/master_clear.xml +++ b/res/layout/master_clear.xml @@ -27,7 +27,8 @@ android:layout_marginEnd="12dp" android:layout_marginTop="12dp" android:layout_weight="1"> - Personal Work + + Work profile accounts - %s + + Personal profile accounts + + Work account - %s + + Personal account - %s Search diff --git a/src/com/android/settings/AccessiblePreferenceCategory.java b/src/com/android/settings/AccessiblePreferenceCategory.java new file mode 100644 index 00000000000..7784c16fe37 --- /dev/null +++ b/src/com/android/settings/AccessiblePreferenceCategory.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings; + +import android.content.Context; +import android.preference.PreferenceCategory; +import android.view.View; + +/** + * Preference category that accepts a content description for accessibility. + */ +public class AccessiblePreferenceCategory extends PreferenceCategory { + private String mContentDescription; + + public AccessiblePreferenceCategory(Context context) { + super(context); + } + + public void setContentDescription(String contentDescription) { + mContentDescription = contentDescription; + } + + @Override + protected void onBindView(View view) { + super.onBindView(view); + + view.setContentDescription(mContentDescription); + } +} diff --git a/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java b/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java index a8b5f2d6743..304c514565f 100644 --- a/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java +++ b/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java @@ -17,6 +17,7 @@ package com.android.settings; import android.annotation.Nullable; +import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; @@ -82,6 +83,17 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr } } + protected void setAccessibilityTitle(CharSequence suplementalText) { + Intent intent = getActivity().getIntent(); + if (intent != null) { + CharSequence titleText = intent.getCharSequenceExtra( + ConfirmDeviceCredentialBaseFragment.TITLE_TEXT); + String accessibilityTitle = + new StringBuilder(titleText).append(",").append(suplementalText).toString(); + getActivity().setTitle(Utils.createAccessibleSequence(titleText, accessibilityTitle)); + } + } + @Override public void onPause() { super.onPause(); diff --git a/src/com/android/settings/ConfirmLockPassword.java b/src/com/android/settings/ConfirmLockPassword.java index 77618076a64..5a8a47eded7 100644 --- a/src/com/android/settings/ConfirmLockPassword.java +++ b/src/com/android/settings/ConfirmLockPassword.java @@ -161,6 +161,7 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity { 110, 1f /* translationScale */, 0.5f /* delayScale */, AnimationUtils.loadInterpolator( getContext(), android.R.interpolator.fast_out_linear_in)); + setAccessibilityTitle(mHeaderTextView.getText()); return view; } diff --git a/src/com/android/settings/ConfirmLockPattern.java b/src/com/android/settings/ConfirmLockPattern.java index 1737635a67a..d86d63bd711 100644 --- a/src/com/android/settings/ConfirmLockPattern.java +++ b/src/com/android/settings/ConfirmLockPattern.java @@ -178,6 +178,7 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity { return (float)(numRows - row) / numRows; } }); + setAccessibilityTitle(mHeaderTextView.getText()); return view; } diff --git a/src/com/android/settings/MasterClear.java b/src/com/android/settings/MasterClear.java index 6ab36c1f3d5..b6cbebe3c9a 100644 --- a/src/com/android/settings/MasterClear.java +++ b/src/com/android/settings/MasterClear.java @@ -168,6 +168,24 @@ public class MasterClear extends InstrumentedFragment { final UserManager um = (UserManager) getActivity().getSystemService(Context.USER_SERVICE); loadAccountList(um); + StringBuffer contentDescription = new StringBuffer(); + View masterClearContainer = mContentView.findViewById(R.id.master_clear_container); + getContentDescription(masterClearContainer, contentDescription); + masterClearContainer.setContentDescription(contentDescription); + } + + private void getContentDescription(View v, StringBuffer description) { + if (v instanceof ViewGroup) { + ViewGroup vGroup = (ViewGroup) v; + for (int i = 0; i < vGroup.getChildCount(); i++) { + View nextChild = vGroup.getChildAt(i); + getContentDescription(nextChild, description); + } + } else if (v instanceof TextView) { + TextView vText = (TextView) v; + description.append(vText.getText()); + description.append(","); // Allow Talkback to pause between sections. + } } private boolean isExtStorageEncrypted() { diff --git a/src/com/android/settings/MasterClearConfirm.java b/src/com/android/settings/MasterClearConfirm.java index 37d9dd6379c..7319a4e98dd 100644 --- a/src/com/android/settings/MasterClearConfirm.java +++ b/src/com/android/settings/MasterClearConfirm.java @@ -21,6 +21,7 @@ import android.content.Context; import android.content.pm.ActivityInfo; import android.os.AsyncTask; import android.service.persistentdata.PersistentDataBlockManager; + import com.android.internal.logging.MetricsLogger; import android.content.Intent; @@ -30,6 +31,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; +import android.widget.TextView; /** * Confirm and execute a reset of the device to a clean "just out of the box" @@ -134,9 +136,21 @@ public class MasterClearConfirm extends InstrumentedFragment { } mContentView = inflater.inflate(R.layout.master_clear_confirm, null); establishFinalConfirmationState(); + setAccessibilityTitle(); return mContentView; } + private void setAccessibilityTitle() { + CharSequence currentTitle = getActivity().getTitle(); + TextView confirmationMessage = + (TextView) mContentView.findViewById(R.id.master_clear_confirm); + if (confirmationMessage != null) { + String accessibileText = new StringBuilder(currentTitle).append(",").append( + confirmationMessage.getText()).toString(); + getActivity().setTitle(Utils.createAccessibleSequence(currentTitle, accessibileText)); + } + } + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java index 0a5853fce5f..af60a6187fb 100644 --- a/src/com/android/settings/Utils.java +++ b/src/com/android/settings/Utils.java @@ -70,7 +70,10 @@ import android.provider.ContactsContract.Profile; import android.provider.ContactsContract.RawContacts; import android.service.persistentdata.PersistentDataBlockManager; import android.telephony.TelephonyManager; +import android.text.Spannable; +import android.text.SpannableString; import android.text.TextUtils; +import android.text.style.TtsSpan; import android.util.ArraySet; import android.util.Log; import android.util.SparseArray; @@ -1217,4 +1220,18 @@ public final class Utils { return false; } } + + /** + * Returns an accessible SpannableString. + * @param displayText the text to display + * @param accessibileText the text text-to-speech engines should read + */ + public static SpannableString createAccessibleSequence(CharSequence displayText, + String accessibileText) { + SpannableString str = new SpannableString(displayText); + str.setSpan(new TtsSpan.TextBuilder(accessibileText).build(), 0, + displayText.length(), + Spannable.SPAN_INCLUSIVE_INCLUSIVE); + return str; + } } \ No newline at end of file diff --git a/src/com/android/settings/accounts/AccountSettings.java b/src/com/android/settings/accounts/AccountSettings.java index c010a7bdc14..94958a07a4f 100644 --- a/src/com/android/settings/accounts/AccountSettings.java +++ b/src/com/android/settings/accounts/AccountSettings.java @@ -49,6 +49,7 @@ import android.preference.PreferenceCategory; import android.preference.PreferenceScreen; import com.android.internal.logging.MetricsLogger; +import com.android.settings.AccessiblePreferenceCategory; import com.android.settings.R; import com.android.settings.SettingsPreferenceFragment; import com.android.settings.Utils; @@ -270,14 +271,19 @@ public class AccountSettings extends SettingsPreferenceFragment final ProfileData profileData = new ProfileData(); profileData.userInfo = userInfo; if (addCategory) { - profileData.preferenceGroup = new PreferenceCategory(context); + profileData.preferenceGroup = new AccessiblePreferenceCategory(context); if (userInfo.isManagedProfile()) { profileData.preferenceGroup.setLayoutResource(R.layout.work_profile_category); profileData.preferenceGroup.setTitle(R.string.category_work); - profileData.preferenceGroup.setSummary(getWorkGroupSummary(context, userInfo)); + String workGroupSummary = getWorkGroupSummary(context, userInfo); + profileData.preferenceGroup.setSummary(workGroupSummary); + ((AccessiblePreferenceCategory) profileData.preferenceGroup).setContentDescription( + getString(R.string.accessibility_category_work, workGroupSummary)); profileData.removeWorkProfilePreference = newRemoveWorkProfilePreference(context); } else { profileData.preferenceGroup.setTitle(R.string.category_personal); + ((AccessiblePreferenceCategory) profileData.preferenceGroup).setContentDescription( + getString(R.string.accessibility_category_personal)); } parent.addPreference(profileData.preferenceGroup); } else { diff --git a/src/com/android/settings/accounts/AccountSyncSettings.java b/src/com/android/settings/accounts/AccountSyncSettings.java index d1df82a6c8f..59ca995ba0b 100644 --- a/src/com/android/settings/accounts/AccountSyncSettings.java +++ b/src/com/android/settings/accounts/AccountSyncSettings.java @@ -35,6 +35,7 @@ import android.content.SyncAdapterType; import android.content.SyncInfo; import android.content.SyncStatusInfo; import android.content.pm.ProviderInfo; +import android.content.pm.UserInfo; import android.os.Bundle; import android.os.UserHandle; import android.os.UserManager; @@ -151,6 +152,7 @@ public class AccountSyncSettings extends AccountPreferenceBase { super.onCreate(icicle); setPreferenceScreen(null); addPreferencesFromResource(R.xml.account_sync_settings); + setAccessibilityTitle(); setHasOptionsMenu(true); } @@ -200,6 +202,18 @@ public class AccountSyncSettings extends AccountPreferenceBase { mProviderId.setText(mAccount.type); } + private void setAccessibilityTitle() { + final UserManager um = (UserManager) getSystemService(Context.USER_SERVICE); + UserInfo user = um.getUserInfo(mUserHandle.getIdentifier()); + boolean isWorkProfile = user != null ? user.isManagedProfile() : false; + CharSequence currentTitle = getActivity().getTitle(); + String accessibilityTitle = + getString(isWorkProfile + ? R.string.accessibility_work_account_title + : R.string.accessibility_personal_account_title, currentTitle); + getActivity().setTitle(Utils.createAccessibleSequence(currentTitle, accessibilityTitle)); + } + @Override public void onResume() { removePreference("dummy");