Android:检测 ScrollView 何时停止滚动

Posted

技术标签:

【中文标题】Android:检测 ScrollView 何时停止滚动【英文标题】:Android: Detect when ScrollView stops scrolling 【发布时间】:2012-01-01 04:22:11 【问题描述】:

我在 android 中使用ScrollView,其中ScrollView 的可见部分与Scrollview 中的一个单元格大小相同。每个“单元格”的高度相同。所以我想要做的是在ScrollView 滚动后卡入位置。

目前我正在检测用户何时触摸ScrollView 以及他们何时开始滚动并从那里开始工作,但它有很多错误。当用户只是轻弹它并滚动然后减速时,它也需要工作。

在 iPhone 上,有一个类似于 didDecelerate 的函数,当 ScrollView 完成滚动时,我可以在那里执行任何我想要的代码。 Android有这样的事情吗?或者是否有一些我可以查看的代码来找出更好的方法?

我查看了 Android 文档,但找不到类似的内容。

【问题讨论】:

【参考方案1】:

这是一个旧线程,但我想添加一个我想出的更短的解决方案:

 buttonsScrollView.setOnScrollChangeListener  v, scrollX, scrollY, oldScrollX, oldScrollY ->

            handler.removeCallbacksAndMessages(null)

            handler.postDelayed(
                  //YOUR CODE TO BE EXECUTED HERE
                ,1000)
        

自然会有 1000 毫秒的延迟。如果需要,请进行调整。

【讨论】:

【参考方案2】:

我的解决方案是 Lin Yu Cheng 伟大解决方案的一个变体,并且还检测滚动何时开始和停止。

第一步:定义一个 Horizo​​ntalScrollView 和 OnScrollChangedListener:

CustomHorizontalScrollView scrollView = (CustomHorizontalScrollView) findViewById(R.id.horizontalScrollView);

horizontalScrollListener = new CustomHorizontalScrollView.OnScrollChangedListener() 
    @Override
    public void onScrollStart() 
        // Scrolling has started. Insert your code here...
    

    @Override
    public void onScrollEnd() 
         // Scrolling has stopped. Insert your code here...
    
;

scrollView.setOnScrollChangedListener(horizontalScrollListener);

步骤 2. 添加 CustomHorizo​​ntalScrollView 类:

public class CustomHorizontalScrollView extends HorizontalScrollView 
    public interface OnScrollChangedListener 
        // Developer must implement these methods.
        void onScrollStart();
        void onScrollEnd();
    

    private long lastScrollUpdate = -1;
    private int scrollTaskInterval = 100;
    private Runnable mScrollingRunnable;
    public OnScrollChangedListener mOnScrollListener;

    public CustomHorizontalScrollView(Context context) 
        this(context, null, 0);
        init(context);
    

    public CustomHorizontalScrollView(Context context, AttributeSet attrs) 
        this(context, attrs, 0);
        init(context);
    

    public CustomHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) 
        super(context, attrs, defStyle);
        init(context);
    

    private void init(Context context) 
        // Check for scrolling every scrollTaskInterval milliseconds
        mScrollingRunnable = new Runnable() 
            public void run() 
                if ((System.currentTimeMillis() - lastScrollUpdate) > scrollTaskInterval) 
                    // Scrolling has stopped.
                    lastScrollUpdate = -1;
                    //CustomHorizontalScrollView.this.onScrollEnd();
                    mOnScrollListener.onScrollEnd();
                 else 
                    // Still scrolling - Check again in scrollTaskInterval milliseconds...
                    postDelayed(this, scrollTaskInterval);
                
            
        ;
    

    public void setOnScrollChangedListener(OnScrollChangedListener onScrollChangedListener) 
        this.mOnScrollListener = onScrollChangedListener;
    

    public void setScrollTaskInterval(int scrollTaskInterval) 
        this.scrollTaskInterval = scrollTaskInterval;
    

    //void onScrollStart() 
    //    System.out.println("Scroll started...");
    //

    //void onScrollEnd() 
    //    System.out.println("Scroll ended...");
    //

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) 
        super.onScrollChanged(l, t, oldl, oldt);
        if (mOnScrollListener != null) 
            if (lastScrollUpdate == -1) 
                //CustomHorizontalScrollView.this.onScrollStart();
                mOnScrollListener.onScrollStart();
                postDelayed(mScrollingRunnable, scrollTaskInterval);
            

            lastScrollUpdate = System.currentTimeMillis();
        
    

