Change Magnification Mode Settings UI

To support new settings UI, we change the UI from scrollview
to listview to simplify UI initialization.

Bug: 182118397
Test: atest MagnificationSettingsFragmentTest
      and manual test.
Change-Id: Ib65dc139ba54f2281e5cb7e2dc55b3574ad2c733
This commit is contained in:
ryanlwlin
2021-03-15 15:30:55 +08:00
parent 993b820a76
commit 0272002335
16 changed files with 723 additions and 232 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1004 B

View File

@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2021 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="77dp"
android:height="134dp"
android:viewportWidth="77"
android:viewportHeight="134">
<path
android:pathData="M7.4,1.1L69.6,1.1A6.3,6.3 0,0 1,75.9 7.4L75.9,126.6A6.3,6.3 0,0 1,69.6 132.9L7.4,132.9A6.3,6.3 0,0 1,1.1 126.6L1.1,7.4A6.3,6.3 0,0 1,7.4 1.1z"
android:strokeWidth="1.8"
android:fillColor="#F2F3F4"
android:strokeColor="#DADCE0"/>
<group>
<clip-path
android:pathData="M7.4,1.1L69.6,1.1A6.3,6.3 0,0 1,75.9 7.4L75.9,126.6A6.3,6.3 0,0 1,69.6 132.9L7.4,132.9A6.3,6.3 0,0 1,1.1 126.6L1.1,7.4A6.3,6.3 0,0 1,7.4 1.1z"/>
<path
android:pathData="M10.442,4.948L67.167,4.948A5.4,5.4 0,0 1,72.567 10.348L72.567,123.548A5.4,5.4 0,0 1,67.167 128.948L10.442,128.948A5.4,5.4 0,0 1,5.042 123.548L5.042,10.348A5.4,5.4 0,0 1,10.442 4.948z"
android:fillColor="#ffffff"/>
<group>
<clip-path
android:pathData="M10.442,4.948L67.167,4.948A5.4,5.4 0,0 1,72.567 10.348L72.567,123.548A5.4,5.4 0,0 1,67.167 128.948L10.442,128.948A5.4,5.4 0,0 1,5.042 123.548L5.042,10.348A5.4,5.4 0,0 1,10.442 4.948z"/>
<path
android:pathData="M13,5L65,5A8,8 0,0 1,73 13L73,120A8,8 0,0 1,65 128L13,128A8,8 0,0 1,5 120L5,13A8,8 0,0 1,13 5z"
android:strokeLineJoin="bevel"
android:strokeWidth="10"
android:fillColor="#00000000"
android:strokeColor="#F29900"/>
<path
android:pathData="M51.077,14V18.314H56.612L50,24.958L53.037,28L59.692,21.334V26.921H64V14H51.077Z"
android:fillColor="#F29900"/>
<path
android:pathData="M25.963,104L19.308,110.655V105.077H15V118H27.923V113.692H22.366L29,107.037L25.963,104Z"
android:fillColor="#F29900"/>
</group>
</group>
</vector>

