Files
packages_apps_Settings/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java
jasonwshsu 5fe2cdcf87 Update the dialog content for accessibility floating menu
Accessibility gesture is replaced by accessibility floating menu, related content in edit shortcut dialog and tutorial dialog are updated in this changelist.

Bug: 173990914
Test: manual test
Change-Id: Ie529fa8a1f8ee87ca1ec5611b35675cdfd762165
2021-03-15 02:39:27 +00:00

372 lines
16 KiB
Java

/*
* Copyright (C) 2019 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 android.app.Dialog;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.text.style.ImageSpan;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import androidx.annotation.ColorInt;
import androidx.annotation.IntDef;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.ContextCompat;
import com.android.settings.R;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.utils.AnnotationSpan;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Utility class for creating the edit dialog.
*/
public class AccessibilityEditDialogUtils {
/**
* IntDef enum for dialog type that indicates different dialog for user to choose the shortcut
* type.
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef({
DialogType.EDIT_SHORTCUT_GENERIC,
DialogType.EDIT_SHORTCUT_MAGNIFICATION,
DialogType.EDIT_MAGNIFICATION_MODE,
DialogType.EDIT_MAGNIFICATION_SWITCH_SHORTCUT,
})
private @interface DialogType {
int EDIT_SHORTCUT_GENERIC = 0;
int EDIT_SHORTCUT_MAGNIFICATION = 1;
int EDIT_MAGNIFICATION_MODE = 2;
int EDIT_MAGNIFICATION_SWITCH_SHORTCUT = 3;
}
/**
* Method to show the edit shortcut dialog.
*
* @param context A valid context
* @param dialogTitle The title of edit shortcut dialog
* @param listener The listener to determine the action of edit shortcut dialog
* @return A edit shortcut dialog for showing
*/
public static AlertDialog showEditShortcutDialog(Context context, CharSequence dialogTitle,
DialogInterface.OnClickListener listener) {
final AlertDialog alertDialog = createDialog(context, DialogType.EDIT_SHORTCUT_GENERIC,
dialogTitle, listener);
alertDialog.show();
setScrollIndicators(alertDialog);
return alertDialog;
}
/**
* Method to show the edit shortcut dialog in Magnification.
*
* @param context A valid context
* @param dialogTitle The title of edit shortcut dialog
* @param listener The listener to determine the action of edit shortcut dialog
* @return A edit shortcut dialog for showing in Magnification
*/
public static AlertDialog showMagnificationEditShortcutDialog(Context context,
CharSequence dialogTitle, DialogInterface.OnClickListener listener) {
final AlertDialog alertDialog = createDialog(context,
DialogType.EDIT_SHORTCUT_MAGNIFICATION, dialogTitle, listener);
alertDialog.show();
setScrollIndicators(alertDialog);
return alertDialog;
}
/**
* Method to show the magnification mode dialog in Magnification.
*
* @param context A valid context
* @param dialogTitle The title of magnify mode dialog
* @param listener The listener to determine the action of magnify mode dialog
* @return A magnification mode dialog in Magnification
*/
public static AlertDialog showMagnificationModeDialog(Context context,
CharSequence dialogTitle, DialogInterface.OnClickListener listener) {
final AlertDialog alertDialog = createDialog(context,
DialogType.EDIT_MAGNIFICATION_MODE, dialogTitle, listener);
alertDialog.show();
setScrollIndicators(alertDialog);
return alertDialog;
}
/**
* Method to show the magnification edit shortcut dialog in Magnification.
*
* @param context A valid context
* @param dialogTitle The title of magnify edit shortcut dialog
* @param listener The listener to determine the action of magnify edit shortcut dialog
* @return A magnification edit shortcut dialog in Magnification
*/
public static Dialog showMagnificationSwitchShortcutDialog(Context context,
CharSequence dialogTitle, View.OnClickListener listener) {
final AlertDialog alertDialog = new AlertDialog.Builder(context)
.setView(createSwitchShortcutDialogContentView(context))
.setTitle(dialogTitle)
.create();
alertDialog.show();
setEditShortcutButtonsListener(alertDialog, listener);
setScrollIndicators(alertDialog);
return alertDialog;
}
private static AlertDialog createDialog(Context context, int dialogType,
CharSequence dialogTitle, DialogInterface.OnClickListener listener) {
final AlertDialog alertDialog = new AlertDialog.Builder(context)
.setView(createEditDialogContentView(context, dialogType))
.setTitle(dialogTitle)
.setPositiveButton(R.string.save, listener)
.setNegativeButton(R.string.cancel,
(DialogInterface dialog, int which) -> dialog.dismiss())
.create();
return alertDialog;
}
/**
* Sets the scroll indicators for dialog view. The indicators appears while content view is
* out of vision for vertical scrolling.
*/
private static void setScrollIndicators(AlertDialog dialog) {
final ScrollView scrollView = dialog.findViewById(R.id.container_layout);
scrollView.setScrollIndicators(
View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_BOTTOM,
View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_BOTTOM);
}
private static void setEditShortcutButtonsListener(AlertDialog dialog,
View.OnClickListener listener) {
final View contentView = dialog.findViewById(R.id.container_layout);
final Button positiveButton = contentView.findViewById(
R.id.switch_shortcut_positive_button);
final Button negativeButton = contentView.findViewById(
R.id.switch_shortcut_negative_button);
positiveButton.setOnClickListener(listener);
negativeButton.setOnClickListener(v -> dialog.dismiss());
}
private static View createSwitchShortcutDialogContentView(Context context) {
return createEditDialogContentView(context, DialogType.EDIT_MAGNIFICATION_SWITCH_SHORTCUT);
}
/**
* Get a content View for the edit shortcut dialog.
*
* @param context A valid context
* @param dialogType The type of edit shortcut dialog
* @return A content view suitable for viewing
*/
private static View createEditDialogContentView(Context context, int dialogType) {
final LayoutInflater inflater = (LayoutInflater) context.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
View contentView = null;
switch (dialogType) {
case DialogType.EDIT_SHORTCUT_GENERIC:
contentView = inflater.inflate(
R.layout.accessibility_edit_shortcut, null);
initSoftwareShortcut(context, contentView);
initHardwareShortcut(context, contentView);
break;
case DialogType.EDIT_SHORTCUT_MAGNIFICATION:
contentView = inflater.inflate(
R.layout.accessibility_edit_shortcut_magnification, null);
initSoftwareShortcut(context, contentView);
initHardwareShortcut(context, contentView);
initMagnifyShortcut(context, contentView);
initAdvancedWidget(contentView);
break;
case DialogType.EDIT_MAGNIFICATION_MODE:
contentView = inflater.inflate(
R.layout.accessibility_edit_magnification_mode, null);
initMagnifyFullScreen(context, contentView);
initMagnifyWindowScreen(context, contentView);
break;
case DialogType.EDIT_MAGNIFICATION_SWITCH_SHORTCUT:
contentView = inflater.inflate(
R.layout.accessibility_edit_magnification_shortcut, null);
break;
default:
throw new IllegalArgumentException();
}
return contentView;
}
private static void initMagnifyFullScreen(Context context, View view) {
final View dialogView = view.findViewById(R.id.magnify_full_screen);
final CharSequence title = context.getText(
R.string.accessibility_magnification_area_settings_full_screen);
setupShortcutWidget(dialogView, title, R.drawable.accessibility_magnification_full_screen);
}
private static void initMagnifyWindowScreen(Context context, View view) {
final View dialogView = view.findViewById(R.id.magnify_window_screen);
final CharSequence title = context.getText(
R.string.accessibility_magnification_area_settings_window_screen);
setupShortcutWidget(dialogView, title,
R.drawable.accessibility_magnification_window_screen);
}
private static void setupShortcutWidget(View view, CharSequence titleText, int imageResId) {
setupShortcutWidget(view, titleText, null, imageResId);
}
private static void setupShortcutWidget(View view, CharSequence titleText,
CharSequence summaryText, int imageResId) {
final CheckBox checkBox = view.findViewById(R.id.checkbox);
checkBox.setText(titleText);
final TextView summary = view.findViewById(R.id.summary);
if (TextUtils.isEmpty(summaryText)) {
summary.setVisibility(View.GONE);
} else {
summary.setText(summaryText);
summary.setMovementMethod(LinkMovementMethod.getInstance());
summary.setFocusable(false);
}
final ImageView image = view.findViewById(R.id.image);
image.setImageResource(imageResId);
}
private static void initSoftwareShortcut(Context context, View view) {
final View dialogView = view.findViewById(R.id.software_shortcut);
final CharSequence title = context.getText(
R.string.accessibility_shortcut_edit_dialog_title_software);
final TextView summary = dialogView.findViewById(R.id.summary);
final int lineHeight = summary.getLineHeight();
setupShortcutWidget(dialogView, title, retrieveSummary(context, lineHeight),
retrieveImageResId(context));
}
private static void initHardwareShortcut(Context context, View view) {
final View dialogView = view.findViewById(R.id.hardware_shortcut);
final CharSequence title = context.getText(
R.string.accessibility_shortcut_edit_dialog_title_hardware);
final CharSequence summary = context.getText(
R.string.accessibility_shortcut_edit_dialog_summary_hardware);
setupShortcutWidget(dialogView, title, summary,
R.drawable.accessibility_shortcut_type_hardware);
// TODO(b/142531156): Use vector drawable instead of temporal png file to avoid distorted.
}
private static void initMagnifyShortcut(Context context, View view) {
final View dialogView = view.findViewById(R.id.triple_tap_shortcut);
final CharSequence title = context.getText(
R.string.accessibility_shortcut_edit_dialog_title_triple_tap);
final CharSequence summary = context.getText(
R.string.accessibility_shortcut_edit_dialog_summary_triple_tap);
setupShortcutWidget(dialogView, title, summary,
R.drawable.accessibility_shortcut_type_triple_tap);
// TODO(b/142531156): Use vector drawable instead of temporal png file to avoid distorted.
}
private static void initAdvancedWidget(View view) {
final LinearLayout advanced = view.findViewById(R.id.advanced_shortcut);
final View tripleTap = view.findViewById(R.id.triple_tap_shortcut);
advanced.setOnClickListener((View v) -> {
advanced.setVisibility(View.GONE);
tripleTap.setVisibility(View.VISIBLE);
});
}
private static CharSequence retrieveSummary(Context context, int lineHeight) {
return AccessibilityUtil.isFloatingMenuEnabled(context)
? getSummaryStringWithLink(context) : getSummaryStringWithIcon(context, lineHeight);
}
private static int retrieveImageResId(Context context) {
return AccessibilityUtil.isFloatingMenuEnabled(context)
? R.drawable.accessibility_shortcut_type_software_floating
: R.drawable.accessibility_shortcut_type_software;
}
private static CharSequence getSummaryStringWithLink(Context context) {
final View.OnClickListener linkListener = v -> new SubSettingLauncher(context)
.setDestination(AccessibilityButtonFragment.class.getName())
.setSourceMetricsCategory(
SettingsEnums.SWITCH_SHORTCUT_DIALOG_ACCESSIBILITY_BUTTON_SETTINGS)
.launch();
final AnnotationSpan.LinkInfo linkInfo = new AnnotationSpan.LinkInfo(
AnnotationSpan.LinkInfo.DEFAULT_ANNOTATION, linkListener);
return AnnotationSpan.linkify(context.getText(
R.string.accessibility_shortcut_edit_dialog_summary_software_floating), linkInfo);
}
private static SpannableString getSummaryStringWithIcon(Context context, int lineHeight) {
final String summary = context
.getString(R.string.accessibility_shortcut_edit_dialog_summary_software);
final SpannableString spannableMessage = SpannableString.valueOf(summary);
// Icon
final int indexIconStart = summary.indexOf("%s");
final int indexIconEnd = indexIconStart + 2;
final Drawable icon = context.getDrawable(R.drawable.ic_accessibility_new);
final ImageSpan imageSpan = new ImageSpan(icon);
imageSpan.setContentDescription("");
icon.setBounds(0, 0, lineHeight, lineHeight);
spannableMessage.setSpan(
imageSpan, indexIconStart, indexIconEnd,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
return spannableMessage;
}
/**
* Returns the color associated with the specified attribute in the context's theme.
*/
@ColorInt
private static int getThemeAttrColor(final Context context, final int attributeColor) {
final int colorResId = getAttrResourceId(context, attributeColor);
return ContextCompat.getColor(context, colorResId);
}
/**
* Returns the identifier of the resolved resource assigned to the given attribute.
*/
private static int getAttrResourceId(final Context context, final int attributeColor) {
final int[] attrs = {attributeColor};
final TypedArray typedArray = context.obtainStyledAttributes(attrs);
final int colorResId = typedArray.getResourceId(0, 0);
typedArray.recycle();
return colorResId;
}
}