diff options
5 files changed, 172 insertions, 4 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepository.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepository.java index 0f5c403f1f96..698d60a5b13e 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepository.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepository.java @@ -16,10 +16,12 @@ package com.android.systemui.accessibility.floatingmenu; +import static android.provider.Settings.Secure.ACCESSIBILITY_FLOATING_MENU_SIZE; import static android.provider.Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES; import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_BUTTON; import static com.android.internal.accessibility.dialog.AccessibilityTargetHelper.getTargets; +import static com.android.systemui.accessibility.floatingmenu.MenuViewAppearance.MenuSizeType.SMALL; import android.content.Context; import android.database.ContentObserver; @@ -29,6 +31,7 @@ import android.os.UserHandle; import android.provider.Settings; import com.android.internal.accessibility.dialog.AccessibilityTarget; +import com.android.internal.annotations.VisibleForTesting; import java.util.List; @@ -49,6 +52,16 @@ class MenuInfoRepository { } }; + @VisibleForTesting + final ContentObserver mMenuSizeContentObserver = + new ContentObserver(mHandler) { + @Override + public void onChange(boolean selfChange) { + mSettingsContentsCallback.onSizeTypeChanged( + getMenuSizeTypeFromSettings(mContext)); + } + }; + MenuInfoRepository(Context context, OnSettingsContentsChanged settingsContentsChanged) { mContext = context; mSettingsContentsCallback = settingsContentsChanged; @@ -58,6 +71,10 @@ class MenuInfoRepository { callback.onReady(getTargets(mContext, ACCESSIBILITY_BUTTON)); } + void loadMenuSizeType(OnInfoReady<Integer> callback) { + callback.onReady(getMenuSizeTypeFromSettings(mContext)); + } + void registerContentObservers() { mContext.getContentResolver().registerContentObserver( Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS), @@ -67,17 +84,29 @@ class MenuInfoRepository { Settings.Secure.getUriFor(ENABLED_ACCESSIBILITY_SERVICES), /* notifyForDescendants */ false, mMenuTargetFeaturesContentObserver, UserHandle.USER_CURRENT); + mContext.getContentResolver().registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_FLOATING_MENU_SIZE), + /* notifyForDescendants */ false, mMenuSizeContentObserver, + UserHandle.USER_CURRENT); } void unregisterContentObservers() { mContext.getContentResolver().unregisterContentObserver(mMenuTargetFeaturesContentObserver); + mContext.getContentResolver().unregisterContentObserver(mMenuSizeContentObserver); } interface OnSettingsContentsChanged { void onTargetFeaturesChanged(List<AccessibilityTarget> newTargetFeatures); + + void onSizeTypeChanged(int newSizeType); } interface OnInfoReady<T> { void onReady(T info); } + + private static int getMenuSizeTypeFromSettings(Context context) { + return Settings.Secure.getIntForUser(context.getContentResolver(), + ACCESSIBILITY_FLOATING_MENU_SIZE, SMALL, UserHandle.USER_CURRENT); + } } diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuView.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuView.java index 7e53d3a6ed52..576f23ee780e 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuView.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuView.java @@ -43,6 +43,7 @@ class MenuView extends FrameLayout { private final AccessibilityTargetAdapter mAdapter; private final MenuViewModel mMenuViewModel; private final RecyclerView mTargetFeaturesView; + private final Observer<Integer> mSizeTypeObserver = this::onSizeTypeChanged; private final Observer<List<AccessibilityTarget>> mTargetFeaturesObserver = this::onTargetFeaturesChanged; private final MenuViewAppearance mMenuViewAppearance; @@ -57,6 +58,8 @@ class MenuView extends FrameLayout { mTargetFeaturesView.setAdapter(mAdapter); mTargetFeaturesView.setLayoutManager(new LinearLayoutManager(context)); setLayoutParams(new FrameLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT)); + // Avoid drawing out of bounds of the parent view + setClipToOutline(true); loadLayoutResources(); addView(mTargetFeaturesView); @@ -76,6 +79,12 @@ class MenuView extends FrameLayout { mAdapter.notifyDataSetChanged(); } + private void onSizeChanged() { + final FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) getLayoutParams(); + layoutParams.height = mMenuViewAppearance.getMenuHeight(); + setLayoutParams(layoutParams); + } + private void onEdgeChanged() { final int[] insets = mMenuViewAppearance.getMenuInsets(); getContainerViewInsetLayer().setLayerInset(INDEX_MENU_ITEM, insets[0], insets[1], insets[2], @@ -88,6 +97,17 @@ class MenuView extends FrameLayout { } @SuppressLint("NotifyDataSetChanged") + private void onSizeTypeChanged(int newSizeType) { + mMenuViewAppearance.setSizeType(newSizeType); + + mAdapter.setItemPadding(mMenuViewAppearance.getMenuPadding()); + mAdapter.setIconWidthHeight(mMenuViewAppearance.getMenuIconSize()); + mAdapter.notifyDataSetChanged(); + + onSizeChanged(); + onEdgeChanged(); + } + private void onTargetFeaturesChanged(List<AccessibilityTarget> newTargetFeatures) { // TODO(b/252756133): Should update specific item instead of the whole list mTargetFeatures.clear(); @@ -95,11 +115,13 @@ class MenuView extends FrameLayout { mMenuViewAppearance.setTargetFeaturesSize(mTargetFeatures.size()); mAdapter.notifyDataSetChanged(); + onSizeChanged(); onEdgeChanged(); } void show() { mMenuViewModel.getTargetFeaturesData().observeForever(mTargetFeaturesObserver); + mMenuViewModel.getSizeTypeData().observeForever(mSizeTypeObserver); setVisibility(VISIBLE); mMenuViewModel.registerContentObservers(); } @@ -107,6 +129,7 @@ class MenuView extends FrameLayout { void hide() { setVisibility(GONE); mMenuViewModel.getTargetFeaturesData().removeObserver(mTargetFeaturesObserver); + mMenuViewModel.getSizeTypeData().removeObserver(mSizeTypeObserver); mMenuViewModel.unregisterContentObservers(); } @@ -116,6 +139,7 @@ class MenuView extends FrameLayout { setBackground(mMenuViewAppearance.getMenuBackground()); setElevation(mMenuViewAppearance.getMenuElevation()); onItemSizeChanged(); + onSizeChanged(); onEdgeChanged(); } diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewAppearance.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewAppearance.java index 8af14dad8d19..b9b7732605c0 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewAppearance.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewAppearance.java @@ -16,6 +16,9 @@ package com.android.systemui.accessibility.floatingmenu; +import static com.android.systemui.accessibility.floatingmenu.MenuViewAppearance.MenuSizeType.SMALL; + +import android.annotation.IntDef; import android.content.Context; import android.content.res.Resources; import android.graphics.drawable.Drawable; @@ -24,16 +27,24 @@ import androidx.annotation.DimenRes; import com.android.systemui.R; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * Provides the layout resources information of the {@link MenuView}. */ class MenuViewAppearance { private final Resources mRes; private int mTargetFeaturesSize; + private int mSizeType; private int mSmallPadding; + private int mLargePadding; private int mSmallIconSize; + private int mLargeIconSize; private int mSmallSingleRadius; private int mSmallMultipleRadius; + private int mLargeSingleRadius; + private int mLargeMultipleRadius; private int mStrokeWidth; private int mStrokeColor; private int mInset; @@ -41,6 +52,16 @@ class MenuViewAppearance { private float[] mRadii; private Drawable mBackgroundDrawable; + @IntDef({ + SMALL, + MenuSizeType.LARGE + }) + @Retention(RetentionPolicy.SOURCE) + @interface MenuSizeType { + int SMALL = 0; + int LARGE = 1; + } + MenuViewAppearance(Context context) { mRes = context.getResources(); @@ -50,13 +71,21 @@ class MenuViewAppearance { void update() { mSmallPadding = mRes.getDimensionPixelSize(R.dimen.accessibility_floating_menu_small_padding); + mLargePadding = + mRes.getDimensionPixelSize(R.dimen.accessibility_floating_menu_large_padding); mSmallIconSize = mRes.getDimensionPixelSize(R.dimen.accessibility_floating_menu_small_width_height); + mLargeIconSize = + mRes.getDimensionPixelSize(R.dimen.accessibility_floating_menu_large_width_height); mSmallSingleRadius = mRes.getDimensionPixelSize(R.dimen.accessibility_floating_menu_small_single_radius); mSmallMultipleRadius = mRes.getDimensionPixelSize( R.dimen.accessibility_floating_menu_small_multiple_radius); mRadii = createRadii(getMenuRadius(mTargetFeaturesSize)); + mLargeSingleRadius = + mRes.getDimensionPixelSize(R.dimen.accessibility_floating_menu_large_single_radius); + mLargeMultipleRadius = mRes.getDimensionPixelSize( + R.dimen.accessibility_floating_menu_large_multiple_radius); mStrokeWidth = mRes.getDimensionPixelSize(R.dimen.accessibility_floating_menu_stroke_width); mStrokeColor = mRes.getColor(R.color.accessibility_floating_menu_stroke_dark); mInset = mRes.getDimensionPixelSize(R.dimen.accessibility_floating_menu_stroke_inset); @@ -66,6 +95,12 @@ class MenuViewAppearance { mBackgroundDrawable = new InstantInsetLayerDrawable(new Drawable[]{drawable}); } + void setSizeType(int sizeType) { + mSizeType = sizeType; + + mRadii = createRadii(getMenuRadius(mTargetFeaturesSize)); + } + void setTargetFeaturesSize(int targetFeaturesSize) { mTargetFeaturesSize = targetFeaturesSize; @@ -80,12 +115,16 @@ class MenuViewAppearance { return mElevation; } + int getMenuHeight() { + return calculateActualMenuHeight(); + } + int getMenuIconSize() { - return mSmallIconSize; + return mSizeType == SMALL ? mSmallIconSize : mLargeIconSize; } int getMenuPadding() { - return mSmallPadding; + return mSizeType == SMALL ? mSmallPadding : mLargePadding; } int[] getMenuInsets() { @@ -105,7 +144,7 @@ class MenuViewAppearance { } private int getMenuRadius(int itemCount) { - return getSmallSize(itemCount); + return mSizeType == SMALL ? getSmallSize(itemCount) : getLargeSize(itemCount); } @DimenRes @@ -113,7 +152,18 @@ class MenuViewAppearance { return itemCount > 1 ? mSmallMultipleRadius : mSmallSingleRadius; } + @DimenRes + private int getLargeSize(int itemCount) { + return itemCount > 1 ? mLargeMultipleRadius : mLargeSingleRadius; + } + private static float[] createRadii(float radius) { return new float[]{0.0f, 0.0f, radius, radius, radius, radius, 0.0f, 0.0f}; } + + private int calculateActualMenuHeight() { + final int menuPadding = getMenuPadding(); + + return (menuPadding + getMenuIconSize()) * mTargetFeaturesSize + menuPadding; + } } diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewModel.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewModel.java index 090e23e2c928..c3ba43950b6e 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewModel.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewModel.java @@ -32,6 +32,7 @@ import java.util.List; class MenuViewModel implements MenuInfoRepository.OnSettingsContentsChanged { private final MutableLiveData<List<AccessibilityTarget>> mTargetFeaturesData = new MutableLiveData<>(); + private final MutableLiveData<Integer> mSizeTypeData = new MutableLiveData<>(); private final MenuInfoRepository mInfoRepository; MenuViewModel(Context context) { @@ -43,6 +44,16 @@ class MenuViewModel implements MenuInfoRepository.OnSettingsContentsChanged { mTargetFeaturesData.setValue(newTargetFeatures); } + @Override + public void onSizeTypeChanged(int newSizeType) { + mSizeTypeData.setValue(newSizeType); + } + + LiveData<Integer> getSizeTypeData() { + mInfoRepository.loadMenuSizeType(mSizeTypeData::setValue); + return mSizeTypeData; + } + LiveData<List<AccessibilityTarget>> getTargetFeaturesData() { mInfoRepository.loadMenuTargetFeatures(mTargetFeaturesData::setValue); return mTargetFeaturesData; @@ -55,4 +66,4 @@ class MenuViewModel implements MenuInfoRepository.OnSettingsContentsChanged { void unregisterContentObservers() { mInfoRepository.unregisterContentObservers(); } -} +}
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepositoryTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepositoryTest.java new file mode 100644 index 000000000000..d8b10e04705e --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepositoryTest.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2022 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 org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.verify; + +import android.testing.AndroidTestingRunner; + +import androidx.test.filters.SmallTest; + +import com.android.systemui.SysuiTestCase; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +/** Tests for {@link MenuInfoRepository}. */ +@RunWith(AndroidTestingRunner.class) +@SmallTest +public class MenuInfoRepositoryTest extends SysuiTestCase { + @Rule + public MockitoRule mockito = MockitoJUnit.rule(); + + @Mock + private MenuInfoRepository.OnSettingsContentsChanged mMockSettingsContentsChanged; + + @Test + public void menuSizeTypeChanged_verifyOnSizeTypeChanged() { + final MenuInfoRepository menuInfoRepository = + new MenuInfoRepository(mContext, mMockSettingsContentsChanged); + + menuInfoRepository.mMenuSizeContentObserver.onChange(true); + + verify(mMockSettingsContentsChanged).onSizeTypeChanged(anyInt()); + } +} |