From 6c286befa31480924cf1edd600b51d8f732f373c Mon Sep 17 00:00:00 2001 From: Evan Rosky Date: Wed, 19 Apr 2017 17:23:32 -0700 Subject: 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 --- core/java/android/view/View.java | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) (limited to 'core/java/android/view/View.java') 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. -- cgit v1.2.3