View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2021 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="77dp"
android:height="134dp"
android:viewportWidth="77"
android:viewportHeight="134">
<path
android:pathData="M7.4,1.1L69.6,1.1A6.3,6.3 0,0 1,75.9 7.4L75.9,126.6A6.3,6.3 0,0 1,69.6 132.9L7.4,132.9A6.3,6.3 0,0 1,1.1 126.6L1.1,7.4A6.3,6.3 0,0 1,7.4 1.1z"
android:strokeWidth="1.8"
android:fillColor="#F2F3F4"
android:strokeColor="#DADCE0"/>
<group>
<clip-path
android:pathData="M7.4,1.1L69.6,1.1A6.3,6.3 0,0 1,75.9 7.4L75.9,126.6A6.3,6.3 0,0 1,69.6 132.9L7.4,132.9A6.3,6.3 0,0 1,1.1 126.6L1.1,7.4A6.3,6.3 0,0 1,7.4 1.1z"/>
<path
android:pathData="M10.442,4.948L67.167,4.948A5.4,5.4 0,0 1,72.567 10.348L72.567,123.548A5.4,5.4 0,0 1,67.167 128.948L10.442,128.948A5.4,5.4 0,0 1,5.042 123.548L5.042,10.348A5.4,5.4 0,0 1,10.442 4.948z"
android:fillColor="#ffffff"/>
<group>
<clip-path
android:pathData="M10.442,4.948L67.167,4.948A5.4,5.4 0,0 1,72.567 10.348L72.567,123.548A5.4,5.4 0,0 1,67.167 128.948L10.442,128.948A5.4,5.4 0,0 1,5.042 123.548L5.042,10.348A5.4,5.4 0,0 1,10.442 4.948z"/>
<path
android:pathData="M39,94h24v24h-24z"
android:fillColor="#000000"
android:fillAlpha="0.7"/>
<path
android:pathData="M51.414,98.138H45.138C44.033,98.138 43.138,99.033 43.138,100.138V112.689C43.138,113.794 44.033,114.689 45.138,114.689H57.69C58.794,114.689 59.69,113.794 59.69,112.689L59.69,106.414H57.69L57.69,112.689L45.138,112.689V100.138H51.414V98.138ZM49.414,108.414H48.448V109.379H49.414V108.414ZM48.448,106.414H46.448V108.414V109.379V111.379H48.448H49.414H51.414V109.379V108.414V106.414H49.414H48.448ZM55.891,103.103L58.035,103.103V104.758L53.069,104.758V99.793L54.724,99.793V101.936L58.275,98.378L59.45,99.553L55.891,103.103Z"
android:fillColor="#ffffff"
android:fillType="evenOdd"/>
<path
android:pathData="M13,5L65,5A8,8 0,0 1,73 13L73,120A8,8 0,0 1,65 128L13,128A8,8 0,0 1,5 120L5,13A8,8 0,0 1,13 5z"
android:strokeLineJoin="bevel"
android:strokeWidth="10"
android:fillColor="#00000000"
android:strokeColor="#F29900"/>
</group>
</group>
</vector>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2021 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="77dp"
android:height="134dp"
android:viewportWidth="77"
android:viewportHeight="134">
<path
android:pathData="M7.4,1.1L69.6,1.1A6.3,6.3 0,0 1,75.9 7.4L75.9,126.6A6.3,6.3 0,0 1,69.6 132.9L7.4,132.9A6.3,6.3 0,0 1,1.1 126.6L1.1,7.4A6.3,6.3 0,0 1,7.4 1.1z"
android:strokeWidth="1.8"
android:fillColor="#F2F3F4"
android:strokeColor="#DADCE0"/>
<group>
<clip-path
android:pathData="M7.4,1.1L69.6,1.1A6.3,6.3 0,0 1,75.9 7.4L75.9,126.6A6.3,6.3 0,0 1,69.6 132.9L7.4,132.9A6.3,6.3 0,0 1,1.1 126.6L1.1,7.4A6.3,6.3 0,0 1,7.4 1.1z"/>
<path
android:pathData="M10.442,4.948L67.167,4.948A5.4,5.4 0,0 1,72.567 10.348L72.567,123.548A5.4,5.4 0,0 1,67.167 128.948L10.442,128.948A5.4,5.4 0,0 1,5.042 123.548L5.042,10.348A5.4,5.4 0,0 1,10.442 4.948z"
android:fillColor="#ffffff"/>
<group>
<clip-path
android:pathData="M10.442,4.948L67.167,4.948A5.4,5.4 0,0 1,72.567 10.348L72.567,123.548A5.4,5.4 0,0 1,67.167 128.948L10.442,128.948A5.4,5.4 0,0 1,5.042 123.548L5.042,10.348A5.4,5.4 0,0 1,10.442 4.948z"/>
<path
android:pathData="M15,47L64,47A2,2 0,0 1,66 49L66,84A2,2 0,0 1,64 86L15,86A2,2 0,0 1,13 84L13,49A2,2 0,0 1,15 47z"
android:strokeLineJoin="bevel"
android:strokeWidth="5"
android:fillColor="#00000000"
android:strokeColor="#F29900"/>
<path
android:pathData="M47.077,53V57.314H52.612L46,63.958L49.037,67L55.692,60.334V65.921H60V53H47.077Z"
android:fillColor="#F29900"/>
<path
android:pathData="M29.963,66L23.308,72.655V67.077H19V80H31.923V75.692H26.366L33,69.037L29.963,66Z"
android:fillColor="#F29900"/>
</group>
</group>
</vector>

View File

@@ -1,51 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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
-->
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbarStyle="outsideOverlay">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="24dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/accessibility_magnification_area_settings_message"
android:textAppearance="?android:attr/textAppearanceListItemSecondary"
android:textColor="?android:attr/textColorSecondary"
android:layout_marginBottom="24dp"/>
<include
android:id="@+id/magnify_full_screen"
layout="@layout/accessibility_edit_shortcut_component"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="32dp" />
<include
android:id="@+id/magnify_window_screen"
layout="@layout/accessibility_edit_shortcut_component" />
</LinearLayout>
</ScrollView>

View File

@@ -55,8 +55,8 @@
<ImageView
android:id="@+id/image"
android:layout_width="176dp"
android:layout_height="176dp"
android:layout_width="@dimen/accessibility_imageview_size"
android:layout_height="@dimen/accessibility_imageview_size"
android:layout_marginStart="44dp"
android:scaleType="fitCenter" />

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2021 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
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="?android:attr/dialogPreferredPadding">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/accessibility_magnification_area_settings_message"
android:textSize="16sp"
style="?android:attr/textAppearanceMedium"
android:textColor="?android:attr/textColorAlertDialogListItem"/>
</FrameLayout>

View File

