setOverScrollMode
该行为会应用于使用 的所有应用,并且适用于以下类中的所有内容:
视觉效果对垂直滚动和水平滚动都适用。由于它默认应用于未停用滚动的所有应用,因此可以为用户提供更一致的界面体验。
最佳做法
为了确保新的滚动体验与您的应用完美搭配,请遵循以下最佳做法:
拉伸 EdgeEffect 的用法
EdgeEffect
添加了两个用于实现拉伸滚动效果的 API。
float getDistance()
float onPullDistance(float deltaDistance, float displacement)
为了利用拉伸滚动提供最佳用户体验,请执行以下操作:
当用户在释放动画过程中释放并轻触内容时,将轻触注册为“捕捉”。用户停止动画并再次开始操控拉伸。
当用户沿拉伸的相反方向移动手指时,释放拉伸,直到其完全消失,然后开始滚动。
当用户在拉伸过程中快速滑动时,快速滑动
EdgeEffect
以增强拉伸效果。
捕捉动画
当用户捕捉活动的拉伸动画时, 会返回 false
。这表示拉伸应由轻触动作操控。在大多数容器中,这在 中检测,如以下代码段所示:
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
...
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
...
mIsBeingDragged = !mEdgeEffectBottom.isFinished()
|| !mEdgeEffectTop.isFinished();
...
在前面的示例中,当 mIsBeingDragged
为 true
时,onInterceptTouchEvent()
返回 true
,因此这对于在子级有机会消耗事件之前消耗事件已经足够了。
释放滚动效果
务必在滚动之前释放拉伸效果,以防止将拉伸应用于滚动内容。以下代码示例展示了这一点:
@Override
public boolean onTouchEvent(MotionEvent ev) {
final int actionMasked = ev.getActionMasked();
switch (actionMasked) {
case MotionEvent.ACTION_MOVE:
final float x = ev.getX(activePointerIndex);
final float y = ev.getY(activePointerIndex);
float deltaY = y - mLastMotionY;
float pullDistance = deltaY / getHeight();
float displacement = x / getWidth();
if (deltaY < 0 && mEdgeEffectTop.getDistance() > 0) {
deltaY -= getHeight() * mEdgeEffectTop
.onPullDistance(pullDistance, displacement);
}
if (deltaY > 0 && mEdgeEffectBottom.getDistance() > 0) {
deltaY += getHeight() * mEdgeEffectBottom
.onPullDistance(-pullDistance, 1 - displacement);
}
...
拖动时,在将触摸事件传递给嵌套滚动或拖动滚动内容之前,必须消耗 EdgeEffect
的拉取距离。在前面的代码示例中,当正在显示边缘效果且可以通过动作将其释放时,getDistance()
会返回一个正值。当触摸事件释放拉伸时,它首先由 EdgeEffect
消耗,这样就可以在显示其他效果(如嵌套滚动)之前完全释放。您可以使用 getDistance()
了解释放当前效果所需的拉取距离。
onPullDistance()
与 onPull()
的不同之处在于返回所传递增量的已消耗量。onPull()
以前允许发光效果的总距离为负值。在 Android 12 及更高版本中,如果在 getDistance()
为 0 时向 onPull()
或 onPullDistance()
传递负的 deltaDistance
值,则拉伸不会发生任何变化。
停用
您可以在 XML 布局文件中或以编程方式停用滚动。以下 XML 代码展示了布局文件中设置的 android:overScrollMode
。
<!-- Via markup -->
<ScrollView
...
android:overScrollMode="never"
...
>
以编程方式停用,如以下代码段所示:
<!-- Programmatically-->
...
recyclerview.setOverScrollMode(View.OVER_SCROLL_NEVER);
...