【讨论】:

【参考方案3】:

这是另一个解决方案,在我看来非常简单和干净,自然受到上述答案的启发。基本上一旦用户结束手势检查 getScrollY() 是否仍在变化,经过短暂的延迟(这里是 50 毫秒)。

public class ScrollViewWithOnStopListener extends ScrollView 

    OnScrollStopListener listener;

    public interface OnScrollStopListener 
        void onScrollStopped(int y);
    

    public ScrollViewWithOnStopListener(Context context) 
        super(context);
    

    public ScrollViewWithOnStopListener(Context context, AttributeSet attrs) 
        super(context, attrs);
    

    @Override
    public boolean onTouchEvent(MotionEvent ev) 
        switch (ev.getAction()) 
            case MotionEvent.ACTION_UP:
                checkIfScrollStopped();
        

        return super.onTouchEvent(ev);
    

    int initialY = 0;

    private void checkIfScrollStopped() 
        initialY = getScrollY();
        this.postDelayed(new Runnable() 
            @Override
            public void run() 
                int updatedY = getScrollY();
                if (updatedY == initialY) 
                    //we've stopped
                    if (listener != null) 
                        listener.onScrollStopped(getScrollY());
                    
                 else 
                    initialY = updatedY;
                    checkIfScrollStopped();
                
            
        , 50);
    

    public void setOnScrollStoppedListener(OnScrollStopListener yListener) 
        listener = yListener;
    

【讨论】:

【参考方案4】:

我认为这在过去已经出现。 AFAIK,您无法轻松检测到这一点。我的建议是您查看ScrollView.java(这就是我们在Android 领域的工作方式:))并弄清楚如何扩展该类以提供您正在寻找的功能。这是我首先要尝试的:

 @Override
 protected void onScrollChanged(int l, int t, int oldl, int oldt) 
     if (mScroller.isFinished()) 
         // do something, for example call a listener
     
 

【讨论】:

很好,我没有注意到 isFinished 方法! 谢谢。如何访问这个 isFinished() 方法?我查看了 ScrollView.java 文件,并且 mScroller 是私有的,我无法确定可以访问它。 嗯,确实。我看的不够近。这就是为什么我说我会尝试first :)。您可以执行其他操作,例如跟踪对onScrollChangedscrollTo 或任何其他滚动相关方法的调用。或者,您可以复制整个 ScrollView 代码并将该字段设为 protected。不过,我不建议这样做。 通过反射访问了 mScroller。也不起作用,每次滚动视图到达您的手指位置时都会触发 isFinished(),这几乎是连续的。当用户松开手指并且滚动条停止滚动时,应该触发滚动停止事件。 这个答案看起来很有希望,但由于它有点死胡同,也许应该删除它?【参考方案5】:

这是我的解决方案,其中包括滚动跟踪和滚动结束:

public class ObservableHorizontalScrollView extends HorizontalScrollView 
    public interface OnScrollListener 
        public void onScrollChanged(ObservableHorizontalScrollView scrollView, int x, int y, int oldX, int oldY);
        public void onEndScroll(ObservableHorizontalScrollView scrollView);
    

    private boolean mIsScrolling;
    private boolean mIsTouching;
    private Runnable mScrollingRunnable;
    private OnScrollListener mOnScrollListener;

    public ObservableHorizontalScrollView(Context context) 
        this(context, null, 0);
    

    public ObservableHorizontalScrollView(Context context, AttributeSet attrs) 
        this(context, attrs, 0);
    

    public ObservableHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) 
        super(context, attrs, defStyle);
    

    @Override
    public boolean onTouchEvent(MotionEvent ev) 
        int action = ev.getAction();

        if (action == MotionEvent.ACTION_MOVE) 
            mIsTouching = true;
            mIsScrolling = true;
         else if (action == MotionEvent.ACTION_UP) 
            if (mIsTouching && !mIsScrolling) 
                if (mOnScrollListener != null) 
                    mOnScrollListener.onEndScroll(this);
                
            

            mIsTouching = false;
        

        return super.onTouchEvent(ev);
    

    @Override
    protected void onScrollChanged(int x, int y, int oldX, int oldY) 
        super.onScrollChanged(x, y, oldX, oldY);

        if (Math.abs(oldX - x) > 0) 
            if (mScrollingRunnable != null) 
                removeCallbacks(mScrollingRunnable);
            

            mScrollingRunnable = new Runnable() 
                public void run() 
                    if (mIsScrolling && !mIsTouching) 
                        if (mOnScrollListener != null) 
                            mOnScrollListener.onEndScroll(ObservableHorizontalScrollView.this);
                        
                    

                    mIsScrolling = false;
                    mScrollingRunnable = null;
                
            ;

            postDelayed(mScrollingRunnable, 200);
        

        if (mOnScrollListener != null) 
            mOnScrollListener.onScrollChanged(this, x, y, oldX, oldY);
        
    

    public OnScrollListener getOnScrollListener() 
        return mOnScrollListener;
    

    public void setOnScrollListener(OnScrollListener mOnEndScrollListener) 
        this.mOnScrollListener = mOnEndScrollListener;
    


