OSDN Git Service

DO NOT MERGE: Enable switch access api to activate/open files in DocsUI.
authorBen Lin <linben@google.com>
Mon, 1 Aug 2016 23:37:13 +0000 (16:37 -0700)
committerBen Lin <linben@google.com>
Tue, 2 Aug 2016 23:53:42 +0000 (16:53 -0700)
Switch Access uses OnClickListener() on individual views to check
whether a view is "clickable" or not. If it is clickable, using
prev/next keys will highlight to these clickable views. Since DocsUI
used to simply trap touch events and did not have any OnClickListeners
on its list/grid child views, switch access was not able to pick up
these views as clickable views. Simply adding an OnClickListener() fixes
this particular bug, but then a regular touch using finger/mouse would
trigger both onClick() and OnSingleTapUp(MotionEvent), which causes
double-firing and lead to unexpected behavior.

This fix overrides two accessibility-related methods in the
recyclerView's layoutManager, which the recyclerView delegates to.
Switch Access should now be routed to the correct behavior (which opens the
file/doc).

Bug: 30077035
Change-Id: I380d7529fa041f7b4905170f43f28a4235dc118d

packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java

index b7c0a9c..8aa7f6e 100644 (file)
@@ -53,10 +53,13 @@ import android.provider.DocumentsContract.Document;
 import android.support.annotation.Nullable;
 import android.support.design.widget.Snackbar;
 import android.support.v13.view.DragStartHelper;
+import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
+import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat;
 import android.support.v7.widget.GridLayoutManager;
 import android.support.v7.widget.GridLayoutManager.SpanSizeLookup;
 import android.support.v7.widget.RecyclerView;
 import android.support.v7.widget.RecyclerView.OnItemTouchListener;
+import android.support.v7.widget.RecyclerView.Recycler;
 import android.support.v7.widget.RecyclerView.RecyclerListener;
 import android.support.v7.widget.RecyclerView.ViewHolder;
 import android.text.BidiFormatter;
@@ -243,7 +246,40 @@ public class DirectoryFragment extends Fragment
 
         mRecView.setAdapter(mAdapter);
 
-        mLayout = new GridLayoutManager(getContext(), mColumnCount);
+        // Switch Access Accessibility API needs an {@link AccessibilityDelegate} to know the proper
+        // route when user selects an UI element. It usually guesses this if the element has an
+        // {@link OnClickListener}, but since we do not have one for itemView, we will need to
+        // manually route it to the right behavior. RecyclerView has its own AccessibilityDelegate,
+        // and routes it to its LayoutManager; so we must override the LayoutManager's accessibility
+        // methods to route clicks correctly.
+        mLayout = new GridLayoutManager(getContext(), mColumnCount) {
+            @Override
+            public void onInitializeAccessibilityNodeInfoForItem(
+                    RecyclerView.Recycler recycler, RecyclerView.State state,
+                    View host, AccessibilityNodeInfoCompat info) {
+                super.onInitializeAccessibilityNodeInfoForItem(recycler, state, host, info);
+                info.addAction(AccessibilityActionCompat.ACTION_CLICK);
+            }
+
+            @Override
+            public boolean performAccessibilityActionForItem(
+                    RecyclerView.Recycler recycler, RecyclerView.State state, View view,
+                    int action, Bundle args) {
+                // We are only handling click events; route all other to default implementation
+                if (action == AccessibilityNodeInfoCompat.ACTION_CLICK) {
+                    RecyclerView.ViewHolder vh = mRecView.getChildViewHolder(view);
+                    if (vh instanceof DocumentHolder) {
+                        DocumentHolder dh = (DocumentHolder) vh;
+                        if (dh.mEventListener != null) {
+                            dh.mEventListener.onActivate(dh);
+                            return true;
+                        }
+                    }
+                }
+                return super.performAccessibilityActionForItem(recycler, state, view, action,
+                        args);
+            }
+        };
         SpanSizeLookup lookup = mAdapter.createSpanSizeLookup();
         if (lookup != null) {
             mLayout.setSpanSizeLookup(lookup);