Loading core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java +5 −1 Original line number Diff line number Diff line Loading @@ -86,7 +86,11 @@ public class ChooserMultiProfilePagerAdapter extends AbstractMultiProfilePagerAd final LayoutInflater inflater = LayoutInflater.from(getContext()); final ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.chooser_list_per_profile, null, false); return new ChooserProfileDescriptor(rootView, adapter); ChooserProfileDescriptor profileDescriptor = new ChooserProfileDescriptor(rootView, adapter); profileDescriptor.recyclerView.setAccessibilityDelegateCompat( new ChooserRecyclerViewAccessibilityDelegate(profileDescriptor.recyclerView)); return profileDescriptor; } RecyclerView getListViewForIndex(int index) { Loading core/java/com/android/internal/app/ChooserRecyclerViewAccessibilityDelegate.java 0 → 100644 +92 −0 Original line number Diff line number Diff line /* * 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.internal.app; import android.annotation.NonNull; import android.graphics.Rect; import android.view.View; import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; import com.android.internal.widget.RecyclerView; import com.android.internal.widget.RecyclerViewAccessibilityDelegate; class ChooserRecyclerViewAccessibilityDelegate extends RecyclerViewAccessibilityDelegate { private final Rect mTempRect = new Rect(); private final int[] mConsumed = new int[2]; ChooserRecyclerViewAccessibilityDelegate(RecyclerView recyclerView) { super(recyclerView); } @Override public boolean onRequestSendAccessibilityEvent( @NonNull ViewGroup host, @NonNull View view, @NonNull AccessibilityEvent event) { boolean result = super.onRequestSendAccessibilityEvent(host, view, event); if (result && event.getEventType() == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED) { ensureViewOnScreenVisibility((RecyclerView) host, view); } return result; } /** * Bring the view that received accessibility focus on the screen. * The method's logic is based on a model where RecyclerView is a child of another scrollable * component (ResolverDrawerLayout) and can be partially scrolled off the screen. In that case, * RecyclerView's children that are positioned fully within RecyclerView bounds but scrolled * out of the screen by the outer component, when selected by the accessibility navigation will * remain off the screen (as neither components detect such specific case). * If the view that receiving accessibility focus is scrolled of the screen, perform the nested * scrolling to make in visible. */ private void ensureViewOnScreenVisibility(RecyclerView recyclerView, View view) { View child = recyclerView.findContainingItemView(view); if (child == null) { return; } recyclerView.getBoundsOnScreen(mTempRect, true); int recyclerOnScreenTop = mTempRect.top; int recyclerOnScreenBottom = mTempRect.bottom; child.getBoundsOnScreen(mTempRect); int dy = 0; // if needed, do the page-length scroll instead of just a row-length scroll as // ResolverDrawerLayout snaps to the compact view and the row-length scroll can be snapped // back right away. if (mTempRect.top < recyclerOnScreenTop) { // snap to the bottom dy = mTempRect.bottom - recyclerOnScreenBottom; } else if (mTempRect.bottom > recyclerOnScreenBottom) { // snap to the top dy = mTempRect.top - recyclerOnScreenTop; } nestedVerticalScrollBy(recyclerView, dy); } private void nestedVerticalScrollBy(RecyclerView recyclerView, int dy) { if (dy == 0) { return; } recyclerView.startNestedScroll(View.SCROLL_AXIS_VERTICAL); if (recyclerView.dispatchNestedPreScroll(0, dy, mConsumed, null)) { dy -= mConsumed[1]; } recyclerView.scrollBy(0, dy); recyclerView.stopNestedScroll(); } } Loading
core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java +5 −1 Original line number Diff line number Diff line Loading @@ -86,7 +86,11 @@ public class ChooserMultiProfilePagerAdapter extends AbstractMultiProfilePagerAd final LayoutInflater inflater = LayoutInflater.from(getContext()); final ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.chooser_list_per_profile, null, false); return new ChooserProfileDescriptor(rootView, adapter); ChooserProfileDescriptor profileDescriptor = new ChooserProfileDescriptor(rootView, adapter); profileDescriptor.recyclerView.setAccessibilityDelegateCompat( new ChooserRecyclerViewAccessibilityDelegate(profileDescriptor.recyclerView)); return profileDescriptor; } RecyclerView getListViewForIndex(int index) { Loading
core/java/com/android/internal/app/ChooserRecyclerViewAccessibilityDelegate.java 0 → 100644 +92 −0 Original line number Diff line number Diff line /* * 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.internal.app; import android.annotation.NonNull; import android.graphics.Rect; import android.view.View; import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; import com.android.internal.widget.RecyclerView; import com.android.internal.widget.RecyclerViewAccessibilityDelegate; class ChooserRecyclerViewAccessibilityDelegate extends RecyclerViewAccessibilityDelegate { private final Rect mTempRect = new Rect(); private final int[] mConsumed = new int[2]; ChooserRecyclerViewAccessibilityDelegate(RecyclerView recyclerView) { super(recyclerView); } @Override public boolean onRequestSendAccessibilityEvent( @NonNull ViewGroup host, @NonNull View view, @NonNull AccessibilityEvent event) { boolean result = super.onRequestSendAccessibilityEvent(host, view, event); if (result && event.getEventType() == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED) { ensureViewOnScreenVisibility((RecyclerView) host, view); } return result; } /** * Bring the view that received accessibility focus on the screen. * The method's logic is based on a model where RecyclerView is a child of another scrollable * component (ResolverDrawerLayout) and can be partially scrolled off the screen. In that case, * RecyclerView's children that are positioned fully within RecyclerView bounds but scrolled * out of the screen by the outer component, when selected by the accessibility navigation will * remain off the screen (as neither components detect such specific case). * If the view that receiving accessibility focus is scrolled of the screen, perform the nested * scrolling to make in visible. */ private void ensureViewOnScreenVisibility(RecyclerView recyclerView, View view) { View child = recyclerView.findContainingItemView(view); if (child == null) { return; } recyclerView.getBoundsOnScreen(mTempRect, true); int recyclerOnScreenTop = mTempRect.top; int recyclerOnScreenBottom = mTempRect.bottom; child.getBoundsOnScreen(mTempRect); int dy = 0; // if needed, do the page-length scroll instead of just a row-length scroll as // ResolverDrawerLayout snaps to the compact view and the row-length scroll can be snapped // back right away. if (mTempRect.top < recyclerOnScreenTop) { // snap to the bottom dy = mTempRect.bottom - recyclerOnScreenBottom; } else if (mTempRect.bottom > recyclerOnScreenBottom) { // snap to the top dy = mTempRect.top - recyclerOnScreenTop; } nestedVerticalScrollBy(recyclerView, dy); } private void nestedVerticalScrollBy(RecyclerView recyclerView, int dy) { if (dy == 0) { return; } recyclerView.startNestedScroll(View.SCROLL_AXIS_VERTICAL); if (recyclerView.dispatchNestedPreScroll(0, dy, mConsumed, null)) { dy -= mConsumed[1]; } recyclerView.scrollBy(0, dy); recyclerView.stopNestedScroll(); } }