From ef696934b04143463fb4a33d21980a7b3a4a8168 Mon Sep 17 00:00:00 2001 From: Michal Brzezinski Date: Thu, 2 Nov 2023 14:07:35 +0000 Subject: [PATCH] Focusing on item highlighted coming from search result There are two cases that require different approach: 1. No scrolling or only a bit of scrolling is required to reach desired item - then we can focus the item straight away. 2. We're still scrolling when highlighting is started - after DELAY_COLLAPSE_DURATION_MILLIS + DELAY_HIGHLIGHT_DURATION_MILLIS. Then we need to wait till we reach the element/stop scrolling and focus afterwards. Test: case 1: search for any setting, press enter and see if keyboard is focused on search result Test: case 2: search for setting that requires a lot of scrolling, e.g. "display cutout" and see if it's get the focus after selecting Fixes: 307902050 Change-Id: Ifa0738748184e78074099e33e09e5d8df198177e --- .../settings/SettingsPreferenceFragment.java | 1 + .../HighlightablePreferenceGroupAdapter.java | 31 +++++++++++++++---- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/com/android/settings/SettingsPreferenceFragment.java b/src/com/android/settings/SettingsPreferenceFragment.java index 278ede4b2e8..d7a276edfc0 100644 --- a/src/com/android/settings/SettingsPreferenceFragment.java +++ b/src/com/android/settings/SettingsPreferenceFragment.java @@ -479,6 +479,7 @@ public abstract class SettingsPreferenceFragment extends InstrumentedPreferenceF mDialogFragment.dismiss(); mDialogFragment = null; } + getListView().clearOnScrollListeners(); } super.onDetach(); } diff --git a/src/com/android/settings/widget/HighlightablePreferenceGroupAdapter.java b/src/com/android/settings/widget/HighlightablePreferenceGroupAdapter.java index a93a986ea2a..7145460d460 100644 --- a/src/com/android/settings/widget/HighlightablePreferenceGroupAdapter.java +++ b/src/com/android/settings/widget/HighlightablePreferenceGroupAdapter.java @@ -29,12 +29,14 @@ import android.util.Log; import android.util.TypedValue; import android.view.View; +import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import androidx.preference.PreferenceGroup; import androidx.preference.PreferenceGroupAdapter; import androidx.preference.PreferenceScreen; import androidx.preference.PreferenceViewHolder; import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.RecyclerView.ViewHolder; import com.android.settings.R; import com.android.settings.SettingsPreferenceFragment; @@ -159,15 +161,32 @@ public class HighlightablePreferenceGroupAdapter extends PreferenceGroupAdapter root.postDelayed(() -> { if (ensureHighlightPosition()) { recyclerView.smoothScrollToPosition(mHighlightPosition); + highlightAndFocusTargetItem(recyclerView, mHighlightPosition); } }, DELAY_HIGHLIGHT_DURATION_MILLIS); + } - // Highlight preference after 900 milliseconds. - root.postDelayed(() -> { - if (ensureHighlightPosition()) { - notifyItemChanged(mHighlightPosition); - } - }, DELAY_COLLAPSE_DURATION_MILLIS + DELAY_HIGHLIGHT_DURATION_MILLIS); + private void highlightAndFocusTargetItem(RecyclerView recyclerView, int highlightPosition) { + ViewHolder target = recyclerView.findViewHolderForAdapterPosition(highlightPosition); + if (target != null) { // view already visible + notifyItemChanged(mHighlightPosition); + target.itemView.requestFocus(); + } else { // otherwise we're about to scroll to that view (but we might not be scrolling yet) + recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { + if (newState == RecyclerView.SCROLL_STATE_IDLE) { + notifyItemChanged(mHighlightPosition); + ViewHolder target = recyclerView + .findViewHolderForAdapterPosition(highlightPosition); + if (target != null) { + target.itemView.requestFocus(); + } + recyclerView.removeOnScrollListener(this); + } + } + }); + } } /**