【讨论】:

【参考方案6】:

我的方法是通过每次调用 onScrollChanged() 时更改的时间戳来确定滚动状态。 很容易确定滚动的开始和结束时间。 您还可以更改阈值(我使用 100 毫秒)来修复灵敏度。

public class CustomScrollView extends ScrollView 
    private long lastScrollUpdate = -1;

    private class ScrollStateHandler implements Runnable 

        @Override
        public void run() 
            long currentTime = System.currentTimeMillis();
            if ((currentTime - lastScrollUpdate) > 100) 
                lastScrollUpdate = -1;
                onScrollEnd();
             else 
                postDelayed(this, 100);
            
        
    

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) 
        super.onScrollChanged(l, t, oldl, oldt);
        if (lastScrollUpdate == -1) 
            onScrollStart();
            postDelayed(new ScrollStateHandler(), 100);
        

        lastScrollUpdate = System.currentTimeMillis();
    

    private void onScrollStart() 
        // do something
    

    private void onScrollEnd() 
        // do something
    


【讨论】:

很好的解决方案。按预期工作。 感谢您的代码。如何从您的代码中检测滚动启动侦听器方法。请看我的问题***.com/questions/27864700/…【参考方案7】:

这里有一些很好的答案,但是我的代码可以检测到滚动停止的时间,而无需扩展 ScrollView 类。 每个视图实例都可以调用 getViewTreeObserver()。当持有这个 ViewTreeObserver 实例时,您可以使用函数 addOnScrollChangedListener() 添加一个 OnScrollChangedListener。

声明如下:

private ScrollView scrollListener;
private volatile long milesec;

private Handler scrollStopDetector;
private Thread scrollcalled = new Thread() 

    @Override
    public void run()  
        if (System.currentTimeMillis() - milesec > 200) 
            //scroll stopped - put your code here
        
    
; 

并在您的 onCreate(或其他地方)添加:

    scrollListener = (ScrollView) findViewById(R.id.scroll);

    scrollListener.getViewTreeObserver().addOnScrollChangedListener(new OnScrollChangedListener() 

        @Override
        public void onScrollChanged() 
            milesec = System.currentTimeMillis();
            scrollStopDetector.postDelayed(scrollcalled, 200);
        
    );

您可能希望在两次检查之间花费更长或更慢的时间,但是当滚动此侦听器时,调用速度非常快,因此它的工作速度非常快。

【讨论】:

我没有尝试过这种情况,但根据我的经验,我猜想从 onScrollChanged 对 postDelayed 的重复和相互调用会导致内存泄漏。【参考方案8】:

我对 ZeroG 的回答做了一些改进。主要是取消多余的任务调用,并将整个事情实现为一个私有的 OnTouchListener,所以所有的滚动检测代码都在一个地方。

将以下代码粘贴到您自己的 ScrollView 实现中:

private class ScrollFinishHandler implements OnTouchListener

        private static final int SCROLL_TASK_INTERVAL = 100;

        private Runnable    mScrollerTask;
        private int         mInitialPosition = 0;

        public ScrollFinishHandler()
        
            mScrollerTask = new Runnable() 

                public void run() 

                    int newPosition = getScrollY();
                    if(mInitialPosition - newPosition == 0)
                    //has stopped

                       onScrollStopped(); // Implement this on your main ScrollView class
                    else
                        mInitialPosition = getScrollY();
                        ExpandingLinearLayout.this.postDelayed(mScrollerTask, SCROLL_TASK_INTERVAL);
                    
                
            ;
        

        @Override
        public boolean onTouch(View v, MotionEvent event) 
        
            if (event.getAction() == MotionEvent.ACTION_UP) 
            

                startScrollerTask();
            
            else
            
                stopScrollerTask();
            

            return false;
        


