From d7211c85d676dbb6071bb765c352c748f08d5458 Mon Sep 17 00:00:00 2001 From: Ben Kwa Date: Wed, 10 Feb 2016 11:54:55 -0800 Subject: [PATCH] Make left- and right- arrow jump rows in grid mode. Like ChromeOS. Pressing left at the beginning of a row of files in grid mode, will move focus up to the end of the preceding row. Analogous behaviour for right-arrow at the end of a row. BUG=27127282 Change-Id: I3b36c1da6559aaf01558807913502f8ab87a9e6e (cherry picked from commit f55e5b714d4adc9f343ab7e691a6846ffa6cd7b1) --- .../dirlist/DirectoryFragment.java | 5 +++ .../documentsui/dirlist/FocusManager.java | 40 ++++++++++++++----- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java index 46ae67fc8d830..f8735b2f99a19 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java +++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java @@ -193,6 +193,11 @@ public class DirectoryFragment extends Fragment implements DocumentsAdapter.Envi mRecView.setItemAnimator(new DirectoryItemAnimator(getActivity())); + // Make the RecyclerView unfocusable. This is needed in order for the focus search code in + // FocusManager to work correctly. Setting android:focusable=false in the layout xml doesn't + // work, for some reason. + mRecView.setFocusable(false); + // TODO: Add a divider between views (which might use RecyclerView.ItemDecoration). if (DEBUG_ENABLE_DND) { setupDragAndDropOnDirectoryView(mRecView); diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FocusManager.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FocusManager.java index cce3e22c23be8..93ec8426e74f6 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FocusManager.java +++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FocusManager.java @@ -16,7 +16,7 @@ package com.android.documentsui.dirlist; -import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.Log; import android.view.KeyEvent; @@ -32,14 +32,14 @@ class FocusManager implements View.OnFocusChangeListener { private RecyclerView mView; private RecyclerView.Adapter mAdapter; - private LinearLayoutManager mLayout; + private GridLayoutManager mLayout; private int mLastFocusPosition = RecyclerView.NO_POSITION; public FocusManager(RecyclerView view) { mView = view; mAdapter = view.getAdapter(); - mLayout = (LinearLayoutManager) view.getLayoutManager(); + mLayout = (GridLayoutManager) view.getLayoutManager(); } /** @@ -134,12 +134,27 @@ class FocusManager implements View.OnFocusChangeListener { case KeyEvent.KEYCODE_DPAD_DOWN: searchDir = View.FOCUS_DOWN; break; - case KeyEvent.KEYCODE_DPAD_LEFT: - searchDir = View.FOCUS_LEFT; - break; - case KeyEvent.KEYCODE_DPAD_RIGHT: - searchDir = View.FOCUS_RIGHT; - break; + } + + if (inGridMode()) { + int currentPosition = mView.getChildAdapterPosition(view); + // Left and right arrow keys only work in grid mode. + switch (keyCode) { + case KeyEvent.KEYCODE_DPAD_LEFT: + if (currentPosition > 0) { + // Stop backward focus search at the first item, otherwise focus will wrap + // around to the last visible item. + searchDir = View.FOCUS_BACKWARD; + } + break; + case KeyEvent.KEYCODE_DPAD_RIGHT: + if (currentPosition < mAdapter.getItemCount() - 1) { + // Stop forward focus search at the last item, otherwise focus will wrap + // around to the first visible item. + searchDir = View.FOCUS_FORWARD; + } + break; + } } if (searchDir != -1) { @@ -238,4 +253,11 @@ class FocusManager implements View.OnFocusChangeListener { }); } } + + /** + * @return Whether the layout manager is currently in a grid-configuration. + */ + private boolean inGridMode() { + return mLayout.getSpanCount() > 1; + } }