diff --git a/core/java/com/android/internal/accessibility/dialog/AccessibilityTarget.java b/core/java/com/android/internal/accessibility/dialog/AccessibilityTarget.java index 5b0abd389e7d1..b8446da3c5fcc 100644 --- a/core/java/com/android/internal/accessibility/dialog/AccessibilityTarget.java +++ b/core/java/com/android/internal/accessibility/dialog/AccessibilityTarget.java @@ -52,6 +52,7 @@ public abstract class AccessibilityTarget implements TargetOperations, OnTargetS private CharSequence mLabel; private Drawable mIcon; private String mKey; + private CharSequence mStateDescription; @VisibleForTesting public AccessibilityTarget(Context context, @ShortcutType int shortcutType, @@ -106,6 +107,10 @@ public abstract class AccessibilityTarget implements TargetOperations, OnTargetS } } + public void setStateDescription(CharSequence stateDescription) { + mStateDescription = stateDescription; + } + /** * Gets the state description of this feature target. * @@ -113,7 +118,7 @@ public abstract class AccessibilityTarget implements TargetOperations, OnTargetS */ @Nullable public CharSequence getStateDescription() { - return null; + return mStateDescription; } public void setShortcutEnabled(boolean enabled) { diff --git a/core/java/com/android/internal/accessibility/dialog/ToggleAccessibilityServiceTarget.java b/core/java/com/android/internal/accessibility/dialog/ToggleAccessibilityServiceTarget.java index 469d10ff98aa6..41a0ba2b693aa 100644 --- a/core/java/com/android/internal/accessibility/dialog/ToggleAccessibilityServiceTarget.java +++ b/core/java/com/android/internal/accessibility/dialog/ToggleAccessibilityServiceTarget.java @@ -41,6 +41,11 @@ class ToggleAccessibilityServiceTarget extends AccessibilityServiceTarget { shortcutType, AccessibilityFragmentType.TOGGLE, serviceInfo); + + final int statusResId = isAccessibilityServiceEnabled(getContext(), getId()) + ? R.string.accessibility_shortcut_menu_item_status_on + : R.string.accessibility_shortcut_menu_item_status_off; + setStateDescription(getContext().getString(statusResId)); } @Override @@ -53,12 +58,4 @@ class ToggleAccessibilityServiceTarget extends AccessibilityServiceTarget { holder.mStatusView.setVisibility(isEditMenuMode ? View.GONE : View.VISIBLE); holder.mStatusView.setText(getStateDescription()); } - - @Override - public CharSequence getStateDescription() { - final int statusResId = isAccessibilityServiceEnabled(getContext(), getId()) - ? R.string.accessibility_shortcut_menu_item_status_on - : R.string.accessibility_shortcut_menu_item_status_off; - return getContext().getString(statusResId); - } } diff --git a/core/java/com/android/internal/accessibility/dialog/ToggleAllowListingFeatureTarget.java b/core/java/com/android/internal/accessibility/dialog/ToggleAllowListingFeatureTarget.java index ebdaed6dbe39b..d2124a00596f3 100644 --- a/core/java/com/android/internal/accessibility/dialog/ToggleAllowListingFeatureTarget.java +++ b/core/java/com/android/internal/accessibility/dialog/ToggleAllowListingFeatureTarget.java @@ -38,6 +38,11 @@ class ToggleAllowListingFeatureTarget extends AccessibilityTarget { boolean isShortcutSwitched, String id, CharSequence label, Drawable icon, String key) { super(context, shortcutType, AccessibilityFragmentType.TOGGLE, isShortcutSwitched, id, label, icon, key); + + final int statusResId = isFeatureEnabled() + ? R.string.accessibility_shortcut_menu_item_status_on + : R.string.accessibility_shortcut_menu_item_status_off; + setStateDescription(getContext().getString(statusResId)); } @Override @@ -51,14 +56,6 @@ class ToggleAllowListingFeatureTarget extends AccessibilityTarget { holder.mStatusView.setText(getStateDescription()); } - @Override - public CharSequence getStateDescription() { - final int statusResId = isFeatureEnabled() - ? R.string.accessibility_shortcut_menu_item_status_on - : R.string.accessibility_shortcut_menu_item_status_off; - return getContext().getString(statusResId); - } - private boolean isFeatureEnabled() { return Settings.Secure.getInt(getContext().getContentResolver(), getKey(), /* settingsValueOff */ 0) == /* settingsValueOn */ 1; diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityTargetAdapter.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityTargetAdapter.java index ee09c620ec1d0..ecfe4caa5984a 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityTargetAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityTargetAdapter.java @@ -100,14 +100,16 @@ public class AccessibilityTargetAdapter extends Adapter { @ItemType @Override public int getItemViewType(int position) { - if (position == 0) { - return ItemType.FIRST_ITEM; - } - + // This LAST_ITEM condition should be checked before others to ensure proper padding when + // adding a second target via notifyItemInserted(). if (position == (getItemCount() - 1)) { return ItemType.LAST_ITEM; } + if (position == 0) { + return ItemType.FIRST_ITEM; + } + return ItemType.REGULAR_ITEM; } diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuAnimationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuAnimationController.java index e2a9d5456a8ed..105de16ce66b6 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuAnimationController.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuAnimationController.java @@ -403,7 +403,7 @@ class MenuAnimationController { } cancelAndRemoveCallbacksAndMessages(); - mHandler.post(() -> mMenuView.setAlpha(COMPLETELY_OPAQUE)); + mMenuView.setAlpha(COMPLETELY_OPAQUE); } void fadeOutIfEnabled() { diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuListViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuListViewTouchHandler.java index 8a31142a02122..d01590f10253a 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuListViewTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuListViewTouchHandler.java @@ -111,6 +111,7 @@ class MenuListViewTouchHandler implements RecyclerView.OnItemTouchListener { return true; } + mMenuAnimationController.fadeOutIfEnabled(); break; default: // Do nothing } diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuTargetsCallback.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuTargetsCallback.java new file mode 100644 index 0000000000000..849b79ae18a6c --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuTargetsCallback.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2023 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 android.text.TextUtils; + +import androidx.recyclerview.widget.DiffUtil; + +import com.android.internal.accessibility.dialog.AccessibilityTarget; + +import java.util.ArrayList; +import java.util.List; + +/** + * A {@link DiffUtil.Callback} to calculate the difference between old and new menu target List. + */ +class MenuTargetsCallback extends DiffUtil.Callback { + private final List mOldTargets = new ArrayList<>(); + private final List mNewTargets = new ArrayList<>(); + + MenuTargetsCallback(List oldTargets, + List newTargets) { + mOldTargets.addAll(oldTargets); + mNewTargets.addAll(newTargets); + } + + @Override + public int getOldListSize() { + return mOldTargets.size(); + } + + @Override + public int getNewListSize() { + return mNewTargets.size(); + } + + @Override + public boolean areItemsTheSame(int oldIndex, int newIndex) { + return mOldTargets.get(oldIndex).getId().equals(mNewTargets.get(newIndex).getId()); + } + + @Override + public boolean areContentsTheSame(int oldIndex, int newIndex) { + if (!TextUtils.equals(mOldTargets.get(oldIndex).getLabel(), + mNewTargets.get(newIndex).getLabel())) { + return false; + } + + if (!TextUtils.equals(mOldTargets.get(oldIndex).getStateDescription(), + mNewTargets.get(newIndex).getStateDescription())) { + return false; + } + + return true; + } +} 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 28269d943ee35..47770fa28b794 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuView.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuView.java @@ -32,6 +32,7 @@ import android.widget.FrameLayout; import androidx.annotation.NonNull; import androidx.core.view.AccessibilityDelegateCompat; import androidx.lifecycle.Observer; +import androidx.recyclerview.widget.DiffUtil; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerViewAccessibilityDelegate; @@ -222,14 +223,17 @@ class MenuView extends FrameLayout implements } private void onTargetFeaturesChanged(List newTargetFeatures) { - // TODO(b/252756133): Should update specific item instead of the whole list mMenuAnimationController.fadeInNowIfEnabled(); + final List targetFeatures = + Collections.unmodifiableList(mTargetFeatures.stream().toList()); mTargetFeatures.clear(); mTargetFeatures.addAll(newTargetFeatures); - mMenuViewAppearance.setTargetFeaturesSize(mTargetFeatures.size()); + mMenuViewAppearance.setTargetFeaturesSize(newTargetFeatures.size()); mTargetFeaturesView.setOverScrollMode(mMenuViewAppearance.getMenuScrollMode()); - mAdapter.notifyDataSetChanged(); + DiffUtil.calculateDiff( + new MenuTargetsCallback(targetFeatures, newTargetFeatures)).dispatchUpdatesTo( + mAdapter); onSizeChanged(); onEdgeChanged();