1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.wallpaper.widget;
17 
18 import android.os.Bundle;
19 import android.view.View;
20 import android.view.ViewGroup;
21 import android.view.accessibility.AccessibilityEvent;
22 
23 import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
24 import androidx.recyclerview.widget.RecyclerView;
25 import androidx.recyclerview.widget.RecyclerViewAccessibilityDelegate;
26 
27 import com.google.android.material.bottomsheet.BottomSheetBehavior;
28 
29 /**
30  * An AccessibilityDelegate class used to fix some RecyclerView-related Talkback issues.
31  * <p>
32  * This is to fix a bug which TalkBack can't visit all wallpaper category/wallpaper items.
33  */
34 public class WallpaperPickerRecyclerViewAccessibilityDelegate
35         extends RecyclerViewAccessibilityDelegate {
36 
37     /**
38      * Interface to be implemented by an Fragment hosting a
39      * {@link WallpaperPickerRecyclerViewAccessibilityDelegate}
40      */
41     public interface BottomSheetHost {
42         /**
43          * Expands the bottom sheet if it's not expanded.
44          */
expandBottomSheet()45         void expandBottomSheet();
46 
47         /**
48          * Gets bottom sheet current state.
49          */
getBottomSheetState()50         int getBottomSheetState();
51 
52         /** Returns {@code true} if the bottom sheet is expanded. */
isExpanded()53         default boolean isExpanded() {
54             return getBottomSheetState() == BottomSheetBehavior.STATE_EXPANDED;
55         }
56     }
57 
58     private final RecyclerView mGridRecyclerView;
59     private final BottomSheetHost mBottomSheetHost;
60     private final int mColumns;
61 
WallpaperPickerRecyclerViewAccessibilityDelegate( RecyclerView recyclerView, BottomSheetHost bottomSheetHost, int columns)62     public WallpaperPickerRecyclerViewAccessibilityDelegate(
63             RecyclerView recyclerView, BottomSheetHost bottomSheetHost, int columns) {
64         super(recyclerView);
65         mGridRecyclerView = recyclerView;
66         mBottomSheetHost = bottomSheetHost;
67         mColumns = columns;
68     }
69 
70     @Override
onRequestSendAccessibilityEvent( ViewGroup host, View child, AccessibilityEvent event)71     public boolean onRequestSendAccessibilityEvent(
72             ViewGroup host, View child, AccessibilityEvent event) {
73         if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED) {
74             int itemPos = mGridRecyclerView.getChildLayoutPosition(child);
75 
76             // Expand the bottom sheet when TB travel to second column.
77             if (mBottomSheetHost != null && !mBottomSheetHost.isExpanded()
78                     && itemPos >= mColumns) {
79                 mBottomSheetHost.expandBottomSheet();
80             }
81         }
82         return super.onRequestSendAccessibilityEvent(host, child, event);
83     }
84 
85     @Override
performAccessibilityAction(View host, int action, Bundle args)86     public boolean performAccessibilityAction(View host, int action, Bundle args) {
87         // Expand the bottom sheet when Switch Access scrolls down grid category.
88         if (action == AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD) {
89             if (mBottomSheetHost != null && !mBottomSheetHost.isExpanded()) {
90                 mBottomSheetHost.expandBottomSheet();
91             }
92         }
93         return super.performAccessibilityAction(host, action, args);
94     }
95 }
96