Add new floating action menu for Accessibility targets. (2/n)

Patch action:
1. Update the style depends on the settings icon and size key.
2. Under half circle shape mode, the menu will enlarge touch area.

Cherry picked from commit c26ac8c638

Bug: 173958541
Test: atest AccessibilityFloatingMenuTest AccessibilityFloatingMenuViewTest AccessibilityTargetAdapterTest
Change-Id: Iec53ef71d7e0abe5c7619d4e5f67862ca56dfd1f
Merged-In: Iec53ef71d7e0abe5c7619d4e5f67862ca56dfd1f
This commit is contained in:
Peter_Liang
2021-01-19 14:39:01 +08:00
parent cd10a1bc49
commit 1b38ff82bc
9 changed files with 457 additions and 60 deletions

View File

@@ -21,9 +21,9 @@
<item android:id="@+id/menu_background_item">
<shape android:shape="rectangle">
<corners
android:bottomLeftRadius="@dimen/accessibility_floating_menu_single_radius"
android:bottomLeftRadius="@dimen/accessibility_floating_menu_small_single_radius"
android:bottomRightRadius="0dp"
android:topLeftRadius="@dimen/accessibility_floating_menu_single_radius"
android:topLeftRadius="@dimen/accessibility_floating_menu_small_single_radius"
android:topRightRadius="0dp"/>
<solid
android:color="@color/accessibility_floating_menu_background"/>

View File

@@ -19,14 +19,15 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/accessibility_floating_menu_padding"
android:paddingStart="@dimen/accessibility_floating_menu_padding"
android:paddingEnd="@dimen/accessibility_floating_menu_padding"
android:orientation="vertical"
android:gravity="center">
<View
android:id="@+id/icon_view"
android:layout_width="@dimen/accessibility_floating_menu_width_height"
android:layout_height="@dimen/accessibility_floating_menu_width_height"/>
android:layout_width="@dimen/accessibility_floating_menu_small_width_height"
android:layout_height="@dimen/accessibility_floating_menu_small_width_height"/>
<View
android:id="@+id/transparent_divider"

View File

@@ -1362,9 +1362,12 @@
<dimen name="accessibility_floating_menu_stroke_inset">-2dp</dimen>
<dimen name="accessibility_floating_menu_margin">16dp</dimen>
<dimen name="accessibility_floating_menu_padding">6dp</dimen>
<dimen name="accessibility_floating_menu_width_height">36dp</dimen>
<dimen name="accessibility_floating_menu_single_radius">25dp</dimen>
<dimen name="accessibility_floating_menu_multiple_radius">20dp</dimen>
<dimen name="accessibility_floating_menu_small_width_height">36dp</dimen>
<dimen name="accessibility_floating_menu_small_single_radius">25dp</dimen>
<dimen name="accessibility_floating_menu_small_multiple_radius">20dp</dimen>
<dimen name="accessibility_floating_menu_large_width_height">56dp</dimen>
<dimen name="accessibility_floating_menu_large_single_radius">33dp</dimen>
<dimen name="accessibility_floating_menu_large_multiple_radius">35dp</dimen>
<dimen name="rounded_slider_height">44dp</dimen>
<!-- rounded_slider_height / 2 -->

View File

