diff options
| author | 2017-04-19 17:23:32 -0700 | |
|---|---|---|
| committer | 2017-04-26 12:50:58 -0700 | |
| commit | 6c286befa31480924cf1edd600b51d8f732f373c (patch) | |
| tree | 94189a43cc8bf5afd6b3689bba367daa7f9ad87f | |
| parent | 2be0a532bf485988aba1b278f070259d9568d80a (diff) | |
Only save focus in keyboard navigation clusters when appropriate
- tabbing forward/backward should not save cluster focus. If
focus leaves a cluster due to normal forward/backward navigation
the cluster focus is cleared.
- directional arrows or cluster jumps (meta+tab) will save focus
in the cluster so that cluster-jumping back will restore it.
Also fixed a couple small bugs: focusable viewgroups wouldn't save
properly, focusIncluster wasn't cleared properly.
Bug: 35274351
Test: Added CTS test for this behavior.
Change-Id: Ie86218d70b0fc3aa1a709e613a2761a65ab12500
| -rw-r--r-- | core/java/android/view/View.java | 37 | ||||
| -rw-r--r-- | core/java/android/view/ViewGroup.java | 11 |
2 files changed, 36 insertions, 12 deletions
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index bcf0b9060ed7..3e50a47d05d2 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -6468,7 +6468,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (mParent != null) { mParent.requestChildFocus(this, this); - setFocusedInCluster(); + updateFocusedInCluster(oldFocus, direction); } if (mAttachInfo != null) { @@ -9834,22 +9834,47 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @hide */ public final void setFocusedInCluster() { - View top = findKeyboardNavigationCluster(); - if (top == this) { + setFocusedInCluster(findKeyboardNavigationCluster()); + } + + private void setFocusedInCluster(View cluster) { + if (this instanceof ViewGroup) { + ((ViewGroup) this).mFocusedInCluster = null; + } + if (cluster == this) { return; } ViewParent parent = mParent; View child = this; while (parent instanceof ViewGroup) { - ((ViewGroup) parent).setFocusedInCluster(child); - if (parent == top) { - return; + ((ViewGroup) parent).mFocusedInCluster = child; + if (parent == cluster) { + break; } child = (View) parent; parent = parent.getParent(); } } + private void updateFocusedInCluster(View oldFocus, @FocusDirection int direction) { + if (oldFocus != null) { + View oldCluster = oldFocus.findKeyboardNavigationCluster(); + View cluster = findKeyboardNavigationCluster(); + if (oldCluster != cluster) { + // Going from one cluster to another, so save last-focused. + // This covers cluster jumps because they are always FOCUS_DOWN + oldFocus.setFocusedInCluster(oldCluster); + if (direction == FOCUS_FORWARD || direction == FOCUS_BACKWARD) { + // This is a result of ordered navigation so consider navigation through + // the previous cluster "complete" and clear its last-focused memory. + if (oldFocus.mParent instanceof ViewGroup) { + ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus); + } + } + } + } + } + /** * Returns whether this View should receive focus when the focus is restored for the view * hierarchy containing this view. diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 1977ef5ae989..d3d46cb4f44b 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -143,7 +143,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager // that is or contains a default-focus view. private View mDefaultFocus; // The last child of this ViewGroup which held focus within the current cluster - private View mFocusedInCluster; + View mFocusedInCluster; /** * A Transformation used when drawing children, to @@ -807,10 +807,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager return mDefaultFocus != null || super.hasDefaultFocus(); } - void setFocusedInCluster(View child) { - mFocusedInCluster = child; - } - /** * Removes {@code child} (and associated focusedInCluster chain) from the cluster containing * it. @@ -826,8 +822,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager ViewParent parent = this; do { ((ViewGroup) parent).mFocusedInCluster = null; + if (parent == top) { + break; + } parent = parent.getParent(); - } while (parent != top && parent instanceof ViewGroup); + } while (parent instanceof ViewGroup); } @Override |