然后在你的 ScrollView 实现中:

setOnTouchListener( new ScrollFinishHandler() );

【讨论】:

【参考方案9】:

这是另一个修复,恕我直言,ScrollView 中缺少 OnEndScroll 事件错误。

它的灵感来自hambonious 答案。 只需将此类放入您的项目中(更改包以匹配您自己的)并使用以下 xml

package com.thecrag.components.ui;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.ScrollView;

public class ResponsiveScrollView extends ScrollView 

    public interface OnEndScrollListener 
        public void onEndScroll();
    

    private boolean mIsFling;
    private OnEndScrollListener mOnEndScrollListener;

    public ResponsiveScrollView(Context context) 
        this(context, null, 0);
    

    public ResponsiveScrollView(Context context, AttributeSet attrs) 
        this(context, attrs, 0);
    

    public ResponsiveScrollView(Context context, AttributeSet attrs, int defStyle) 
        super(context, attrs, defStyle);
    

    @Override
    public void fling(int velocityY) 
        super.fling(velocityY);
        mIsFling = true;
    

    @Override
    protected void onScrollChanged(int x, int y, int oldX, int oldY) 
        super.onScrollChanged(x, y, oldX, oldY);
        if (mIsFling) 
            if (Math.abs(y - oldY) < 2 || y >= getMeasuredHeight() || y == 0) 
                if (mOnEndScrollListener != null) 
                    mOnEndScrollListener.onEndScroll();
                
                mIsFling = false;
            
        
    

    public OnEndScrollListener getOnEndScrollListener() 
        return mOnEndScrollListener;
    

    public void setOnEndScrollListener(OnEndScrollListener mOnEndScrollListener) 
        this.mOnEndScrollListener = mOnEndScrollListener;
    


再次更改包名称以匹配您的项目

<com.thecrag.components.ui.ResponsiveScrollView
        android:id="@+id/welcome_scroller"
        android:layout_
        android:layout_
        android:layout_above="@+id/welcome_scroll_command_help_container"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:layout_below="@+id/welcome_header_text_thecrag"
        android:layout_margin="6dp">
    ....
</com.thecrag.components.ui.ResponsiveScrollView>

【讨论】:

+1 不错,简单的答案。我将差值 2 更改为 0.5f 以反映原始 ScrollViewMAX_SCROLL_FACTOR 值。 这个实现很好,但是当滚动视图在开始时没有填充时它失败了。这是一种解决方法(对于水平滚动视图,因此将所有 x 替换为 y 以获得垂直滚动视图):@Override protected void onScrollChanged(int x, int y, int oldX, int oldY) super.onScrollChanged(x, y , 旧X, 旧Y); if (Math.abs(x - oldX) = getMeasuredWidth() || x == 0) lastStopX = x; if (mOnEndScrollListener != null) mOnEndScrollListener.onScrollEnded(); 这并不总是有效。与模拟器一样,并不总是调用 public void fling(int velocityY) 。滚动结束阈值有时超过 20 像素。【参考方案10】:

我对这个问题的方法是使用计时器来检查以下 2 个“事件”。

1) onScrollChanged() 停止被调用

2) 用户的手指从滚动视图中抬起

public class CustomScrollView extends HorizontalScrollView 

public CustomScrollView(Context context, AttributeSet attrs) 
    super(context, attrs);


Timer ntimer = new Timer();
MotionEvent event;

@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) 

    checkAgain();
    super.onScrollChanged(l, t, oldl, oldt);


public void checkAgain()
    try
        ntimer.cancel();
        ntimer.purge();
    
    catch(Exception e)
    ntimer = new Timer();
    ntimer.schedule(new TimerTask() 

        @Override
        public void run() 

            if(event.getAction() == MotionEvent.ACTION_UP)
                // ScrollView Stopped Scrolling and Finger is not on the ScrollView
            
            else
                // ScrollView Stopped Scrolling But Finger is still on the ScrollView
                checkAgain();
            
        
    ,100);



