【问题标题】:How can you correctly continue the fling of a ScrollView when adding children?添加子项时如何正确继续滚动 ScrollView?
【发布时间】:2026-01-06 13:10:01
【问题描述】:

上下文:我有一个ScrollView,它可能在投掷期间将子项添加到其内容视图中。由于投掷配置了ScrollView 内容的高度之前添加了这些孩子,如果添加了孩子,那么投掷会自行停止(实际上由于过度滚动而向后滚动一点),即使它还没到内容的底部。

我可以使用#fling(int velocity) 重新启动投掷,但我无法找到获取当前投掷速度或停止当前投掷的方法。有什么想法吗?

【问题讨论】:

  • 我建议像数组一样处理这个问题。在列表中放置您需要的两倍(或更多)元素。您现在没有的元素的后半部分是空的。如果添加一个元素,请不要添加它,而是用新数据填充下一个空元素。如果列表滚动进入最后一个被填充的元素,则停止投掷。这样,您将始终有一个持续的投掷。
  • @Foxichu,我也遇到了问题,请分享一些代码来解决这个问题。正如你提到的,你使用嵌套的滚动视图代码解决了这个问题。请分享。提前谢谢。

标签: android scrollview


【解决方案1】:

根据提示回答您的问题:

  • 没有 API 可以获取 ScrollView 的当前速度。
  • 您可以按照之前的SO post 中所述仔细处理触摸事件来停止当前的投掷。

查看ScrollView source code,它使用 OverScroller 来处理投掷事件。有两种方法可以解决这个问题:

  1. 使用反射访问 ScrollView 中的 mScroller 私有字段。访问它后,您可以通过其公共 API 获取当前速度:public float getCurrVelocity(); 使用反射从来都不是理想的,因为您必须担心它会破坏 Android 版本,但简单的隔离使用可能相对有效。
  2. 覆盖fling() method in ScrollView 并实例化一个OverScroller 以跟踪滚动。如果一切顺利,您的 Overscoller 将始终与 ScrollView 中的处于相同状态。

类似这样的:

@Override
public void fling(int velocityY)
{
    // Pass through fling to parent
    super.fling(velocityY);

    // Keep track of velocity using our own Overscoller instance
    mOurOverscroller = mScroller.fling(mScrollX, mScrollY, 0, velocityY, 0, 0, 0,
    Math.max(0, bottom - height), 0, height/2);
}

【讨论】:

  • 我最终采用的替代方法:从支持库中分叉 NestedScrollView 代码(即将其复制到新类)并根据需要进行编辑。
【解决方案2】:

我用@Override fling 方法解决了类似的问题。如果您在 ScrollViewNoFling 类上覆盖 fling 方法而不在此方法上调用 super.fling,那么您将无法处理 scrollView

@Override
public void fling (int velocity)
{
    /*Scroll view is no longer going to handle scroll velocity.
     * super.fling(velocity);
    */
}

【讨论】:

    最近更新 更多