diff options
author | Wesley.CW Wang <wesleycwwang@google.com> | 2020-06-16 19:11:35 +0800 |
---|---|---|
committer | Wesley.CW Wang <wesleycwwang@google.com> | 2020-06-17 15:00:51 +0800 |
commit | 49bcc2711091dfee873a5dfe005d91b989f9a28a (patch) | |
tree | 90d501ba6bab18820a8f42cb71a669d85b771ba1 /src/com/android/customization/widget/OptionSelectorController.java | |
parent | 0e91a8927647d95114ccf83e58d3183bc8e29a2f (diff) |
Fix TB lose focus when navigating recyclerview
- Issue history: b/37088814 and previous workaround: ag/11747784
- Since the previous workaround no longer works, apply new scroll
behavior to the recyclerview when TB navigating, make sure the focusing item's
previous/next item totally visible, then TB won't lose focus.
video: https://drive.google.com/file/d/1KJQT9cAmm9G5yZGDZZTNnpezDbT_Rh31/view?usp=sharing
Bug: 157007291
Test: manually, enable TB and test the result
Change-Id: I1c4c8416d7b1849cf705db931bcd9c6e5c354719
Diffstat (limited to 'src/com/android/customization/widget/OptionSelectorController.java')
-rw-r--r-- | src/com/android/customization/widget/OptionSelectorController.java | 50 |
1 files changed, 41 insertions, 9 deletions
diff --git a/src/com/android/customization/widget/OptionSelectorController.java b/src/com/android/customization/widget/OptionSelectorController.java index a532e401..69a45a94 100644 --- a/src/com/android/customization/widget/OptionSelectorController.java +++ b/src/com/android/customization/widget/OptionSelectorController.java @@ -26,12 +26,14 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; +import android.view.accessibility.AccessibilityEvent; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.RecyclerViewAccessibilityDelegate; import com.android.customization.model.CustomizationManager; import com.android.customization.model.CustomizationOption; @@ -154,17 +156,15 @@ public class OptionSelectorController<T extends CustomizationOption<T>> { * Initializes the UI for the options passed in the constructor of this class. */ public void initOptions(final CustomizationManager<T> manager) { + mContainer.setAccessibilityDelegateCompat( + new OptionSelectorAccessibilityDelegate(mContainer)); + mAdapter = new RecyclerView.Adapter<TileViewHolder>() { @Override public int getItemViewType(int position) { return mOptions.get(position).getLayoutResId(); } - @Override - public long getItemId(int position) { - return position; - } - @NonNull @Override public TileViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { @@ -232,10 +232,6 @@ public class OptionSelectorController<T extends CustomizationOption<T>> { LinearLayoutManager.HORIZONTAL, false)); Resources res = mContainer.getContext().getResources(); - // A workaround from b/37088814, fix TalkBack will lose focus when receive notify*Changed() - mAdapter.setHasStableIds(true); - mContainer.setItemAnimator(null); - mContainer.setAdapter(mAdapter); // Measure RecyclerView to get to the total amount of space used by all options. @@ -340,4 +336,40 @@ public class OptionSelectorController<T extends CustomizationOption<T>> { } } } + + private class OptionSelectorAccessibilityDelegate extends RecyclerViewAccessibilityDelegate { + + OptionSelectorAccessibilityDelegate(RecyclerView recyclerView) { + super(recyclerView); + } + + @Override + public boolean onRequestSendAccessibilityEvent( + ViewGroup host, View child, AccessibilityEvent event) { + + // Apply this workaround to horizontal recyclerview only, + // since the symptom is TalkBack will lose focus when navigating horizontal list items. + if (mContainer.getLayoutManager() != null + && mContainer.getLayoutManager().canScrollHorizontally() + && event.getEventType() == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED) { + int itemPos = mContainer.getChildLayoutPosition(child); + int itemWidth = mContainer.getContext().getResources() + .getDimensionPixelOffset(R.dimen.option_tile_width); + int itemMarginHorizontal = mContainer.getContext().getResources() + .getDimensionPixelOffset(R.dimen.option_tile_margin_horizontal) * 2; + int scrollOffset = itemWidth + itemMarginHorizontal; + + // Make focusing item's previous/next item totally visible when changing focus, + // ensure TalkBack won't lose focus when recyclerview scrolling. + if (itemPos >= ((LinearLayoutManager) mContainer.getLayoutManager()) + .findLastCompletelyVisibleItemPosition()) { + mContainer.scrollBy(scrollOffset, 0); + } else if (itemPos <= ((LinearLayoutManager) mContainer.getLayoutManager()) + .findFirstCompletelyVisibleItemPosition() && itemPos != 0) { + mContainer.scrollBy(-scrollOffset, 0); + } + } + return super.onRequestSendAccessibilityEvent(host, child, event); + } + } } |