Merge changes from topic "tutorial_improvement" into rvc-dev am: b6bf10ebbc
am: 15d20efe43
am: 636d68059e
Change-Id: I9065b0d1f7d1e29f19bc1c5d872f4ef8516e58f8
This commit is contained in:
@@ -15,8 +15,8 @@
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:width="18dp"
|
||||
android:height="18dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?android:attr/colorControlNormal">
|
||||
|
26
res/drawable/ic_accessibility_page_indicator.xml
Normal file
26
res/drawable/ic_accessibility_page_indicator.xml
Normal file
@@ -0,0 +1,26 @@
|
||||
<!--
|
||||
Copyright (C) 2020 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.
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?android:attr/colorControlNormal">
|
||||
<path
|
||||
android:pathData="M12,12m-8,0a8,8 0,1 1,16 0a8,8 0,1 1,-16 0"
|
||||
android:fillColor="#FFFFFF"/>
|
||||
</vector>
|
58
res/layout/accessibility_shortcut_tutorial_dialog.xml
Normal file
58
res/layout/accessibility_shortcut_tutorial_dialog.xml
Normal file
@@ -0,0 +1,58 @@
|
||||
<!--
|
||||
Copyright (C) 2020 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.
|
||||
-->
|
||||
|
||||
<ScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:textDirection="locale"
|
||||
android:scrollbarStyle="outsideOverlay">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="24dp">
|
||||
|
||||
<TextSwitcher
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:measureAllChildren="false" />
|
||||
|
||||
<androidx.viewpager.widget.ViewPager
|
||||
android:id="@+id/view_pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="176dp"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="16dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/indicator_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="10dp"
|
||||
android:layout_gravity="center" />
|
||||
|
||||
<TextSwitcher
|
||||
android:id="@+id/instruction"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:measureAllChildren="false" />
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
@@ -16,35 +16,55 @@
|
||||
|
||||
package com.android.settings.accessibility;
|
||||
|
||||
import static android.view.View.GONE;
|
||||
import static android.view.View.VISIBLE;
|
||||
|
||||
import static com.android.settings.accessibility.AccessibilityUtil.UserShortcutType;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Typeface;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.style.ImageSpan;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.TextureView;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextSwitcher;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.AnimRes;
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.IntDef;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.util.Preconditions;
|
||||
import androidx.viewpager.widget.PagerAdapter;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Utility class for creating the dialog that guides users for gesture navigation for
|
||||
* accessibility services.
|
||||
*/
|
||||
public class AccessibilityGestureNavigationTutorial {
|
||||
|
||||
public final class AccessibilityGestureNavigationTutorial {
|
||||
/** IntDef enum for dialog type. */
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({
|
||||
@@ -59,6 +79,8 @@ public class AccessibilityGestureNavigationTutorial {
|
||||
int GESTURE_NAVIGATION_SETTINGS = 2;
|
||||
}
|
||||
|
||||
private AccessibilityGestureNavigationTutorial() {}
|
||||
|
||||
private static final DialogInterface.OnClickListener mOnClickListener =
|
||||
(DialogInterface dialog, int which) -> dialog.dismiss();
|
||||
|
||||
@@ -91,6 +113,13 @@ public class AccessibilityGestureNavigationTutorial {
|
||||
return createDialog(context, DialogType.LAUNCH_SERVICE_BY_GESTURE_NAVIGATION);
|
||||
}
|
||||
|
||||
static AlertDialog createAccessibilityTutorialDialog(Context context, int shortcutTypes) {
|
||||
return new AlertDialog.Builder(context)
|
||||
.setView(createShortcutNavigationContentView(context, shortcutTypes))
|
||||
.setNegativeButton(R.string.accessibility_tutorial_dialog_button, mOnClickListener)
|
||||
.create();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a content View for a dialog to confirm that they want to enable a service.
|
||||
*
|
||||
@@ -201,4 +230,302 @@ public class AccessibilityGestureNavigationTutorial {
|
||||
typedArray.recycle();
|
||||
return colorResId;
|
||||
}
|
||||
|
||||
private static class TutorialPagerAdapter extends PagerAdapter {
|
||||
private final List<TutorialPage> mTutorialPages;
|
||||
private TutorialPagerAdapter(List<TutorialPage> tutorialPages) {
|
||||
this.mTutorialPages = tutorialPages;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Object instantiateItem(@NonNull ViewGroup container, int position) {
|
||||
final View itemView = mTutorialPages.get(position).getImageView();
|
||||
container.addView(itemView);
|
||||
return itemView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return mTutorialPages.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isViewFromObject(@NonNull View view, @NonNull Object o) {
|
||||
return view == o;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyItem(@NonNull ViewGroup container, int position,
|
||||
@NonNull Object object) {
|
||||
final View itemView = mTutorialPages.get(position).getImageView();
|
||||
container.removeView(itemView);
|
||||
}
|
||||
}
|
||||
|
||||
private static ImageView createImageView(Context context, int imageRes) {
|
||||
final ImageView imageView = new ImageView(context);
|
||||
imageView.setImageResource(imageRes);
|
||||
imageView.setAdjustViewBounds(true);
|
||||
|
||||
return imageView;
|
||||
}
|
||||
|
||||
private static View createShortcutNavigationContentView(Context context, int shortcutTypes) {
|
||||
final LayoutInflater inflater = context.getSystemService(LayoutInflater.class);
|
||||
final View contentView = inflater.inflate(
|
||||
R.layout.accessibility_shortcut_tutorial_dialog, /* root= */ null);
|
||||
final List<TutorialPage> tutorialPages =
|
||||
createShortcutTutorialPages(context, shortcutTypes);
|
||||
Preconditions.checkArgument(!tutorialPages.isEmpty(),
|
||||
/* errorMessage= */ "Unexpected tutorial pages size");
|
||||
|
||||
final LinearLayout indicatorContainer = contentView.findViewById(R.id.indicator_container);
|
||||
indicatorContainer.setVisibility(tutorialPages.size() > 1 ? VISIBLE : GONE);
|
||||
for (TutorialPage page : tutorialPages) {
|
||||
indicatorContainer.addView(page.getIndicatorIcon());
|
||||
}
|
||||
tutorialPages.get(/* firstIndex */ 0).getIndicatorIcon().setEnabled(true);
|
||||
|
||||
final TextSwitcher title = contentView.findViewById(R.id.title);
|
||||
title.setFactory(() -> makeTitleView(context));
|
||||
title.setText(tutorialPages.get(/* firstIndex */ 0).getTitle());
|
||||
|
||||
final TextSwitcher instruction = contentView.findViewById(R.id.instruction);
|
||||
instruction.setFactory(() -> makeInstructionView(context));
|
||||
instruction.setText(tutorialPages.get(/* firstIndex */ 0).getInstruction());
|
||||
|
||||
final ViewPager viewPager = contentView.findViewById(R.id.view_pager);
|
||||
viewPager.setAdapter(new TutorialPagerAdapter(tutorialPages));
|
||||
viewPager.addOnPageChangeListener(
|
||||
new TutorialPageChangeListener(context, title, instruction, tutorialPages));
|
||||
|
||||
return contentView;
|
||||
}
|
||||
|
||||
private static View makeTitleView(Context context) {
|
||||
final String familyName =
|
||||
context.getString(
|
||||
com.android.internal.R.string.config_headlineFontFamilyMedium);
|
||||
final TextView textView = new TextView(context);
|
||||
|
||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, /* size= */ 20);
|
||||
textView.setTextColor(Utils.getColorAttr(context, android.R.attr.textColorPrimary));
|
||||
textView.setGravity(Gravity.CENTER);
|
||||
textView.setTypeface(Typeface.create(familyName, Typeface.NORMAL));
|
||||
|
||||
return textView;
|
||||
}
|
||||
|
||||
private static View makeInstructionView(Context context) {
|
||||
final TextView textView = new TextView(context);
|
||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, /* size= */ 16);
|
||||
textView.setTextColor(Utils.getColorAttr(context, android.R.attr.textColorPrimary));
|
||||
textView.setTypeface(
|
||||
Typeface.create(/* familyName= */ "sans-serif", Typeface.NORMAL));
|
||||
return textView;
|
||||
}
|
||||
|
||||
private static TutorialPage createSoftwareTutorialPage(@NonNull Context context) {
|
||||
final CharSequence title = getSoftwareTitle(context);
|
||||
final ImageView image = createSoftwareImage(context);
|
||||
final CharSequence instruction = getSoftwareInstruction(context);
|
||||
final ImageView indicatorIcon =
|
||||
createImageView(context, R.drawable.ic_accessibility_page_indicator);
|
||||
indicatorIcon.setEnabled(false);
|
||||
|
||||
return new TutorialPage(title, image, indicatorIcon, instruction);
|
||||
}
|
||||
|
||||
private static TutorialPage createHardwareTutorialPage(@NonNull Context context) {
|
||||
final CharSequence title =
|
||||
context.getText(R.string.accessibility_tutorial_dialog_title_volume);
|
||||
final ImageView image =
|
||||
createImageView(context, R.drawable.accessibility_shortcut_type_hardware);
|
||||
final ImageView indicatorIcon =
|
||||
createImageView(context, R.drawable.ic_accessibility_page_indicator);
|
||||
final CharSequence instruction =
|
||||
context.getText(R.string.accessibility_tutorial_dialog_message_volume);
|
||||
indicatorIcon.setEnabled(false);
|
||||
|
||||
return new TutorialPage(title, image, indicatorIcon, instruction);
|
||||
}
|
||||
|
||||
private static TutorialPage createTripleTapTutorialPage(@NonNull Context context) {
|
||||
final CharSequence title =
|
||||
context.getText(R.string.accessibility_tutorial_dialog_title_triple);
|
||||
final ImageView image =
|
||||
createImageView(context, R.drawable.accessibility_shortcut_type_triple_tap);
|
||||
final CharSequence instruction =
|
||||
context.getText(R.string.accessibility_tutorial_dialog_message_triple);
|
||||
final ImageView indicatorIcon =
|
||||
createImageView(context, R.drawable.ic_accessibility_page_indicator);
|
||||
indicatorIcon.setEnabled(false);
|
||||
|
||||
return new TutorialPage(title, image, indicatorIcon, instruction);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static List<TutorialPage> createShortcutTutorialPages(@NonNull Context context,
|
||||
int shortcutTypes) {
|
||||
final List<TutorialPage> tutorialPages = new ArrayList<>();
|
||||
if ((shortcutTypes & UserShortcutType.SOFTWARE) == UserShortcutType.SOFTWARE) {
|
||||
tutorialPages.add(createSoftwareTutorialPage(context));
|
||||
}
|
||||
|
||||
if ((shortcutTypes & UserShortcutType.HARDWARE) == UserShortcutType.HARDWARE) {
|
||||
tutorialPages.add(createHardwareTutorialPage(context));
|
||||
}
|
||||
|
||||
if ((shortcutTypes & UserShortcutType.TRIPLETAP) == UserShortcutType.TRIPLETAP) {
|
||||
tutorialPages.add(createTripleTapTutorialPage(context));
|
||||
}
|
||||
|
||||
return tutorialPages;
|
||||
}
|
||||
|
||||
private static CharSequence getSoftwareTitle(Context context) {
|
||||
final boolean isGestureNavigationEnabled =
|
||||
AccessibilityUtil.isGestureNavigateEnabled(context);
|
||||
final boolean isTouchExploreEnabled = AccessibilityUtil.isTouchExploreEnabled(context);
|
||||
|
||||
return (isGestureNavigationEnabled || isTouchExploreEnabled)
|
||||
? context.getText(R.string.accessibility_tutorial_dialog_title_gesture)
|
||||
: context.getText(R.string.accessibility_tutorial_dialog_title_button);
|
||||
}
|
||||
|
||||
private static ImageView createSoftwareImage(Context context) {
|
||||
int resId = R.drawable.accessibility_shortcut_type_software;
|
||||
if (AccessibilityUtil.isGestureNavigateEnabled(context)) {
|
||||
resId = AccessibilityUtil.isTouchExploreEnabled(context)
|
||||
? R.drawable.accessibility_shortcut_type_software_gesture_talkback
|
||||
: R.drawable.accessibility_shortcut_type_software_gesture;
|
||||
}
|
||||
|
||||
return createImageView(context, resId);
|
||||
}
|
||||
|
||||
private static CharSequence getSoftwareInstruction(Context context) {
|
||||
final boolean isGestureNavigateEnabled =
|
||||
AccessibilityUtil.isGestureNavigateEnabled(context);
|
||||
final boolean isTouchExploreEnabled = AccessibilityUtil.isTouchExploreEnabled(context);
|
||||
int resId = R.string.accessibility_tutorial_dialog_message_button;
|
||||
if (isGestureNavigateEnabled) {
|
||||
resId = isTouchExploreEnabled
|
||||
? R.string.accessibility_tutorial_dialog_message_gesture_talkback
|
||||
: R.string.accessibility_tutorial_dialog_message_gesture;
|
||||
}
|
||||
|
||||
CharSequence text = context.getText(resId);
|
||||
if (resId == R.string.accessibility_tutorial_dialog_message_button) {
|
||||
text = getSoftwareInstructionWithIcon(context, text);
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
private static CharSequence getSoftwareInstructionWithIcon(Context context, CharSequence text) {
|
||||
final String message = text.toString();
|
||||
final SpannableString spannableInstruction = SpannableString.valueOf(message);
|
||||
final int indexIconStart = message.indexOf("%s");
|
||||
final int indexIconEnd = indexIconStart + 2;
|
||||
final ImageView iconView = new ImageView(context);
|
||||
iconView.setImageDrawable(context.getDrawable(R.drawable.ic_accessibility_new));
|
||||
final Drawable icon = iconView.getDrawable().mutate();
|
||||
final ImageSpan imageSpan = new ImageSpan(icon);
|
||||
imageSpan.setContentDescription("");
|
||||
icon.setBounds(/* left= */ 0, /* top= */ 0,
|
||||
icon.getIntrinsicWidth(), icon.getIntrinsicHeight());
|
||||
spannableInstruction.setSpan(imageSpan, indexIconStart, indexIconEnd,
|
||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
|
||||
return spannableInstruction;
|
||||
}
|
||||
|
||||
private static class TutorialPage {
|
||||
private final CharSequence mTitle;
|
||||
private final ImageView mImageView;
|
||||
private final ImageView mIndicatorIcon;
|
||||
private final CharSequence mInstruction;
|
||||
|
||||
TutorialPage(CharSequence title, ImageView imageView, ImageView indicatorIcon,
|
||||
CharSequence instruction) {
|
||||
this.mTitle = title;
|
||||
this.mImageView = imageView;
|
||||
this.mIndicatorIcon = indicatorIcon;
|
||||
this.mInstruction = instruction;
|
||||
}
|
||||
|
||||
public CharSequence getTitle() {
|
||||
return mTitle;
|
||||
}
|
||||
|
||||
public ImageView getImageView() {
|
||||
return mImageView;
|
||||
}
|
||||
|
||||
public ImageView getIndicatorIcon() {
|
||||
return mIndicatorIcon;
|
||||
}
|
||||
|
||||
public CharSequence getInstruction() {
|
||||
return mInstruction;
|
||||
}
|
||||
}
|
||||
|
||||
private static class TutorialPageChangeListener implements ViewPager.OnPageChangeListener {
|
||||
private int mLastTutorialPagePosition = 0;
|
||||
private final Context mContext;
|
||||
private final TextSwitcher mTitle;
|
||||
private final TextSwitcher mInstruction;
|
||||
private final List<TutorialPage> mTutorialPages;
|
||||
|
||||
TutorialPageChangeListener(Context context, ViewGroup title, ViewGroup instruction,
|
||||
List<TutorialPage> tutorialPages) {
|
||||
this.mContext = context;
|
||||
this.mTitle = (TextSwitcher) title;
|
||||
this.mInstruction = (TextSwitcher) instruction;
|
||||
this.mTutorialPages = tutorialPages;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset,
|
||||
int positionOffsetPixels) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
final boolean isPreviousPosition =
|
||||
mLastTutorialPagePosition > position;
|
||||
@AnimRes
|
||||
final int inAnimationResId = isPreviousPosition
|
||||
? android.R.anim.slide_in_left
|
||||
: com.android.internal.R.anim.slide_in_right;
|
||||
|
||||
@AnimRes
|
||||
final int outAnimationResId = isPreviousPosition
|
||||
? android.R.anim.slide_out_right
|
||||
: com.android.internal.R.anim.slide_out_left;
|
||||
|
||||
mTitle.setInAnimation(mContext, inAnimationResId);
|
||||
mTitle.setOutAnimation(mContext, outAnimationResId);
|
||||
mTitle.setText(mTutorialPages.get(position).getTitle());
|
||||
|
||||
mInstruction.setInAnimation(mContext, inAnimationResId);
|
||||
mInstruction.setOutAnimation(mContext, outAnimationResId);
|
||||
mInstruction.setText(mTutorialPages.get(position).getInstruction());
|
||||
|
||||
for (TutorialPage page : mTutorialPages) {
|
||||
page.getIndicatorIcon().setEnabled(false);
|
||||
}
|
||||
mTutorialPages.get(position).getIndicatorIcon().setEnabled(true);
|
||||
mLastTutorialPagePosition = position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int state) {
|
||||
// Do nothing.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -100,6 +100,12 @@ public class LaunchAccessibilityActivityPreferenceFragment extends
|
||||
showDialog(DialogEnums.EDIT_SHORTCUT);
|
||||
}
|
||||
|
||||
@Override
|
||||
int getUserShortcutTypes() {
|
||||
return AccessibilityUtil.getUserShortcutTypesFromSettings(getPrefContext(),
|
||||
mComponentName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
// Do not call super. We don't want to see the "Help & feedback" option on this page so as
|
||||
|
@@ -18,6 +18,7 @@ package com.android.settings.accessibility;
|
||||
|
||||
import static com.android.settings.accessibility.AccessibilityUtil.UserShortcutType;
|
||||
|
||||
import android.accessibilityservice.AccessibilityServiceInfo;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
|
||||
@@ -48,6 +49,22 @@ public class LegacyAccessibilityServicePreferenceFragment extends
|
||||
setAllowedPreferredShortcutType(UserShortcutType.HARDWARE);
|
||||
}
|
||||
|
||||
@Override
|
||||
int getUserShortcutTypes() {
|
||||
int shortcutTypes = super.getUserShortcutTypes();
|
||||
|
||||
final AccessibilityServiceInfo info = getAccessibilityServiceInfo();
|
||||
final boolean hasRequestAccessibilityButtonFlag =
|
||||
(info.flags & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0;
|
||||
if (hasRequestAccessibilityButtonFlag) {
|
||||
shortcutTypes |= UserShortcutType.SOFTWARE;
|
||||
} else {
|
||||
shortcutTypes &= (~UserShortcutType.SOFTWARE);
|
||||
}
|
||||
|
||||
return shortcutTypes;
|
||||
}
|
||||
|
||||
private void setAllowedPreferredShortcutType(int type) {
|
||||
final AccessibilityUserShortcutType shortcut = new AccessibilityUserShortcutType(
|
||||
mComponentName.flattenToString(), type);
|
||||
|
@@ -106,7 +106,7 @@ public class ToggleAccessibilityServicePreferenceFragment extends
|
||||
// capabilities. For
|
||||
// example, before JellyBean MR2 the user was granting the explore by touch
|
||||
// one.
|
||||
private AccessibilityServiceInfo getAccessibilityServiceInfo() {
|
||||
AccessibilityServiceInfo getAccessibilityServiceInfo() {
|
||||
final List<AccessibilityServiceInfo> infos = AccessibilityManager.getInstance(
|
||||
getPrefContext()).getInstalledAccessibilityServiceList();
|
||||
|
||||
@@ -164,16 +164,6 @@ public class ToggleAccessibilityServicePreferenceFragment extends
|
||||
this::onDialogButtonFromDisableToggleClicked);
|
||||
break;
|
||||
}
|
||||
case DialogEnums.LAUNCH_ACCESSIBILITY_TUTORIAL: {
|
||||
if (AccessibilityUtil.isGestureNavigateEnabled(getPrefContext())) {
|
||||
mDialog = AccessibilityGestureNavigationTutorial
|
||||
.showGestureNavigationTutorialDialog(getPrefContext());
|
||||
} else {
|
||||
mDialog = AccessibilityGestureNavigationTutorial
|
||||
.showAccessibilityButtonTutorialDialog(getPrefContext());
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
mDialog = super.onCreateDialog(dialogId);
|
||||
}
|
||||
@@ -197,6 +187,12 @@ public class ToggleAccessibilityServicePreferenceFragment extends
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
int getUserShortcutTypes() {
|
||||
return AccessibilityUtil.getUserShortcutTypesFromSettings(getPrefContext(),
|
||||
mComponentName);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateToggleServiceTitle(SwitchPreference switchPreference) {
|
||||
final AccessibilityServiceInfo info = getAccessibilityServiceInfo();
|
||||
@@ -301,6 +297,7 @@ public class ToggleAccessibilityServicePreferenceFragment extends
|
||||
} else {
|
||||
AccessibilityUtil.optInAllValuesToSettings(getPrefContext(), shortcutTypes,
|
||||
mComponentName);
|
||||
showPopupDialog(DialogEnums.LAUNCH_ACCESSIBILITY_TUTORIAL);
|
||||
}
|
||||
} else {
|
||||
AccessibilityUtil.optOutAllValuesFromSettings(getPrefContext(), shortcutTypes,
|
||||
@@ -414,6 +411,9 @@ public class ToggleAccessibilityServicePreferenceFragment extends
|
||||
final int shortcutTypes = getUserShortcutTypes(getPrefContext(), UserShortcutType.SOFTWARE);
|
||||
AccessibilityUtil.optInAllValuesToSettings(getPrefContext(), shortcutTypes, mComponentName);
|
||||
|
||||
mIsDialogShown.set(false);
|
||||
showPopupDialog(DialogEnums.LAUNCH_ACCESSIBILITY_TUTORIAL);
|
||||
|
||||
mDialog.dismiss();
|
||||
|
||||
mShortcutPreference.setSummary(getShortcutTypeSummary(getPrefContext()));
|
||||
|
@@ -124,6 +124,12 @@ public class ToggleColorInversionPreferenceFragment extends ToggleFeaturePrefere
|
||||
showDialog(DialogEnums.EDIT_SHORTCUT);
|
||||
}
|
||||
|
||||
@Override
|
||||
int getUserShortcutTypes() {
|
||||
return AccessibilityUtil.getUserShortcutTypesFromSettings(getPrefContext(),
|
||||
mComponentName);
|
||||
}
|
||||
|
||||
private void updateSwitchBarToggleSwitch() {
|
||||
final boolean checked = Settings.Secure.getInt(getContentResolver(), ENABLED, OFF) == ON;
|
||||
if (mToggleServiceDividerSwitchPreference.isChecked() == checked) {
|
||||
|
@@ -198,6 +198,12 @@ public final class ToggleDaltonizerPreferenceFragment extends ToggleFeaturePrefe
|
||||
showDialog(DialogEnums.EDIT_SHORTCUT);
|
||||
}
|
||||
|
||||
@Override
|
||||
int getUserShortcutTypes() {
|
||||
return AccessibilityUtil.getUserShortcutTypesFromSettings(getPrefContext(),
|
||||
mComponentName);
|
||||
}
|
||||
|
||||
private void updateSwitchBarToggleSwitch() {
|
||||
final boolean checked = Settings.Secure.getInt(getContentResolver(), ENABLED, OFF) == ON;
|
||||
if (mToggleServiceDividerSwitchPreference.isChecked() == checked) {
|
||||
|
@@ -42,7 +42,6 @@ import android.view.accessibility.AccessibilityManager.TouchExplorationStateChan
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
@@ -250,14 +249,21 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(int dialogId) {
|
||||
Dialog dialog;
|
||||
switch (dialogId) {
|
||||
case DialogEnums.EDIT_SHORTCUT:
|
||||
final CharSequence dialogTitle = getPrefContext().getString(
|
||||
R.string.accessibility_shortcut_title, mPackageName);
|
||||
final AlertDialog dialog = AccessibilityEditDialogUtils.showEditShortcutDialog(
|
||||
dialog = AccessibilityEditDialogUtils.showEditShortcutDialog(
|
||||
getPrefContext(), dialogTitle, this::callOnAlertDialogCheckboxClicked);
|
||||
initializeDialogCheckBox(dialog);
|
||||
return dialog;
|
||||
case DialogEnums.LAUNCH_ACCESSIBILITY_TUTORIAL:
|
||||
dialog = AccessibilityGestureNavigationTutorial
|
||||
.createAccessibilityTutorialDialog(getPrefContext(),
|
||||
getUserShortcutTypes());
|
||||
dialog.setCanceledOnTouchOutside(false);
|
||||
return dialog;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unsupported dialogId " + dialogId);
|
||||
}
|
||||
@@ -268,6 +274,8 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference
|
||||
switch (dialogId) {
|
||||
case DialogEnums.EDIT_SHORTCUT:
|
||||
return SettingsEnums.DIALOG_ACCESSIBILITY_SERVICE_EDIT_SHORTCUT;
|
||||
case DialogEnums.LAUNCH_ACCESSIBILITY_TUTORIAL:
|
||||
return SettingsEnums.DIALOG_ACCESSIBILITY_TUTORIAL;
|
||||
default:
|
||||
return SettingsEnums.ACTION_UNKNOWN;
|
||||
}
|
||||
@@ -334,6 +342,11 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference
|
||||
removeActionBarToggleSwitch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the shortcut type list which has been checked by user.
|
||||
*/
|
||||
abstract int getUserShortcutTypes();
|
||||
|
||||
protected void updateToggleServiceTitle(SwitchPreference switchPreference) {
|
||||
switchPreference.setTitle(R.string.accessibility_service_master_switch_title);
|
||||
}
|
||||
@@ -658,6 +671,7 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference
|
||||
if (preference.isChecked()) {
|
||||
AccessibilityUtil.optInAllValuesToSettings(getPrefContext(), shortcutTypes,
|
||||
mComponentName);
|
||||
showDialog(DialogEnums.LAUNCH_ACCESSIBILITY_TUTORIAL);
|
||||
} else {
|
||||
AccessibilityUtil.optOutAllValuesFromSettings(getPrefContext(), shortcutTypes,
|
||||
mComponentName);
|
||||
|
@@ -224,24 +224,22 @@ public class ToggleScreenMagnificationPreferenceFragment extends
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(int dialogId) {
|
||||
final AlertDialog dialog;
|
||||
switch (dialogId) {
|
||||
case DialogEnums.GESTURE_NAVIGATION_TUTORIAL:
|
||||
return AccessibilityGestureNavigationTutorial
|
||||
.showGestureNavigationTutorialDialog(getPrefContext());
|
||||
case DialogEnums.ACCESSIBILITY_BUTTON_TUTORIAL:
|
||||
return AccessibilityGestureNavigationTutorial
|
||||
.showAccessibilityButtonTutorialDialog(getPrefContext());
|
||||
case DialogEnums.MAGNIFICATION_EDIT_SHORTCUT:
|
||||
final CharSequence dialogTitle = getPrefContext().getString(
|
||||
R.string.accessibility_shortcut_title, mPackageName);
|
||||
final AlertDialog dialog =
|
||||
AccessibilityEditDialogUtils.showMagnificationEditShortcutDialog(
|
||||
dialog = AccessibilityEditDialogUtils.showMagnificationEditShortcutDialog(
|
||||
getPrefContext(), dialogTitle,
|
||||
this::callOnAlertDialogCheckboxClicked);
|
||||
initializeDialogCheckBox(dialog);
|
||||
return dialog;
|
||||
default:
|
||||
return super.onCreateDialog(dialogId);
|
||||
}
|
||||
throw new IllegalArgumentException("Unsupported dialogId " + dialogId);
|
||||
}
|
||||
|
||||
private void setDialogTextAreaClickListener(View dialogView, CheckBox checkBox) {
|
||||
@@ -408,18 +406,21 @@ public class ToggleScreenMagnificationPreferenceFragment extends
|
||||
case DialogEnums.MAGNIFICATION_EDIT_SHORTCUT:
|
||||
return SettingsEnums.DIALOG_MAGNIFICATION_EDIT_SHORTCUT;
|
||||
default:
|
||||
return 0;
|
||||
return super.getDialogMetricsCategory(dialogId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
int getUserShortcutTypes() {
|
||||
return getUserShortcutTypeFromSettings(getPrefContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreferenceToggled(String preferenceKey, boolean enabled) {
|
||||
if (enabled && TextUtils.equals(
|
||||
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED,
|
||||
preferenceKey)) {
|
||||
showDialog(AccessibilityUtil.isGestureNavigateEnabled(getPrefContext())
|
||||
? DialogEnums.GESTURE_NAVIGATION_TUTORIAL
|
||||
: DialogEnums.ACCESSIBILITY_BUTTON_TUTORIAL);
|
||||
showDialog(DialogEnums.LAUNCH_ACCESSIBILITY_TUTORIAL);
|
||||
}
|
||||
MagnificationPreferenceFragment.setChecked(getContentResolver(), preferenceKey, enabled);
|
||||
}
|
||||
@@ -449,6 +450,7 @@ public class ToggleScreenMagnificationPreferenceFragment extends
|
||||
final int shortcutTypes = getUserShortcutTypes(getPrefContext(), UserShortcutType.SOFTWARE);
|
||||
if (preference.isChecked()) {
|
||||
optInAllMagnificationValuesToSettings(getPrefContext(), shortcutTypes);
|
||||
showDialog(DialogEnums.LAUNCH_ACCESSIBILITY_TUTORIAL);
|
||||
} else {
|
||||
optOutAllMagnificationValuesFromSettings(getPrefContext(), shortcutTypes);
|
||||
}
|
||||
|
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.accessibility;
|
||||
|
||||
import static com.android.settings.accessibility.AccessibilityGestureNavigationTutorial.createAccessibilityTutorialDialog;
|
||||
import static com.android.settings.accessibility.AccessibilityGestureNavigationTutorial.createShortcutTutorialPages;
|
||||
import static com.android.settings.accessibility.AccessibilityUtil.UserShortcutType;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
/** Tests for {@link AccessibilityGestureNavigationTutorial}. */
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public final class AccessibilityGestureNavigationTutorialTest {
|
||||
|
||||
private Context mContext;
|
||||
private int mShortcutTypes;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mShortcutTypes = /* initial */ 0;
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void createTutorialPages_shortcutListIsEmpty_throwsException() {
|
||||
createAccessibilityTutorialDialog(mContext, mShortcutTypes);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createTutorialPages_turnOnTripleTapShortcut_hasOnePage() {
|
||||
mShortcutTypes |= UserShortcutType.TRIPLETAP;
|
||||
|
||||
final AlertDialog alertDialog =
|
||||
createAccessibilityTutorialDialog(mContext, mShortcutTypes);
|
||||
|
||||
assertThat(createShortcutTutorialPages(mContext,
|
||||
mShortcutTypes)).hasSize(/* expectedSize= */ 1);
|
||||
assertThat(alertDialog).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createTutorialPages_turnOnSoftwareShortcut_hasOnePage() {
|
||||
mShortcutTypes |= UserShortcutType.SOFTWARE;
|
||||
|
||||
final AlertDialog alertDialog =
|
||||
createAccessibilityTutorialDialog(mContext, mShortcutTypes);
|
||||
|
||||
assertThat(createShortcutTutorialPages(mContext,
|
||||
mShortcutTypes)).hasSize(/* expectedSize= */ 1);
|
||||
assertThat(alertDialog).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createTutorialPages_turnOnSoftwareAndHardwareShortcuts_hasTwoPages() {
|
||||
mShortcutTypes |= UserShortcutType.SOFTWARE;
|
||||
mShortcutTypes |= UserShortcutType.HARDWARE;
|
||||
|
||||
final AlertDialog alertDialog =
|
||||
createAccessibilityTutorialDialog(mContext, mShortcutTypes);
|
||||
|
||||
assertThat(createShortcutTutorialPages(mContext,
|
||||
mShortcutTypes)).hasSize(/* expectedSize= */ 2);
|
||||
assertThat(alertDialog).isNotNull();
|
||||
}
|
||||
}
|
@@ -129,6 +129,11 @@ public class ToggleFeaturePreferenceFragmentTest {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
int getUserShortcutTypes() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPreferenceScreenResId() {
|
||||
return R.xml.placeholder_prefs;
|
||||
|
@@ -86,5 +86,10 @@ public class ToggleFeaturePreferenceFragmentTest {
|
||||
public int getMetricsCategory() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
int getUserShortcutTypes() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user