@@ -16,9 +16,13 @@
package com.android.systemui.accessibility.floatingmenu;
import static android.provider.Settings.Secure.ACCESSIBILITY_FLOATING_MENU_ICON_TYPE;
import static android.provider.Settings.Secure.ACCESSIBILITY_FLOATING_MENU_SIZE;
import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_BUTTON;
import static com.android.internal.accessibility.dialog.AccessibilityTargetHelper.getTargets;
import static com.android.systemui.accessibility.floatingmenu.AccessibilityFloatingMenuView.ShapeType;
import static com.android.systemui.accessibility.floatingmenu.AccessibilityFloatingMenuView.SizeType;
import android.content.Context;
import android.database.ContentObserver;
@@ -44,6 +48,22 @@ public class AccessibilityFloatingMenu implements IAccessibilityFloatingMenu {
}
};
private final ContentObserver mSizeContentObserver =
new ContentObserver(new Handler(Looper.getMainLooper())) {
@Override
public void onChange(boolean selfChange) {
mMenuView.setSizeType(getSizeType(mContext));
}
};
private final ContentObserver mShapeContentObserver =
new ContentObserver(new Handler(Looper.getMainLooper())) {
@Override
public void onChange(boolean selfChange) {
mMenuView.setShapeType(getShapeType(mContext));
}
};
public AccessibilityFloatingMenu(Context context) {
mContext = context;
mMenuView = new AccessibilityFloatingMenuView(context);
@@ -66,13 +86,12 @@ public class AccessibilityFloatingMenu implements IAccessibilityFloatingMenu {
return;
}
mMenuView.onTargetsChanged(getTargets(mContext, ACCESSIBILITY_BUTTON));
mMenuView.show();
mMenuView.onTargetsChanged(getTargets(mContext, ACCESSIBILITY_BUTTON));
mMenuView.setSizeType(getSizeType(mContext));
mMenuView.setShapeType(getShapeType(mContext));
mContext.getContentResolver().registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS),
/* notifyForDescendants */ false, mContentObserver,
UserHandle.USER_CURRENT);
registerContentObservers();
}
@Override
@@ -83,6 +102,38 @@ public class AccessibilityFloatingMenu implements IAccessibilityFloatingMenu {
mMenuView.hide();
unregisterContentObservers();
}
private static int getSizeType(Context context) {
return Settings.Secure.getInt(
context.getContentResolver(), ACCESSIBILITY_FLOATING_MENU_SIZE, SizeType.SMALL);
}
private static int getShapeType(Context context) {
return Settings.Secure.getInt(
context.getContentResolver(), ACCESSIBILITY_FLOATING_MENU_ICON_TYPE,
ShapeType.CIRCLE);
}
private void registerContentObservers() {
mContext.getContentResolver().registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS),
/* notifyForDescendants */ false, mContentObserver,
UserHandle.USER_CURRENT);
mContext.getContentResolver().registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_FLOATING_MENU_SIZE),
/* notifyForDescendants */ false, mSizeContentObserver,
UserHandle.USER_CURRENT);
mContext.getContentResolver().registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_FLOATING_MENU_ICON_TYPE),
/* notifyForDescendants */ false, mShapeContentObserver,
UserHandle.USER_CURRENT);
}
private void unregisterContentObservers() {
mContext.getContentResolver().unregisterContentObserver(mContentObserver);
mContext.getContentResolver().unregisterContentObserver(mSizeContentObserver);
mContext.getContentResolver().unregisterContentObserver(mShapeContentObserver);
}
}

View File