@Override
public boolean onTouchEvent(MotionEvent event) 
    this.event = event; 
    return super.onTouchEvent(event);
    

【讨论】:

【参考方案11】:

我最近不得不实现您描述的功能。我所做的是通过比较第一次触发 onTouchEvent 时 getScrollY() 返回的值与变量 newCheck 定义的时间后返回的值来检查 ScrollView 是否停止滚动.

参见下面的代码(工作解决方案):

public class MyScrollView extends ScrollView

private Runnable scrollerTask;
private int initialPosition;

private int newCheck = 100;
private static final String TAG = "MyScrollView";

public interface OnScrollStoppedListener
    void onScrollStopped();


private OnScrollStoppedListener onScrollStoppedListener;

public MyScrollView(Context context, AttributeSet attrs) 
    super(context, attrs);

    scrollerTask = new Runnable() 

        public void run() 

            int newPosition = getScrollY();
            if(initialPosition - newPosition == 0)//has stopped

                if(onScrollStoppedListener!=null)

                    onScrollStoppedListener.onScrollStopped();
                
            else
                initialPosition = getScrollY();
                MyScrollView.this.postDelayed(scrollerTask, newCheck);
            
        
    ;


public void setOnScrollStoppedListener(MyScrollView.OnScrollStoppedListener listener)
    onScrollStoppedListener = listener;


public void startScrollerTask()

    initialPosition = getScrollY();
    MyScrollView.this.postDelayed(scrollerTask, newCheck);



然后我有:

scroll.setOnTouchListener(new OnTouchListener() 

        public boolean onTouch(View v, MotionEvent event) 

            if (event.getAction() == MotionEvent.ACTION_UP) 

                scroll.startScrollerTask();
            

            return false;
        
);
scroll.setOnScrollStoppedListener(new OnScrollStoppedListener() 

        public void onScrollStopped() 

            Log.i(TAG, "stopped");

        
);

顺便说一句,我在我的应用程序中使用了其他回复中的一些想法来执行此操作。 希望这可以帮助。有任何问题请随时询问我(们)。 干杯。

【讨论】:

谢谢,一直在寻找类似的东西。用于 Horizo​​ntalScrollView 代替,它(显然)也有效。只有 getScrollY() 必须替换为 getScrollX() 在这里都试过了。这是唯一有效的。 即使单击滚动视图,它也会显示“已停止”。它应该只适用于用户滚动滚动视图。那我们需要做什么呢? 当你触摸屏幕时它会调用 onScrollStopped()。如果您向下滚动,则立即向上滚动 onScrollStopped() 方法将调用.. 如果您连续向上滚动和向下滚动,它将一直调用 onScrollStopped()。【参考方案12】:

我将 (Horizo​​ntal)ScrollView 子类化并做了这样的事情:

@Override
protected void onScrollChanged(int x, int y, int oldX, int oldY) 
    if (Math.abs(x - oldX) > SlowDownThreshold)   
        currentlyScrolling = true;
     else 
        currentlyScrolling = false;
        if (!currentlyTouching) 
            //scrolling stopped...handle here
        
    
    super.onScrollChanged(x, y, oldX, oldY);

我为 SlowDownThreshold 使用了 1 的值,因为它似乎总是与最后一个 onScrollChanged 事件的差异。

为了在缓慢拖动时使其行为正确,我必须这样做:

@Override
public boolean onInterceptTouchEvent(MotionEvent event) 
    switch (event.getAction()) 
        case MotionEvent.ACTION_DOWN:
            currentlyTouching = true;
    
    return super.onInterceptTouchEvent(event);


@Override
public boolean onTouch(View view, MotionEvent event) 
    switch (event.getAction()) 
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:
            currentlyTouching = false;
            if (!currentlyScrolling) 
                //I handle the release from a drag here
                return true;
            
    
    return false;

【讨论】:

