Don't allow apps to request scrolls to out-of-bounds positions

An app was requesting smooth scrolling to a view position beyond the
number of items in the list. This caused our setup logic to execute on
every frame, waiting for the target view to be added.

This fix clamps the requested target position to the number of items
actually in the list.

Issue #6572175 Messaging: Sometimes conversation doesn't scroll when focus is brought to the compose field

Change-Id: I23707aeb213e67af4297713a03c2f5b446c8e2b6
This commit is contained in:
Chet Haase
2012-06-08 15:01:56 -07:00
parent 059537e792
commit 0061e16e53

View File

@@ -4289,14 +4289,15 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
final int lastPos = firstPos + childCount - 1;
int viewTravelCount;
if (position < firstPos) {
viewTravelCount = firstPos - position + 1;
int clampedPosition = Math.max(0, Math.min(getCount() - 1, position));
if (clampedPosition < firstPos) {
viewTravelCount = firstPos - clampedPosition + 1;
mMode = MOVE_UP_POS;
} else if (position > lastPos) {
viewTravelCount = position - lastPos + 1;
} else if (clampedPosition > lastPos) {
viewTravelCount = clampedPosition - lastPos + 1;
mMode = MOVE_DOWN_POS;
} else {
scrollToVisible(position, INVALID_POSITION, SCROLL_DURATION);
scrollToVisible(clampedPosition, INVALID_POSITION, SCROLL_DURATION);
return;
}
@@ -4305,7 +4306,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
} else {
mScrollDuration = SCROLL_DURATION;
}
mTargetPos = position;
mTargetPos = clampedPosition;
mBoundPos = INVALID_POSITION;
mLastSeenPos = INVALID_POSITION;
@@ -4340,14 +4341,15 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
final int lastPos = firstPos + childCount - 1;
int viewTravelCount;
if (position < firstPos) {
int clampedPosition = Math.max(0, Math.min(getCount() - 1, position));
if (clampedPosition < firstPos) {
final int boundPosFromLast = lastPos - boundPosition;
if (boundPosFromLast < 1) {
// Moving would shift our bound position off the screen. Abort.
return;
}
final int posTravel = firstPos - position + 1;
final int posTravel = firstPos - clampedPosition + 1;
final int boundTravel = boundPosFromLast - 1;
if (boundTravel < posTravel) {
viewTravelCount = boundTravel;
@@ -4356,14 +4358,14 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
viewTravelCount = posTravel;
mMode = MOVE_UP_POS;
}
} else if (position > lastPos) {
} else if (clampedPosition > lastPos) {
final int boundPosFromFirst = boundPosition - firstPos;
if (boundPosFromFirst < 1) {
// Moving would shift our bound position off the screen. Abort.
return;
}
final int posTravel = position - lastPos + 1;
final int posTravel = clampedPosition - lastPos + 1;
final int boundTravel = boundPosFromFirst - 1;
if (boundTravel < posTravel) {
viewTravelCount = boundTravel;
@@ -4373,7 +4375,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
mMode = MOVE_DOWN_POS;
}
} else {
scrollToVisible(position, boundPosition, SCROLL_DURATION);
scrollToVisible(clampedPosition, boundPosition, SCROLL_DURATION);
return;
}
@@ -4382,7 +4384,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
} else {
mScrollDuration = SCROLL_DURATION;
}
mTargetPos = position;
mTargetPos = clampedPosition;
mBoundPos = boundPosition;
mLastSeenPos = INVALID_POSITION;
@@ -4415,7 +4417,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
offset += getPaddingTop();
mTargetPos = position;
mTargetPos = Math.max(0, Math.min(getCount() - 1, position));
mOffsetFromTop = offset;
mBoundPos = INVALID_POSITION;
mLastSeenPos = INVALID_POSITION;
@@ -4425,13 +4427,13 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
final int lastPos = firstPos + childCount - 1;
int viewTravelCount;
if (position < firstPos) {
viewTravelCount = firstPos - position;
} else if (position > lastPos) {
viewTravelCount = position - lastPos;
if (mTargetPos < firstPos) {
viewTravelCount = firstPos - mTargetPos;
} else if (mTargetPos > lastPos) {
viewTravelCount = mTargetPos - lastPos;
} else {
// On-screen, just scroll.
final int targetTop = getChildAt(position - firstPos).getTop();
final int targetTop = getChildAt(mTargetPos - firstPos).getTop();
smoothScrollBy(targetTop - offset, duration, true);
return;
}