@@ -16,15 +16,18 @@
package com.android.systemui.accessibility.floatingmenu;
import android.annotation.IntDef;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.LayerDrawable;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.FrameLayout;
@@ -34,8 +37,11 @@ import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.android.internal.accessibility.dialog.AccessibilityTarget;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.R;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
@@ -50,21 +56,59 @@ public class AccessibilityFloatingMenuView extends FrameLayout {
private static final float DEFAULT_LOCATION_Y_PERCENTAGE = 0.8f;
private static final int INDEX_MENU_ITEM = 0;
private boolean mIsShowing;
private RecyclerView mListView;
@SizeType
private int mSizeType = SizeType.SMALL;
private int mMargin;
private int mPadding;
private int mScreenHeight;
private int mScreenWidth;
private int mIconWidth;
private int mIconHeight;
private final RecyclerView mListView;
private final AccessibilityTargetAdapter mAdapter;
private final WindowManager.LayoutParams mLayoutParams;
private final WindowManager mWindowManager;
private final AccessibilityTargetAdapter mAdapter;
private final List<AccessibilityTarget> mTargets = new ArrayList<>();
@IntDef({
SizeType.SMALL,
SizeType.LARGE
})
@Retention(RetentionPolicy.SOURCE)
@interface SizeType {
int SMALL = 0;
int LARGE = 1;
}
@IntDef({
ShapeType.CIRCLE,
ShapeType.HALF_CIRCLE
})
@Retention(RetentionPolicy.SOURCE)
@interface ShapeType {
int CIRCLE = 0;
int HALF_CIRCLE = 1;
}
public AccessibilityFloatingMenuView(Context context) {
this(context, new RecyclerView(context));
}
@VisibleForTesting
AccessibilityFloatingMenuView(Context context,
RecyclerView listView) {
super(context);
mListView = listView;
mWindowManager = context.getSystemService(WindowManager.class);
mLayoutParams = createDefaultLayoutParams();
mAdapter = new AccessibilityTargetAdapter(mTargets);
initListView(context, mAdapter);
updateStroke();
updateDimensions();
initListView();
final int uiMode = context.getResources().getConfiguration().uiMode;
updateStrokeWith(uiMode);
}
void show() {
@@ -94,41 +138,100 @@ public class AccessibilityFloatingMenuView extends FrameLayout {
mTargets.addAll(newTargets);
mAdapter.notifyDataSetChanged();
final boolean hasMoreItems = mAdapter.getItemCount() > 1;
final int resId = hasMoreItems
? R.dimen.accessibility_floating_menu_multiple_radius
: R.dimen.accessibility_floating_menu_single_radius;
setRadius(resId);
updateRadiusWith(mSizeType, mTargets.size());
}
private void setRadius(@DimenRes int radiusResId) {
final float radius = getResources().getDimension(radiusResId);
void setSizeType(@SizeType int newSizeType) {
mSizeType = newSizeType;
updateIconSizeWith(newSizeType);
updateRadiusWith(newSizeType, mTargets.size());
// When the icon sized changed, the menu size and location will be impacted.
updateLocation();
}
void setShapeType(@ShapeType int newShapeType) {
final boolean isCircleShape =
newShapeType == ShapeType.CIRCLE;
final float offset =
isCircleShape
? 0
: getLayoutWidth() / 2.0f;
mListView.animate().translationX(offset);
setOnTouchListener(
isCircleShape
? null
: (view, event) -> onTouched(event));
}
private boolean onTouched(MotionEvent event) {
final int currentX = (int) event.getX();
final int currentY = (int) event.getY();
final int menuHalfWidth = getLayoutWidth() / 2;
final Rect touchDelegateBounds =
new Rect(mMargin, mMargin, mMargin + menuHalfWidth, mMargin + getLayoutHeight());
if (touchDelegateBounds.contains(currentX, currentY)) {
// In order to correspond to the correct item of list view.
event.setLocation(currentX - mMargin, currentY - mMargin);
return mListView.dispatchTouchEvent(event);
}
return false;
}
private void setRadius(float radius) {
final float[] radii = new float[]{radius, radius, 0.0f, 0.0f, 0.0f, 0.0f, radius, radius};
getMenuGradientDrawable().setCornerRadii(radii);
}
private void initListView(Context context, AccessibilityTargetAdapter adapter) {
final Resources res = context.getResources();
final int margin =
private void updateDimensions() {
final Resources res = getResources();
final DisplayMetrics dm = res.getDisplayMetrics();
mScreenWidth = dm.widthPixels;
mScreenHeight = dm.heightPixels;
mMargin =
res.getDimensionPixelSize(R.dimen.accessibility_floating_menu_margin);
final int elevation =
res.getDimensionPixelSize(R.dimen.accessibility_floating_menu_elevation);
final Drawable listViewBackground =
context.getDrawable(R.drawable.accessibility_floating_menu_background);
mPadding =
res.getDimensionPixelSize(R.dimen.accessibility_floating_menu_padding);
}
mListView = new RecyclerView(context);
final LinearLayoutManager layoutManager = new LinearLayoutManager(context);
private void updateIconSizeWith(@SizeType int sizeType) {
final Resources res = getResources();
final int iconResId =
sizeType == SizeType.SMALL
? R.dimen.accessibility_floating_menu_small_width_height
: R.dimen.accessibility_floating_menu_large_width_height;
mIconWidth = res.getDimensionPixelSize(iconResId);
mIconHeight = mIconWidth;
mAdapter.setIconWidthHeight(mIconWidth);
mAdapter.notifyDataSetChanged();
}
private void initListView() {
final Drawable listViewBackground =
getContext().getDrawable(R.drawable.accessibility_floating_menu_background);
final LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
mListView.setBackground(listViewBackground);
mListView.setAdapter(mAdapter);
mListView.setLayoutManager(layoutManager);
updateListView();
addView(mListView);
}
private void updateListView() {
final int elevation =
getResources().getDimensionPixelSize(R.dimen.accessibility_floating_menu_elevation);
final LayoutParams layoutParams =
new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
layoutParams.setMarginsRelative(margin, margin, /* end= */ 0, margin);
layoutParams.setMarginsRelative(mMargin, mMargin, /* end= */ 0, mMargin);
mListView.setLayoutParams(layoutParams);
mListView.setElevation(elevation);
mListView.setBackground(listViewBackground);
mListView.setAdapter(adapter);
mListView.setLayoutManager(layoutManager);
addView(mListView);
}
private WindowManager.LayoutParams createDefaultLayoutParams() {
@@ -150,9 +253,12 @@ public class AccessibilityFloatingMenuView extends FrameLayout {
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
updateLocation();
updateDimensions();
updateListView();
updateIconSizeWith(mSizeType);
updateColor();
updateStroke();
updateStrokeWith(newConfig.uiMode);
updateLocation();
}
private LayerDrawable getMenuLayerDrawable() {
@@ -163,10 +269,12 @@ public class AccessibilityFloatingMenuView extends FrameLayout {
return (GradientDrawable) getMenuLayerDrawable().getDrawable(INDEX_MENU_ITEM);
}
/**
* Updates the floating menu to be fixed at the side of the screen.
*/
private void updateLocation() {
final DisplayMetrics dm = getResources().getDisplayMetrics();
mLayoutParams.x = dm.widthPixels;
mLayoutParams.y = (int) (dm.heightPixels * DEFAULT_LOCATION_Y_PERCENTAGE);
mLayoutParams.x = mScreenWidth - mMargin - getLayoutWidth();
mLayoutParams.y = (int) (mScreenHeight * DEFAULT_LOCATION_Y_PERCENTAGE);
mWindowManager.updateViewLayout(this, mLayoutParams);
}
@@ -175,10 +283,10 @@ public class AccessibilityFloatingMenuView extends FrameLayout {
getMenuGradientDrawable().setColor(getResources().getColor(menuColorResId));
}
private void updateStroke() {
private void updateStrokeWith(int uiMode) {
final Resources res = getResources();
final boolean isNightMode =
(res.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK)
(uiMode & Configuration.UI_MODE_NIGHT_MASK)
== Configuration.UI_MODE_NIGHT_YES;
final int inset =
@@ -192,4 +300,34 @@ public class AccessibilityFloatingMenuView extends FrameLayout {
final int strokeColor = res.getColor(R.color.accessibility_floating_menu_stroke_dark);
getMenuGradientDrawable().setStroke(strokeWidth, strokeColor);
}
private void updateRadiusWith(@SizeType int sizeType, int itemCount) {
setRadius(getResources().getDimensionPixelSize(getRadiusResId(sizeType, itemCount)));
}
private @DimenRes int getRadiusResId(@SizeType int sizeType, int itemCount) {
return sizeType == SizeType.SMALL
? getSmallSizeResIdWith(itemCount)
: getLargeSizeResIdWith(itemCount);
}
private int getSmallSizeResIdWith(int itemCount) {
return itemCount > 1
? R.dimen.accessibility_floating_menu_small_multiple_radius
: R.dimen.accessibility_floating_menu_small_single_radius;
}
private int getLargeSizeResIdWith(int itemCount) {
return itemCount > 1
? R.dimen.accessibility_floating_menu_large_multiple_radius
: R.dimen.accessibility_floating_menu_large_single_radius;
}
private int getLayoutWidth() {
return mPadding * 2 + mIconWidth;
}
private int getLayoutHeight() {
return (mPadding + mIconHeight) * mTargets.size() + mPadding;
}
}

View File

@@ -16,10 +16,17 @@
package com.android.systemui.accessibility.floatingmenu;
import static android.view.View.GONE;
import static com.android.systemui.accessibility.floatingmenu.AccessibilityTargetAdapter.ItemType.FIRST_ITEM;
import static com.android.systemui.accessibility.floatingmenu.AccessibilityTargetAdapter.ItemType.LAST_ITEM;
import static com.android.systemui.accessibility.floatingmenu.AccessibilityTargetAdapter.ItemType.REGULAR_ITEM;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.RecyclerView.Adapter;
@@ -28,40 +35,70 @@ import com.android.internal.accessibility.dialog.AccessibilityTarget;
import com.android.systemui.R;
import com.android.systemui.accessibility.floatingmenu.AccessibilityTargetAdapter.ViewHolder;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
/**
* An adapter which shows the set of accessibility targets that can be performed.
*/
public class AccessibilityTargetAdapter extends Adapter<ViewHolder> {
private int mIconWidthHeight;
private final List<AccessibilityTarget> mTargets;
@IntDef({
FIRST_ITEM,
REGULAR_ITEM,
LAST_ITEM
})
@Retention(RetentionPolicy.SOURCE)
@interface ItemType {
int FIRST_ITEM = 0;
int REGULAR_ITEM = 1;
int LAST_ITEM = 2;
}
public AccessibilityTargetAdapter(List<AccessibilityTarget> targets) {
mTargets = targets;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int i) {
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, @ItemType int itemType) {
final View root = LayoutInflater.from(parent.getContext()).inflate(
R.layout.accessibility_floating_menu_item, parent,
/* attachToRoot= */ false);
if (itemType == FIRST_ITEM) {
return new TopViewHolder(root);
}
if (itemType == LAST_ITEM) {
return new BottomViewHolder(root);
}
return new ViewHolder(root);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
holder.mIconView.setBackground(mTargets.get(position).getIcon());
final boolean isFirstItem = (position == 0);
final boolean isLastItem = (position == (getItemCount() - 1));
final int padding = holder.itemView.getPaddingStart();
final int paddingTop = isFirstItem ? padding : 0;
final int paddingBottom = isLastItem ? padding : 0;
holder.itemView.setPaddingRelative(padding, paddingTop, padding, paddingBottom);
holder.updateIconWidthHeight(mIconWidthHeight);
holder.itemView.setOnClickListener((v) -> mTargets.get(position).onSelected());
holder.mDivider.setVisibility(isLastItem ? View.GONE : View.VISIBLE);
}
@ItemType
@Override
public int getItemViewType(int position) {
if (position == 0) {
return FIRST_ITEM;
}
if (position == (getItemCount() - 1)) {
return LAST_ITEM;
}
return REGULAR_ITEM;
}
@Override
@@ -69,6 +106,10 @@ public class AccessibilityTargetAdapter extends Adapter<ViewHolder> {
return mTargets.size();
}
public void setIconWidthHeight(int iconWidthHeight) {
mIconWidthHeight = iconWidthHeight;
}
static class ViewHolder extends RecyclerView.ViewHolder {
final View mIconView;
final View mDivider;
@@ -78,5 +119,32 @@ public class AccessibilityTargetAdapter extends Adapter<ViewHolder> {
mIconView = itemView.findViewById(R.id.icon_view);
mDivider = itemView.findViewById(R.id.transparent_divider);
}
void updateIconWidthHeight(int newValue) {
final ViewGroup.LayoutParams layoutParams = mIconView.getLayoutParams();
if (layoutParams.width == newValue) {
return;
}
layoutParams.width = newValue;
layoutParams.height = newValue;
mIconView.setLayoutParams(layoutParams);
}
}
static class TopViewHolder extends ViewHolder {
TopViewHolder(View itemView) {
super(itemView);
final int padding = itemView.getPaddingStart();
itemView.setPaddingRelative(padding, padding, padding, 0);
}
}
static class BottomViewHolder extends ViewHolder {
BottomViewHolder(View itemView) {
super(itemView);
mDivider.setVisibility(GONE);
final int padding = itemView.getPaddingStart();
itemView.setPaddingRelative(padding, 0, padding, padding);
}
}
}

View File

@@ -22,6 +22,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import android.content.Context;
import android.testing.AndroidTestingRunner;
@@ -30,6 +31,7 @@ import android.view.accessibility.AccessibilityManager;
import androidx.test.filters.SmallTest;
import com.android.internal.accessibility.dialog.AccessibilityTarget;
import com.android.systemui.SysuiTestCase;
import org.junit.After;
@@ -58,6 +60,9 @@ public class AccessibilityFloatingMenuTest extends SysuiTestCase {
public void initMenu() {
MockitoAnnotations.initMocks(this);
final List<AccessibilityTarget> mTargets = new ArrayList<>();
mTargets.add(mock(AccessibilityTarget.class));
final List<String> assignedTargets = new ArrayList<>();
mContext.addMockSystemService(Context.ACCESSIBILITY_SERVICE, mAccessibilityManager);
assignedTargets.add(MAGNIFICATION_CONTROLLER_NAME);

View File

@@ -16,23 +16,29 @@
package com.android.systemui.accessibility.floatingmenu;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.LayerDrawable;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.View;
import android.view.ViewPropertyAnimator;
import android.view.WindowManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.test.filters.SmallTest;
import com.android.internal.accessibility.dialog.AccessibilityTarget;
@@ -51,12 +57,18 @@ import java.util.List;
/** Tests for {@link AccessibilityFloatingMenuView}. */
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class AccessibilityFloatingMenuViewTest extends SysuiTestCase {
private AccessibilityFloatingMenuView mMenuView;
@Mock
private WindowManager mWindowManager;
@Mock
private ViewPropertyAnimator mAnimator;
private RecyclerView mListView;
private final List<AccessibilityTarget> mTargets = new ArrayList<>();
@Before
@@ -69,6 +81,7 @@ public class AccessibilityFloatingMenuViewTest extends SysuiTestCase {
mContext.addMockSystemService(Context.WINDOW_SERVICE, mWindowManager);
mTargets.add(mock(AccessibilityTarget.class));
mListView = spy(new RecyclerView(mContext));
mMenuView = new AccessibilityFloatingMenuView(mContext);
}
@@ -117,10 +130,10 @@ public class AccessibilityFloatingMenuViewTest extends SysuiTestCase {
@Test
public void updateListViewRadius_singleTarget_matchResult() {
final float radius =
getContext().getResources().getDimension(
R.dimen.accessibility_floating_menu_single_radius);
getContext().getResources().getDimensionPixelSize(
R.dimen.accessibility_floating_menu_small_single_radius);
final float[] expectedRadii =
new float[] {radius, radius, 0.0f, 0.0f, 0.0f, 0.0f, radius, radius};
new float[]{radius, radius, 0.0f, 0.0f, 0.0f, 0.0f, radius, radius};
mMenuView.onTargetsChanged(mTargets);
final View view = mMenuView.getChildAt(0);
@@ -131,4 +144,37 @@ public class AccessibilityFloatingMenuViewTest extends SysuiTestCase {
assertThat(actualRadii).isEqualTo(expectedRadii);
}
@Test
public void setSizeType_largeSize_matchResult() {
final int shapeType = 2;
final float radius = getContext().getResources().getDimensionPixelSize(
R.dimen.accessibility_floating_menu_large_single_radius);
final float[] expectedRadii =
new float[]{radius, radius, 0.0f, 0.0f, 0.0f, 0.0f, radius, radius};
final Drawable listViewBackground =
mContext.getDrawable(R.drawable.accessibility_floating_menu_background);
mListView = spy(new RecyclerView(mContext));
mListView.setBackground(listViewBackground);
mMenuView = new AccessibilityFloatingMenuView(mContext, mListView);
mMenuView.setSizeType(shapeType);
final LayerDrawable layerDrawable =
(LayerDrawable) mListView.getBackground();
final GradientDrawable gradientDrawable =
(GradientDrawable) layerDrawable.getDrawable(0);
assertThat(gradientDrawable.getCornerRadii()).isEqualTo(expectedRadii);
}
@Test
public void setShapeType_halfCircle_translationX() {
final int shapeType = 2;
doReturn(mAnimator).when(mListView).animate();
mMenuView = new AccessibilityFloatingMenuView(mContext, mListView);
mMenuView.setShapeType(shapeType);
verify(mAnimator).translationX(anyFloat());
}
}

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.systemui.accessibility.floatingmenu;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
import android.graphics.drawable.Drawable;
import android.testing.AndroidTestingRunner;
import android.view.LayoutInflater;
import android.view.View;
import androidx.test.filters.SmallTest;
import com.android.internal.accessibility.dialog.AccessibilityTarget;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.accessibility.floatingmenu.AccessibilityTargetAdapter.ViewHolder;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.List;
/** Tests for {@link AccessibilityTargetAdapter}. */
@SmallTest
@RunWith(AndroidTestingRunner.class)
public class AccessibilityTargetAdapterTest extends SysuiTestCase {
@Mock
private AccessibilityTarget mAccessibilityTarget;
@Mock
private Drawable mIcon;
@Mock
private Drawable.ConstantState mConstantState;
private ViewHolder mViewHolder;
private AccessibilityTargetAdapter mAdapter;
private final List<AccessibilityTarget> mTargets = new ArrayList<>();
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mTargets.add(mAccessibilityTarget);
mAdapter = new AccessibilityTargetAdapter(mTargets);
final View root = LayoutInflater.from(mContext).inflate(
R.layout.accessibility_floating_menu_item, null);
mViewHolder = new ViewHolder(root);
when(mAccessibilityTarget.getIcon()).thenReturn(mIcon);
when(mIcon.getConstantState()).thenReturn(mConstantState);
}
@Test
public void onBindViewHolder_setIconWidthHeight_matchResult() {
final int iconWidthHeight = 50;
mAdapter.setIconWidthHeight(iconWidthHeight);
mAdapter.onBindViewHolder(mViewHolder, 0);
final int actualIconWith = mViewHolder.mIconView.getLayoutParams().width;
assertThat(actualIconWith).isEqualTo(iconWidthHeight);
}
}