不错的答案。唯一的一个补充。在 onInterceptTouchEvent() 中,您还处理 MotionEvent.ACTION_UP 和 MotionEvent.ACTION_CANCEL 否则 currentTouching 将保持为真,以防您在点击时打开另一个活动。 另一个修复:在 onScrollChanged() 中,即使减速尚未达到 1,您也必须检查滚动结束。像这样: boolean end = (oldx > x) ? (x = getMaxScrollAmount()); if (Math.abs(x - oldx) > 1 && !end) 滚动开始; else 滚动结束 这在某些设备上不起作用,例如 GS3。在我的 GS3 上,y 和旧 y 之间的差异可以在滚动中间为 1。它在我的 Nexus 4 上完美运行。我不知道为什么。 在三星 Galaxy Note 2 和华硕 Memo Pad 7 上也无法使用。我还在这些设备上的滚动中间看到了 1 的增量。【参考方案13】:

对于您描述的简单案例,您可能可以在自定义滚动视图中使用覆盖 fling 方法。每次用户从屏幕上抬起手指时,都会调用 Fling 方法来执行“减速”。

所以你应该做的是这样的:

    子类 ScrollView。

    public class MyScrollView extends ScrollView  
    
        private Scroller scroller;  
        private Runnable scrollerTask; 
    
        //...
    
        public MyScrollView(Context context, AttributeSet attrs) 
            super(context, attrs);
    
            scroller = new Scroller(getContext()); //or OverScroller for 3.0+
            scrollerTask = new Runnable() 
                @Override
                public void run() 
                    scroller.computeScrollOffset();
                    scrollTo(0, scroller.getCurrY());
    
                    if (!scroller.isFinished()) 
                        MyScrollView.this.post(this);
                     else 
                        //deceleration ends here, do your code
                    
                
            ;
            //...
        
    
    

    子类 fling 方法,不要调用超类实现。

    @Override  
    public void fling(int velocityY)   
        scroller.fling(getScrollX(), getScrollY(), 0, velocityY, 0, 0, 0, container.getHeight());
        post(scrollerTask);  
    
        //add any extra functions you need from android source code:
        //show scroll bars
        //change focus
        //etc.
    
    

    如果用户在抬起手指之前停止滚动(velocityY == 0),则不会触发 Fling。如果您还想拦截此类事件,请覆盖 onTouchEvent。

    @Override
    public boolean onTouchEvent(MotionEvent ev) 
        boolean eventConsumed = super.onTouchEvent(ev);
        if (eventConsumed && ev.getAction() == MotionEvent.ACTION_UP) 
            if (scroller.isFinished()) 
                //do your code
            
        
        return eventConsumed;
    
    

注意虽然这可行,但覆盖 fling 方法可能不是一个好主意。它是公开的,但几乎没有为子类化而设计。现在它做了 3 件事——它为私有 mScroller 启动投掷,处理可能的焦点变化并显示滚动条。这可能会在未来的 android 版本中改变。例如,私有 mScroller 实例在 2.3 和 3.0 之间将其类从 Scroller 更改为 OvershootScroller。你必须记住所有这些小差异。无论如何,为未来不可预见的后果做好准备。

【讨论】:

第二步 (2.) 中的 container.getHeight() 是什么? container 是 scrollView 内部的视图。由于 scrollView 只能包含 1 个孩子,您可以将容器替换为 getChildAt(0)。【参考方案14】:
        this.getListView().setOnScrollListener(new OnScrollListener()
        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) 

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem,
            int visibleItemCount, int totalItemCount) 
                     if( firstVisibleItem + visibleItemCount >= totalItemCount ) 
                              // Last item is shown...

            

希望sn-p帮助:)

【讨论】:

不幸的是,我使用的是 ScrollView,而不是 ListView。不过还是谢谢。 喂? ScrollView 不是 ListView。【参考方案15】:

尝试在 *** 上查看 this question - 它与您的问题不完全相同,但它提供了一个关于如何管理 ScrollView 的滚动事件的想法。

基本上,您需要通过扩展ScrollView 并覆盖onScrollChanged(int x, int y, int oldx, int oldy) 来创建自己的CustomScrollView。然后你需要在你的布局文件中引用它而不是像com.mypackage.CustomScrollView这样的标准ScrollView

【讨论】:

这个 onScrollChanged() 实际上是我现在正在使用的。不过还是谢谢。

以上是关于Android:检测 ScrollView 何时停止滚动的主要内容,如果未能解决你的问题,请参考以下文章

检测 ScrollView 的结束

iOS Scrollview 检测滚动

如何检测 UITableView 标题何时滚动?

android-基础编程-ScrollView

如何检测滚动嵌套scrollview android在底部的位置?

检测UIScrollview底部到达