Merge "Fling while overscrolled: ScrollView/HorizontalScrollView" into sc-dev

This commit is contained in:
George Mount
2021-04-29 23:05:32 +00:00
committed by Android (Google) Code Review
2 changed files with 43 additions and 22 deletions

View File

@@ -47,6 +47,7 @@ import android.view.animation.AnimationUtils;
import android.view.inspector.InspectableProperty;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import java.util.List;
@@ -86,19 +87,23 @@ public class HorizontalScrollView extends FrameLayout {
*
* Even though this field is practically final, we cannot make it final because there are apps
* setting it via reflection and they need to keep working until they target Q.
* @hide
*/
@NonNull
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124053130)
private EdgeEffect mEdgeGlowLeft;
@VisibleForTesting
public EdgeEffect mEdgeGlowLeft;
/**
* Tracks the state of the bottom edge glow.
*
* Even though this field is practically final, we cannot make it final because there are apps
* setting it via reflection and they need to keep working until they target Q.
* @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124052619)
private EdgeEffect mEdgeGlowRight;
@VisibleForTesting
public EdgeEffect mEdgeGlowRight;
/**
* Position of the last motion event.
@@ -774,11 +779,8 @@ public class HorizontalScrollView extends FrameLayout {
// Calling overScrollBy will call onOverScrolled, which
// calls onScrollChanged if applicable.
if (overScrollBy(deltaX, 0, mScrollX, 0, range, 0,
mOverscrollDistance, 0, true)) {
// Break our velocity if we hit a scroll barrier.
mVelocityTracker.clear();
}
overScrollBy(deltaX, 0, mScrollX, 0, range, 0,
mOverscrollDistance, 0, true);
if (canOverscroll && deltaX != 0f) {
final int pulledToX = oldX + deltaX;
@@ -1737,23 +1739,31 @@ public class HorizontalScrollView extends FrameLayout {
public void fling(int velocityX) {
if (getChildCount() > 0) {
int width = getWidth() - mPaddingRight - mPaddingLeft;
int right = getChildAt(0).getWidth();
int right = getChildAt(0).getRight() - mPaddingLeft;
mScroller.fling(mScrollX, mScrollY, velocityX, 0, 0,
Math.max(0, right - width), 0, 0, width/2, 0);
int maxScroll = Math.max(0, right - width);
final boolean movingRight = velocityX > 0;
if (mScrollX == 0 && !mEdgeGlowLeft.isFinished()) {
mEdgeGlowLeft.onAbsorb(-velocityX);
} else if (mScrollX == maxScroll && !mEdgeGlowRight.isFinished()) {
mEdgeGlowRight.onAbsorb(velocityX);
} else {
mScroller.fling(mScrollX, mScrollY, velocityX, 0, 0,
maxScroll, 0, 0, width / 2, 0);
View currentFocused = findFocus();
View newFocused = findFocusableViewInMyBounds(movingRight,
mScroller.getFinalX(), currentFocused);
final boolean movingRight = velocityX > 0;
if (newFocused == null) {
newFocused = this;
}
View currentFocused = findFocus();
View newFocused = findFocusableViewInMyBounds(movingRight,
mScroller.getFinalX(), currentFocused);
if (newFocused != currentFocused) {
newFocused.requestFocus(movingRight ? View.FOCUS_RIGHT : View.FOCUS_LEFT);
if (newFocused == null) {
newFocused = this;
}
if (newFocused != currentFocused) {
newFocused.requestFocus(movingRight ? View.FOCUS_RIGHT : View.FOCUS_LEFT);
}
}
postInvalidateOnAnimation();

View File

@@ -49,6 +49,7 @@ import android.view.animation.AnimationUtils;
import android.view.inspector.InspectableProperty;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import java.util.List;
@@ -95,20 +96,24 @@ public class ScrollView extends FrameLayout {
*
* Even though this field is practically final, we cannot make it final because there are apps
* setting it via reflection and they need to keep working until they target Q.
* @hide
*/
@NonNull
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768600)
private EdgeEffect mEdgeGlowTop;
@VisibleForTesting
public EdgeEffect mEdgeGlowTop;
/**
* Tracks the state of the bottom edge glow.
*
* Even though this field is practically final, we cannot make it final because there are apps
* setting it via reflection and they need to keep working until they target Q.
* @hide
*/
@NonNull
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769386)
private EdgeEffect mEdgeGlowBottom;
@VisibleForTesting
public EdgeEffect mEdgeGlowBottom;
/**
* Position of the last motion event.
@@ -1791,9 +1796,15 @@ public class ScrollView extends FrameLayout {
final boolean canFling = (mScrollY > 0 || velocityY > 0) &&
(mScrollY < getScrollRange() || velocityY < 0);
if (!dispatchNestedPreFling(0, velocityY)) {
dispatchNestedFling(0, velocityY, canFling);
final boolean consumed = dispatchNestedFling(0, velocityY, canFling);
if (canFling) {
fling(velocityY);
} else if (!consumed) {
if (!mEdgeGlowTop.isFinished()) {
mEdgeGlowTop.onAbsorb(-velocityY);
} else if (!mEdgeGlowBottom.isFinished()) {
mEdgeGlowBottom.onAbsorb(velocityY);
}
}
}
}