From 49fc4dcd4c0d88b74084d6b2a2d843ad17b8a1eb Mon Sep 17 00:00:00 2001 From: Jaewan Kim Date: Tue, 21 May 2013 03:02:30 +0900 Subject: Fix out-of-screen item can take focus issue In case of a ListView has a item which takes more than 33% of its height (result from getMaxScrollAmount), scroll does not move enough to show all the item. In this case, consecutive arrow scroll moves selection everytime while scroll may not move that much. This fixes the issue by checking the visibility of current selection in advance. Bug: 8831751 Change-Id: Ic747bd5513c6734aaf1a1d08e497c1e3ef835004 --- core/java/android/widget/ListView.java | 35 +++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java index f42999d283cb..a82bebd3828b 100644 --- a/core/java/android/widget/ListView.java +++ b/core/java/android/widget/ListView.java @@ -2425,24 +2425,37 @@ public class ListView extends AbsListView { /** * Used by {@link #arrowScrollImpl(int)} to help determine the next selected position - * to move to. This can return a position currently not represented by a view on screen - * but only in the direction given. + * to move to. This return a position in the direction given if the selected item + * is fully visible. * + * @param selectedView Current selected view to move from * @param selectedPos Current selected position to move from * @param direction Direction to move in * @return Desired selected position after moving in the given direction */ - private final int nextSelectedPositionForDirection(int selectedPos, int direction) { + private final int nextSelectedPositionForDirection( + View selectedView, int selectedPos, int direction) { int nextSelected; + if (direction == View.FOCUS_DOWN) { - nextSelected = selectedPos != INVALID_POSITION && selectedPos >= mFirstPosition ? - selectedPos + 1 : - mFirstPosition; + final int listBottom = getHeight() - mListPadding.bottom; + if (selectedView != null && selectedView.getBottom() <= listBottom) { + nextSelected = selectedPos != INVALID_POSITION && selectedPos >= mFirstPosition ? + selectedPos + 1 : + mFirstPosition; + } else { + return INVALID_POSITION; + } } else { - final int lastPos = mFirstPosition + getChildCount() - 1; - nextSelected = selectedPos != INVALID_POSITION && selectedPos <= lastPos ? - selectedPos - 1 : - lastPos; + final int listTop = mListPadding.top; + if (selectedView != null && selectedView.getTop() >= listTop) { + final int lastPos = mFirstPosition + getChildCount() - 1; + nextSelected = selectedPos != INVALID_POSITION && selectedPos <= lastPos ? + selectedPos - 1 : + lastPos; + } else { + return INVALID_POSITION; + } } if (nextSelected < 0 || nextSelected >= mAdapter.getCount()) { @@ -2466,7 +2479,7 @@ public class ListView extends AbsListView { View selectedView = getSelectedView(); int selectedPos = mSelectedPosition; - int nextSelectedPosition = nextSelectedPositionForDirection(selectedPos, direction); + int nextSelectedPosition = nextSelectedPositionForDirection(selectedView, selectedPos, direction); int amountToScroll = amountToScroll(direction, nextSelectedPosition); // if we are moving focus, we may OVERRIDE the default behavior -- cgit v1.2.3-59-g8ed1b