@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2021 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.
-->
<com.android.settings.widget.CheckableRelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/dialogPreferredPadding"
android:paddingBottom="12dp"
android:paddingTop="12dp">
<RadioButton
android:id="@+id/radioButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:clickable="false"
android:focusable="false" />
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignBaseline="@id/radioButton"
android:layout_marginStart="8dp"
android:layout_toEndOf="@+id/radioButton"
android:gravity="center_vertical|start"
style="?android:attr/textAppearanceMedium"
android:textSize="16sp" />
<TextView
android:id="@+id/summary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceListItemSecondary"
android:layout_marginTop="8dp"
android:layout_alignLeft="@id/title"
android:layout_below="@id/title" />
<ImageView
android:id="@+id/image"
android:layout_width="@dimen/accessibility_imageview_size"
android:layout_height="@dimen/accessibility_imageview_size"
android:layout_marginTop="16dp"
android:scaleType="fitStart"
android:layout_alignLeft="@id/title"
android:layout_below="@id/summary"/>
</com.android.settings.widget.CheckableRelativeLayout>

View File

@@ -295,6 +295,7 @@
<!-- Accessibility Settings -->
<dimen name="accessibility_layout_margin_start_end">16dp</dimen>
<dimen name="accessibility_button_preference_padding_top_bottom">18dp</dimen>
<dimen name="accessibility_imageview_size">176dp</dimen>
<!-- Restricted icon in switch bar -->
<dimen name="restricted_icon_margin_end">16dp</dimen>

View File

@@ -5039,7 +5039,7 @@
<!-- Title for the accessibility preference screen to enable screen magnification. [CHAR LIMIT=35] -->
<string name="accessibility_screen_magnification_title">Magnification</string>
<!-- Title for the accessibility preference screen to edit magnification area. [CHAR LIMIT=35] -->
<string name="accessibility_magnification_mode_title">Choose how to magnify</string>
<string name="accessibility_magnification_mode_title">Magnification type</string>
<!-- Message for the accessibility preference screen to edit magnification area dialog. [CHAR LIMIT=none] -->
<string name="accessibility_magnification_area_settings_message">Magnify your full screen, a specific area, or switch between both options</string>
<!-- Summary for the accessibility preference screen to edit full screen. [CHAR LIMIT=none] -->
@@ -5048,10 +5048,16 @@
<string name="accessibility_magnification_area_settings_window_screen_summary">Partial screen</string>
<!-- Summary for the accessibility preference screen to edit full and partial screen. [CHAR LIMIT=none] -->
<string name="accessibility_magnification_area_settings_all_summary">Switch between full and partial screen</string>
<!-- Message for the accessibility preference screen to edit the full screen. [CHAR LIMIT=none] -->
<string name="accessibility_magnification_area_settings_full_screen">Magnify full screen</string>
<!-- Message for the accessibility preference screen to edit part of screen. [CHAR LIMIT=none] -->
<string name="accessibility_magnification_area_settings_window_screen">Magnify part of screen</string>
<!-- dialog title for magnification mode selection. [CHAR LIMIT=35] -->
<string name="accessibility_magnification_mode_dialog_title">Choose how to magnify</string>
<!-- Option title of full-screen magnification mode in the mode selection dialog. [CHAR LIMIT=50] -->
<string name="accessibility_magnification_mode_dialog_option_full_screen">Magnify full screen</string>
<!-- Option title of window magnification mode in the mode selection dialog. [CHAR LIMIT=50] -->
<string name="accessibility_magnification_mode_dialog_option_window">Magnify part of screen</string>
<!-- Option title of full magnification mode in the mode selection dialog. [CHAR LIMIT=50] -->
<string name="accessibility_magnification_mode_dialog_option_switch">Switch between full and partial screen</string>
<!-- Message of the magnification mode option to choose the magnification mode. [CHAR LIMIT=none] -->
<string name="accessibility_magnification_area_settings_mode_switch_summary">Tap the switch button to move between both options</string>
<!-- Title for the accessibility magnification switch shortcut dialog. [CHAR LIMIT=48] -->
<string name="accessibility_magnification_switch_shortcut_title">Switch to accessibility button?</string>
<!-- Message for the accessibility magnification switch shortcut dialog. [CHAR LIMIT=none] -->

View File

