diff options
| -rw-r--r-- | core/java/android/view/View.java | 16 | ||||
| -rw-r--r-- | core/java/android/view/ViewGroup.java | 40 |
2 files changed, 38 insertions, 18 deletions
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index a69b813c093d..19ae25335f22 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -10028,12 +10028,20 @@ public class View implements Drawable.Callback, KeyEvent.Callback, // Going from one cluster to another, so save last-focused. // This covers cluster jumps because they are always FOCUS_DOWN oldFocus.setFocusedInCluster(oldCluster); + if (!(oldFocus.mParent instanceof ViewGroup)) { + return; + } 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); - } + ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus); + } else if (oldFocus instanceof ViewGroup + && ((ViewGroup) oldFocus).getDescendantFocusability() + == ViewGroup.FOCUS_AFTER_DESCENDANTS + && ViewRootImpl.isViewDescendantOf(this, oldFocus)) { + // This means oldFocus is not focusable since it obviously has a focusable + // child (this). Don't restore focus to it in the future. + ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus); } } } @@ -13080,7 +13088,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, // about in case nothing has focus. even if this specific view // isn't focusable, it may contain something that is, so let // the root view try to give this focus if nothing else does. - if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) { + if ((mParent != null)) { mParent.focusableViewAvailable(this); } } diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 09464eec4d90..8637593b38be 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -833,8 +833,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager public void focusableViewAvailable(View v) { if (mParent != null // shortcut: don't report a new focusable view if we block our descendants from - // getting focus + // getting focus or if we're not visible && (getDescendantFocusability() != FOCUS_BLOCK_DESCENDANTS) + && ((mViewFlags & VISIBILITY_MASK) == VISIBLE) && (isFocusableInTouchMode() || !shouldBlockFocusForTouchscreen()) // shortcut: don't report a new focusable view if we already are focused // (and we don't prefer our descendants) @@ -1159,18 +1160,25 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager // Determine whether we have a focused descendant. final int descendantFocusability = getDescendantFocusability(); if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS) { - final int count = mChildrenCount; - final View[] children = mChildren; + return hasFocusableChild(dispatchExplicit); + } - for (int i = 0; i < count; i++) { - final View child = children[i]; + return false; + } - // In case the subclass has overridden has[Explicit]Focusable, dispatch - // to the expected one for each child even though we share logic here. - if ((dispatchExplicit && child.hasExplicitFocusable()) - || (!dispatchExplicit && child.hasFocusable())) { - return true; - } + boolean hasFocusableChild(boolean dispatchExplicit) { + // Determine whether we have a focusable descendant. + final int count = mChildrenCount; + final View[] children = mChildren; + + for (int i = 0; i < count; i++) { + final View child = children[i]; + + // In case the subclass has overridden has[Explicit]Focusable, dispatch + // to the expected one for each child even though we share logic here. + if ((dispatchExplicit && child.hasExplicitFocusable()) + || (!dispatchExplicit && child.hasFocusable())) { + return true; } } @@ -3230,7 +3238,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager // will refer to a view not-in a cluster. return restoreFocusInCluster(View.FOCUS_DOWN); } - if (isKeyboardNavigationCluster()) { + if (isKeyboardNavigationCluster() || (mViewFlags & VISIBILITY_MASK) != VISIBLE) { return false; } int descendentFocusability = getDescendantFocusability(); @@ -3248,7 +3256,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager return true; } } - if (descendentFocusability == FOCUS_AFTER_DESCENDANTS) { + if (descendentFocusability == FOCUS_AFTER_DESCENDANTS && !hasFocusableChild(false)) { return super.requestFocus(FOCUS_DOWN, null); } return false; @@ -4914,7 +4922,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager child.mParent = this; } - if (child.hasFocus()) { + final boolean childHasFocus = child.hasFocus(); + if (childHasFocus) { requestChildFocus(child, child.findFocus()); } @@ -4927,6 +4936,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager needGlobalAttributesUpdate(true); } ai.mKeepScreenOn = lastKeepOn; + if (!childHasFocus && child.hasFocusable()) { + focusableViewAvailable(child); + } } if (child.isLayoutDirectionInherited()) { |