@@ -16,6 +16,8 @@
package com.android.settings.accessibility;
import static com.android.settings.accessibility.ItemInfoArrayAdapter.ItemInfo;
import android.app.Dialog;
import android.app.settings.SettingsEnums;
import android.content.Context;
@@ -29,15 +31,20 @@ import android.text.method.LinkMovementMethod;
import android.text.style.ImageSpan;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ScrollView;
import android.widget.TextView;
import androidx.annotation.ColorInt;
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.ContextCompat;
@@ -47,6 +54,8 @@ import com.android.settings.utils.AnnotationSpan;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
/**
* Utility class for creating the edit dialog.
@@ -61,15 +70,13 @@ public class AccessibilityEditDialogUtils {
@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;
int EDIT_MAGNIFICATION_SWITCH_SHORTCUT = 2;
}
/**
@@ -106,23 +113,6 @@ public class AccessibilityEditDialogUtils {
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.
*
@@ -163,11 +153,21 @@ public class AccessibilityEditDialogUtils {
*/
private static void setScrollIndicators(AlertDialog dialog) {
final ScrollView scrollView = dialog.findViewById(R.id.container_layout);
scrollView.setScrollIndicators(
setScrollIndicators(scrollView);
}
/**
* Sets the scroll indicators for dialog view. The indicators appear while content view is
* out of vision for vertical scrolling.
*
* @param view The view contains customized dialog content. Usually it is {@link ScrollView} or
* {@link AbsListView}
*/
private static void setScrollIndicators(@NonNull View view) {
view.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);
@@ -212,12 +212,6 @@ public class AccessibilityEditDialogUtils {
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);
@@ -229,25 +223,6 @@ public class AccessibilityEditDialogUtils {
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);
@@ -345,7 +320,6 @@ public class AccessibilityEditDialogUtils {
spannableMessage.setSpan(
imageSpan, indexIconStart, indexIconEnd,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
return spannableMessage;
}
@@ -368,4 +342,52 @@ public class AccessibilityEditDialogUtils {
typedArray.recycle();
return colorResId;
}
/**
* Creates a dialog with the given view.
*
* @param context A valid context
* @param dialogTitle The title of the dialog
* @param customView The customized view
* @param listener This listener will be invoked when the positive button in the dialog is
* clicked
* @return the {@link Dialog} with the given view
*/
public static Dialog createCustomDialog(Context context, CharSequence dialogTitle,
View customView, DialogInterface.OnClickListener listener) {
final AlertDialog alertDialog = new AlertDialog.Builder(context)
.setView(customView)
.setTitle(dialogTitle)
.setCancelable(true)
.setPositiveButton(R.string.save, listener)
.setNegativeButton(R.string.cancel, null)
.create();
if (customView instanceof ScrollView || customView instanceof AbsListView) {
setScrollIndicators(customView);
}
return alertDialog;
}
/**
* Creates a single choice {@link ListView} with given {@link ItemInfo} list.
*
* @param context A context.
* @param itemInfoList A {@link ItemInfo} list.
* @param itemListener The listener will be invoked when the item is clicked.
*/
@NonNull
public static ListView createSingleChoiceListView(@NonNull Context context,
@NonNull List<? extends ItemInfo> itemInfoList,
@Nullable AdapterView.OnItemClickListener itemListener) {
final ListView list = new ListView(context);
// Set an id to save its state.
list.setId(android.R.id.list);
list.setDivider(/* divider= */ null);
list.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
final ItemInfoArrayAdapter
adapter = new ItemInfoArrayAdapter(context, itemInfoList);
list.setAdapter(adapter);
list.setOnItemClickListener(itemListener);
return list;
}
}

View File

@@ -0,0 +1,85 @@
/*
* Copyright (C) 2021 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.content.Context;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.settings.R;
import java.util.List;
/**
* An {@link ArrayAdapter} to fill the information of {@link ItemInfo} in the item view. The item
* view must have textview to set the title.
*
* @param <T> the type of elements in the array, inherited from {@link ItemInfo}.
*/
public class ItemInfoArrayAdapter<T extends ItemInfoArrayAdapter.ItemInfo> extends ArrayAdapter<T> {
public ItemInfoArrayAdapter(@NonNull Context context, @NonNull List<T> items) {
super(context, R.layout.dialog_single_radio_choice_list_item, R.id.title, items);
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
final View root = super.getView(position, convertView, parent);
final ItemInfo item = getItem(position);
final TextView title = root.findViewById(R.id.title);
title.setText(item.mTitle);
final TextView summary = root.findViewById(R.id.summary);
if (!TextUtils.isEmpty(item.mSummary)) {
summary.setVisibility(View.VISIBLE);
summary.setText(item.mSummary);
} else {
summary.setVisibility(View.GONE);
}
final ImageView image = root.findViewById(R.id.image);
image.setImageResource(item.mDrawableId);
return root;
}
/**
* Presents a data structure shown in the item view.
*/
public static class ItemInfo {
@NonNull
public final CharSequence mTitle;
@Nullable
public final CharSequence mSummary;
@DrawableRes
public final int mDrawableId;
public ItemInfo(@NonNull CharSequence title, @Nullable CharSequence summary,
@DrawableRes int drawableId) {
mTitle = title;
mSummary = summary;
mDrawableId = drawableId;
}
}
}

View File

@@ -26,20 +26,26 @@ import android.content.DialogInterface;
import android.os.Bundle;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.AdapterView;
import android.widget.ListView;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import com.android.settings.R;
import com.android.settings.accessibility.MagnificationCapabilities.MagnificationMode;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.search.SearchIndexable;
import java.util.ArrayList;
import java.util.List;
import java.util.StringJoiner;
/** Settings page for magnification. */
@@ -52,6 +58,7 @@ public class MagnificationSettingsFragment extends DashboardFragment {
static final int DIALOG_MAGNIFICATION_CAPABILITY = 1;
@VisibleForTesting
static final int DIALOG_MAGNIFICATION_SWITCH_SHORTCUT = 2;
@VisibleForTesting
static final String EXTRA_CAPABILITY = "capability";
private static final int NONE = 0;
@@ -60,13 +67,13 @@ public class MagnificationSettingsFragment extends DashboardFragment {
private Preference mModePreference;
@VisibleForTesting
Dialog mDialog;
@VisibleForTesting
CheckBox mMagnifyFullScreenCheckBox;
@VisibleForTesting
CheckBox mMagnifyWindowCheckBox;
@VisibleForTesting
ListView mMagnificationModesListView;
private int mCapabilities = NONE;
private final List<MagnificationModeInfo> mModeInfos = new ArrayList<>();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -77,6 +84,7 @@ public class MagnificationSettingsFragment extends DashboardFragment {
if (mCapabilities == NONE) {
mCapabilities = MagnificationCapabilities.getCapabilities(getPrefContext());
}
initModeInfos();
}
@Override
@@ -121,13 +129,10 @@ public class MagnificationSettingsFragment extends DashboardFragment {
@Override
public Dialog onCreateDialog(int dialogId) {
final CharSequence title;
switch (dialogId) {
case DIALOG_MAGNIFICATION_CAPABILITY:
title = getPrefContext().getString(
R.string.accessibility_magnification_mode_title);
mDialog = AccessibilityEditDialogUtils.showMagnificationModeDialog(getPrefContext(),
title, this::callOnAlertDialogCheckboxClicked);
initializeDialogCheckBox(mDialog);
mDialog = createMagnificationModeDialog();
return mDialog;
case DIALOG_MAGNIFICATION_SWITCH_SHORTCUT:
title = getPrefContext().getString(
@@ -136,10 +141,97 @@ public class MagnificationSettingsFragment extends DashboardFragment {
getPrefContext(), title, this::onSwitchShortcutDialogPositiveButtonClicked);
return mDialog;
}
throw new IllegalArgumentException("Unsupported dialogId " + dialogId);
}
private Dialog createMagnificationModeDialog() {
mMagnificationModesListView = AccessibilityEditDialogUtils.createSingleChoiceListView(
getPrefContext(), mModeInfos, this::onMagnificationModeSelected);
final View headerView = LayoutInflater.from(getPrefContext()).inflate(
R.layout.accessibility_magnification_mode_header, mMagnificationModesListView,
false);
mMagnificationModesListView.addHeaderView(headerView, null, /* isSelectable= */false);
mMagnificationModesListView.setItemChecked(computeSelectedMagnificationModeIndex(), true);
final CharSequence title = getPrefContext().getString(
R.string.accessibility_magnification_mode_dialog_title);
return AccessibilityEditDialogUtils.createCustomDialog(getPrefContext(), title,
mMagnificationModesListView, this::onMagnificationModeDialogPositiveButtonClicked);
}
private int computeSelectedMagnificationModeIndex() {
final int size = mModeInfos.size();
for (int i = 0; i < size; i++) {
if (mModeInfos.get(i).mMagnificationMode == mCapabilities) {
return i + mMagnificationModesListView.getHeaderViewsCount();
}
}
Log.w(TAG, "chosen mode" + mCapabilities + "is not in the list");
return 0;
}
private void onMagnificationModeSelected(AdapterView<?> parent, View view, int position,
long id) {
final MagnificationModeInfo modeInfo =
(MagnificationModeInfo) mMagnificationModesListView.getItemAtPosition(position);
if (modeInfo.mMagnificationMode == mCapabilities) {
return;
}
mCapabilities = modeInfo.mMagnificationMode;
if (isTripleTapEnabled() && mCapabilities != MagnificationMode.FULLSCREEN) {
showDialog(DIALOG_MAGNIFICATION_SWITCH_SHORTCUT);
}
}
private void onMagnificationModeDialogPositiveButtonClicked(DialogInterface dialogInterface,
int which) {
final int selectedIndex = mMagnificationModesListView.getCheckedItemPosition();
if (selectedIndex != AdapterView.INVALID_POSITION) {
final MagnificationModeInfo modeInfo =
(MagnificationModeInfo) mMagnificationModesListView.getItemAtPosition(
selectedIndex);
updateCapabilities(modeInfo.mMagnificationMode);
} else {
Log.w(TAG, "no checked item in the list");
}
}
private void updateCapabilities(int mode) {
mCapabilities = mode;
MagnificationCapabilities.setCapabilities(getPrefContext(), mCapabilities);
mModePreference.setSummary(
MagnificationCapabilities.getSummary(getPrefContext(), mCapabilities));
}
private void initModeInfos() {
mModeInfos.clear();
mModeInfos.add(new MagnificationModeInfo(getPrefContext().getText(
R.string.accessibility_magnification_mode_dialog_option_full_screen), null,
R.drawable.accessibility_magnification_full_screen, MagnificationMode.FULLSCREEN));
mModeInfos.add(new MagnificationModeInfo(getPrefContext().getText(
R.string.accessibility_magnification_mode_dialog_option_window), null,
R.drawable.accessibility_magnification_window_screen, MagnificationMode.WINDOW));
mModeInfos.add(new MagnificationModeInfo(getPrefContext().getText(
R.string.accessibility_magnification_mode_dialog_option_switch),
getPrefContext().getText(
R.string.accessibility_magnification_area_settings_mode_switch_summary),
R.drawable.accessibility_magnification_switch, MagnificationMode.ALL));
}
@VisibleForTesting
static class MagnificationModeInfo extends ItemInfoArrayAdapter.ItemInfo {
@MagnificationMode
public final int mMagnificationMode;
MagnificationModeInfo(@NonNull CharSequence title, @Nullable CharSequence summary,
@DrawableRes int drawableId, @MagnificationMode int magnificationMode) {
super(title, summary, drawableId);
mMagnificationMode = magnificationMode;
}
}
private void initModePreference() {
mModePreference = findPreference(PREF_KEY_MODE);
mModePreference.setOnPreferenceClickListener(preference -> {
@@ -149,12 +241,6 @@ public class MagnificationSettingsFragment extends DashboardFragment {
});
}
private void callOnAlertDialogCheckboxClicked(DialogInterface dialog, int which) {
updateCapabilities(true);
mModePreference.setSummary(
MagnificationCapabilities.getSummary(getPrefContext(), mCapabilities));
}
private void onSwitchShortcutDialogPositiveButtonClicked(View view) {
//TODO(b/147990389): Merge this function into util until magnification change format to
// Component.
@@ -188,95 +274,6 @@ public class MagnificationSettingsFragment extends DashboardFragment {
joiner.toString());
}
private void initializeDialogCheckBox(Dialog dialog) {
final View dialogFullScreenView = dialog.findViewById(R.id.magnify_full_screen);
final View dialogFullScreenTextArea = dialogFullScreenView.findViewById(R.id.container);
mMagnifyFullScreenCheckBox = dialogFullScreenView.findViewById(R.id.checkbox);
final View dialogWidowView = dialog.findViewById(R.id.magnify_window_screen);
final View dialogWindowTextArea = dialogWidowView.findViewById(R.id.container);
mMagnifyWindowCheckBox = dialogWidowView.findViewById(R.id.checkbox);
updateAlertDialogCheckState();
updateAlertDialogEnableState(dialogFullScreenTextArea, dialogWindowTextArea);
setTextAreasClickListener(dialogFullScreenTextArea, mMagnifyFullScreenCheckBox,
dialogWindowTextArea, mMagnifyWindowCheckBox);
}
private void setTextAreasClickListener(View fullScreenTextArea, CheckBox fullScreenCheckBox,
View windowTextArea, CheckBox windowCheckBox) {
fullScreenTextArea.setOnClickListener(v -> {
fullScreenCheckBox.toggle();
updateCapabilities(false);
updateAlertDialogEnableState(fullScreenTextArea, windowTextArea);
});
windowTextArea.setOnClickListener(v -> {
windowCheckBox.toggle();
updateCapabilities(false);
updateAlertDialogEnableState(fullScreenTextArea, windowTextArea);
if (isTripleTapEnabled() && windowCheckBox.isChecked()) {
showDialog(DIALOG_MAGNIFICATION_SWITCH_SHORTCUT);
}
});
}
private void updateAlertDialogCheckState() {
updateCheckStatus(mMagnifyWindowCheckBox,
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
updateCheckStatus(mMagnifyFullScreenCheckBox,
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
}
private void updateCheckStatus(CheckBox checkBox, int mode) {
checkBox.setChecked((mode & mCapabilities) != 0);
}
private void updateAlertDialogEnableState(View fullScreenTextArea, View windowTextArea) {
switch (mCapabilities) {
case Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN:
setViewAndChildrenEnabled(fullScreenTextArea, false);
break;
case Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW:
setViewAndChildrenEnabled(windowTextArea, false);
break;
case Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL:
setViewAndChildrenEnabled(fullScreenTextArea, true);
setViewAndChildrenEnabled(windowTextArea, true);
break;
default:
throw new IllegalArgumentException(
"Unsupported ACCESSIBILITY_MAGNIFICATION_CAPABILITY " + mCapabilities);
}
}
private void setViewAndChildrenEnabled(View view, boolean enabled) {
view.setEnabled(enabled);
if (view instanceof ViewGroup) {
final ViewGroup viewGroup = (ViewGroup) view;
for (int i = 0; i < viewGroup.getChildCount(); i++) {
View child = viewGroup.getChildAt(i);
setViewAndChildrenEnabled(child, enabled);
}
}
}
private void updateCapabilities(boolean saveToDB) {
int capabilities = 0;
capabilities |=
mMagnifyFullScreenCheckBox.isChecked()
? Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN : 0;
capabilities |= mMagnifyWindowCheckBox.isChecked()
? Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW : 0;
mCapabilities = capabilities;
if (saveToDB) {
MagnificationCapabilities.setCapabilities(getPrefContext(), mCapabilities);
}
}
private boolean isTripleTapEnabled() {
return Settings.Secure.getInt(getPrefContext().getContentResolver(),
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, OFF) == ON;

View File

@@ -0,0 +1,127 @@
/*
* Copyright (C) 2021 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.widget;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.Checkable;
import android.widget.RelativeLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
/**
* A RelativeLayout which implements {@link Checkable}. With this implementation, it could be used
* in the list item layout for {@link android.widget.AbsListView} to change UI after item click.
* Its checked state would be propagated to the checkable child.
*
* <p>
* To support accessibility, the state description is from the checkable view and is
* changed with {@link #setChecked(boolean)}. We make the checkable child unclickable, unfocusable
* and non-important for accessibility, so that the announcement wouldn't include
* the checkable view.
* <
*/
public class CheckableRelativeLayout extends RelativeLayout implements Checkable {
private Checkable mCheckable;
private View mCheckableChild;
private boolean mChecked;
public CheckableRelativeLayout(Context context) {
super(context);
}
public CheckableRelativeLayout(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onFinishInflate() {
mCheckableChild = findFirstCheckableView(this);
if (mCheckableChild != null) {
mCheckableChild.setClickable(false);
mCheckableChild.setFocusable(false);
mCheckableChild.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
mCheckable = (Checkable) mCheckableChild;
mCheckable.setChecked(isChecked());
setStateDescriptionIfNeeded();
}
super.onFinishInflate();
}
@Nullable
private static View findFirstCheckableView(@NonNull ViewGroup viewGroup) {
final int childCount = viewGroup.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = viewGroup.getChildAt(i);
if (child instanceof Checkable) {
return child;
}
if (child instanceof ViewGroup) {
findFirstCheckableView((ViewGroup) child);
}
}
return null;
}
@Override
public void setChecked(boolean checked) {
if (mChecked != checked) {
mChecked = checked;
if (mCheckable != null) {
mCheckable.setChecked(checked);
}
}
setStateDescriptionIfNeeded();
notifyViewAccessibilityStateChangedIfNeeded(
AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
}
private void setStateDescriptionIfNeeded() {
if (mCheckableChild == null) {
return;
}
setStateDescription(mCheckableChild.getStateDescription());
}
@Override
public boolean isChecked() {
return mChecked;
}
@Override
public void toggle() {
setChecked(!mChecked);
}
@Override
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(event);
event.setChecked(mChecked);
}
@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
info.setChecked(mChecked);
}
}

View File

@@ -16,12 +16,15 @@
package com.android.settings.accessibility;
import static com.android.settings.accessibility.MagnificationCapabilities.MagnificationMode;
import static com.android.settings.accessibility.MagnificationPreferenceFragment.ON;
import static com.android.settings.accessibility.MagnificationSettingsFragment.MagnificationModeInfo;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -29,7 +32,8 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.os.Bundle;
import android.provider.Settings;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import androidx.fragment.app.FragmentManager;
import androidx.preference.PreferenceManager;
@@ -77,7 +81,7 @@ public class MagnificationSettingsFragmentTest {
}
@Test
public void onCreateDialog_capabilitiesInBundle_matchCheckBoxStatus() {
public void onCreateDialog_capabilitiesInBundle_checkedModeInDialogIsExpected() {
final Bundle windowModeSavedInstanceState = new Bundle();
windowModeSavedInstanceState.putInt(EXTRA_CAPABILITY,
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
@@ -85,23 +89,21 @@ public class MagnificationSettingsFragmentTest {
mFragment.onCreate(windowModeSavedInstanceState);
mFragment.onCreateDialog(MagnificationSettingsFragment.DIALOG_MAGNIFICATION_CAPABILITY);
assertThat(mFragment.mMagnifyFullScreenCheckBox.isChecked()).isFalse();
assertThat(mFragment.mMagnifyWindowCheckBox.isChecked()).isTrue();
assertThat(getChoseModeFromDialog()).isEqualTo(MagnificationMode.WINDOW);
}
@Test
public void onCreateDialog_capabilitiesInSettings_matchCheckBoxStatus() {
public void onCreateDialog_capabilitiesInSetting_checkedModeInDialogIsExpected() {
MagnificationCapabilities.setCapabilities(mContext,
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
mFragment.onCreate(Bundle.EMPTY);
mFragment.onCreateDialog(MagnificationSettingsFragment.DIALOG_MAGNIFICATION_CAPABILITY);
assertThat(mFragment.mMagnifyFullScreenCheckBox.isChecked()).isTrue();
assertThat(mFragment.mMagnifyWindowCheckBox.isChecked()).isFalse();
assertThat(getChoseModeFromDialog()).isEqualTo(MagnificationMode.FULLSCREEN);
}
@Test
public void onCreateDialog_capabilitiesInSettingsAndBundle_matchBundleValueCheckBoxStatus() {
public void onCreateDialog_choseModeIsDifferentFromInSettings_ShowUsersChoseModeInDialog() {
final Bundle allModeSavedInstanceState = new Bundle();
allModeSavedInstanceState.putInt(EXTRA_CAPABILITY,
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL);
@@ -111,37 +113,93 @@ public class MagnificationSettingsFragmentTest {
mFragment.onCreate(allModeSavedInstanceState);
mFragment.onCreateDialog(MagnificationSettingsFragment.DIALOG_MAGNIFICATION_CAPABILITY);
assertThat(mFragment.mMagnifyFullScreenCheckBox.isChecked()).isTrue();
assertThat(mFragment.mMagnifyWindowCheckBox.isChecked()).isTrue();
assertThat(getChoseModeFromDialog()).isEqualTo(MagnificationMode.ALL);
}
@Test
public void onCreateDialog_emptySettingsAndBundle_matchDefaultValueCheckBoxStatus() {
public void onCreateDialog_emptySettingsAndBundle_checkedModeInDialogIsDefaultValue() {
mFragment.onCreate(Bundle.EMPTY);
mFragment.onCreateDialog(MagnificationSettingsFragment.DIALOG_MAGNIFICATION_CAPABILITY);
// Compare to default Capabilities
assertThat(mFragment.mMagnifyFullScreenCheckBox.isChecked()).isTrue();
assertThat(mFragment.mMagnifyWindowCheckBox.isChecked()).isFalse();
assertThat(getChoseModeFromDialog()).isEqualTo(MagnificationMode.FULLSCREEN);
}
@Test
public void checkWindowModeCheckBox_tripleTapEnabled_showSwitchShortcutDialog() {
public void chooseWindowMode_tripleTapEnabled_showSwitchShortcutDialog() {
enableTripleTap();
final Bundle fullScreenModeSavedInstanceState = new Bundle();
fullScreenModeSavedInstanceState.putInt(EXTRA_CAPABILITY,
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
mFragment.onCreate(fullScreenModeSavedInstanceState);
mFragment.onCreateDialog(MagnificationSettingsFragment.DIALOG_MAGNIFICATION_CAPABILITY);
enableTripleTap();
final View dialogWidowView = mFragment.mDialog.findViewById(R.id.magnify_window_screen);
final View dialogWindowTextArea = dialogWidowView.findViewById(R.id.container);
dialogWindowTextArea.performClick();
performItemClickWith(MagnificationMode.WINDOW);
verify(mFragment).showDialog(
MagnificationSettingsFragment.DIALOG_MAGNIFICATION_SWITCH_SHORTCUT);
}
@Test
public void chooseModeAll_tripleTapEnabled_showSwitchShortcutDialog() {
enableTripleTap();
final Bundle fullScreenModeSavedInstanceState = new Bundle();
fullScreenModeSavedInstanceState.putInt(EXTRA_CAPABILITY,
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
mFragment.onCreate(fullScreenModeSavedInstanceState);
mFragment.onCreateDialog(MagnificationSettingsFragment.DIALOG_MAGNIFICATION_CAPABILITY);
performItemClickWith(MagnificationMode.ALL);
verify(mFragment).showDialog(
MagnificationSettingsFragment.DIALOG_MAGNIFICATION_SWITCH_SHORTCUT);
}
@Test
public void chooseWindowMode_WindowModeInSettingsAndTripleTapEnabled_notShowShortCutDialog() {
enableTripleTap();
MagnificationCapabilities.setCapabilities(mContext,
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
mFragment.onCreate(Bundle.EMPTY);
mFragment.onCreateDialog(MagnificationSettingsFragment.DIALOG_MAGNIFICATION_CAPABILITY);
performItemClickWith(MagnificationMode.WINDOW);
verify(mFragment, never()).showDialog(
MagnificationSettingsFragment.DIALOG_MAGNIFICATION_SWITCH_SHORTCUT);
}
private int getChoseModeFromDialog() {
final ListView listView = mFragment.mMagnificationModesListView;
assertThat(listView).isNotNull();
final int checkedPosition = listView.getCheckedItemPosition();
final MagnificationModeInfo modeInfo =
(MagnificationModeInfo) listView.getAdapter().getItem(
checkedPosition);
return modeInfo.mMagnificationMode;
}
private void performItemClickWith(@MagnificationMode int mode) {
final ListView listView = mFragment.mMagnificationModesListView;
assertThat(listView).isNotNull();
int modeIndex = AdapterView.NO_ID;
// Index 0 is header.
for (int i = 1; i < listView.getAdapter().getCount(); i++) {
final MagnificationModeInfo modeInfo =
(MagnificationModeInfo) listView.getAdapter().getItem(i);
if (modeInfo.mMagnificationMode == mode) {
modeIndex = i;
break;
}
}
if (modeIndex == AdapterView.NO_ID) {
throw new RuntimeException("The mode is not in the list.");
}
listView.performItemClick(listView.getChildAt(modeIndex), modeIndex, modeIndex);
}
private void enableTripleTap() {
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, ON);