Android:ScrollViewがスクロールを停止したことを検出する


84

私はScrollViewAndroidでを使用しており、の表示部分はScrollView内のセルの1つと同じサイズScrollviewです。すべての「セル」は同じ高さです。だから私がやろうとしScrollViewているのは、スクロールした後に所定の位置にスナップすることです。

現在、ユーザーがに触れたScrollViewときと、そこからスクロールして作業を開始したときを検出していますが、かなりバグがあります。また、ユーザーがフリックするだけで、スクロールしてから減速するときにも機能する必要があります。

iPhoneには次のような機能があり、スクロールが終了したら好きなdidDecelerateコードを実行できますScrollView。Androidでそんなことはありますか?それとも、それを行うためのより良い方法を見つけるために私が見ることができるいくつかのコードがありますか?

Androidのドキュメントを調べましたが、そのようなものは見つかりませんでした。

回答:


101

最近、あなたが説明した機能を実装する必要がありました。私がしたことは、onTouchEventが最初にトリガーされたときにgetScrollY()によって返された値を、変数newCheckによって定義された時間の後に返された値と比較することによって、ScrollViewがスクロールを停止したかどうかをRunnableにチェックさせることでした

以下のコードを参照してください(実用的なソリューション):

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");

        }
});

ところで、私は自分のアプリでこれを行うために他の返信からのいくつかのアイデアを使用しました。お役に立てれば。ご不明な点はお気軽にお問い合わせください。乾杯。


11
おかげで、このようなものの年齢を探していました。代わりにHorizo​​ntalScrollViewに使用されます。これは(明らかに)同様に機能します。getScrollY()のみをgetScrollX()に置き換える必要があります
Schnodahipfe 2012

1
ここですべて試してみました。これが機能する唯一のものです。
Mike66 7918年

23

ScrollViewにOnEndScrollイベントのバグがないIMHOのさらに別の修正があります。

その恥ずべき答えに触発されました。このクラスをプロジェクトにドロップし(パッケージを自分のクラスに一致するように変更)、以下の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_width="wrap_content"
        android:layout_height="wrap_content"
        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>

2
+1素晴らしく、簡単な答え。私は、差分値を変更20.5f、元反映するために、ScrollViews「のMAX_SCROLL_FACTOR値を。
Phil

2
この実装は素晴らしいですが、開始時にスクロールビューがいっぱいにならない場合は失敗しました。回避策は次のとおりです(水平スクロールビューの場合、すべてのxをyに置き換えて垂直スクロールビューを取得します):@ Override protected void onScrollChanged(int x、int y、int oldX、int oldY){super.onScrollChanged(x、y 、oldX、oldY); if(Math.abs(x --oldX)<SCROLL_FINISHED_THRESHOLD && x!= lastStopX || x> = getMeasuredWidth()|| x == 0){lastStopX = x; if(mOnEndScrollListener!= null){mOnEndScrollListener.onScrollEnded(); }}}
Snicolas 2013

これは常に機能するとは限りません。エミュレーターと同様に、public void fling(intvelocityY)が常に呼び出されるとは限りません。スクロール終了のしきい値が20ピクセルを超える場合があります。
Andrew Feng

9

(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には常に最後のonScrollChangedイベントの違いのように見えるため、値1を使用しました。

ゆっくりドラッグしたときにこれが正しく動作するようにするには、次のことを行う必要がありました。

@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も処理します。それ以外の場合、クリックで別のアクティビティを開いた場合、currentlyTouchingはtrueのままになります。
Cynichniy Bandera 2013

もう1つの修正:onScrollChanged()では、スローダウンがまだ1でない場合でも、スクロールの終了を確認する必要があります。次のように:boolean end =(oldx> x)?(x <= 0):( x> = getMaxScrollAmount()); if(Math.abs(x --oldx)> 1 &&!end){スクロール開始; } else {スクロール終了}
Cynichniy Bandera 2013

これは、一部のデバイス、つまりGS3では機能しません。私のGS3では、スクロールの途中でyと古いyの差分を1にすることができます。それでも私のNexus4では完全に機能します。理由はわかりません。
ブライアン

Samsung Galaxy Note2とAsusMemo Pad7でも動作しません。また、これらのデバイスのスクロールの中央に1の増分が表示されます。
オリバーハウスラー2014年

7

私のアプローチは、onScrollChanged()が呼び出されるたびに変更されるタイムスタンプによってスクロール状態を判別することです。スクロールの開始と終了を判断するのは非常に簡単です。感度を修正するためにしきい値を変更することもできます(私は100msを使用します)。

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
    }

}

素晴らしいソリューション。想定どおりに動作します。
オリバーハウスラー2014年

コードをありがとう。コードからスクロールスタートリスナーメソッドを検出する方法。私の質問を見てくださいstackoverflow.com/questions/27864700/...
MAMurali

6

上記の回答に自然に触発された、私の意見では非常にシンプルでクリーンな、さらに別の解決策があります。基本的に、ユーザーがジェスチャを終了したら、少し遅れて(ここでは50ms)、getScrollY()がまだ変更されているかどうかを確認します。

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;
    }
}

5

この質問に対する私のアプローチは、タイマーを使用して次の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);
    }
}

3

私の解決策は、Lin Yu Chengの優れた解決策のバリエーションであり、スクロールがいつ開始および停止したかを検出します。

手順1.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();
        }
    }
}

2

StackOverflowでこの質問を見てみてください-これはあなたの質問とまったく同じではありませんが、のスクロールイベントを管理する方法についてのアイデアを提供しますScrollView

基本的にCustomScrollView、を拡張ScrollViewしてオーバーライドすることにより、独自のものを作成する必要がありますonScrollChanged(int x, int y, int oldx, int oldy)。次に、のScrollViewような標準ではなく、レイアウトファイルでこれを参照する必要がありますcom.mypackage.CustomScrollView


このonScrollChanged()は、実際に私がその瞬間に使用しているものです。でもありがとう。
user1053691 2011年

2

あなたが説明したような単純なケースでは、カスタムスクロールビューでフリングメソッドをオーバーライドすることでおそらく逃げることができます。ユーザーが画面から指を上げるたびに、フリングメソッドが呼び出されて「減速」が実行されます。

したがって、あなたがすべきことは次のようなものです:

  1. 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
                    }
                }
            };
            //...
        }
    }
    
  2. サブクラスのフリングメソッドであり、スーパークラスの実装を呼び出さないでください。

    @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.
    }
    
  3. ユーザーが指を上げる前にスクロールを停止した場合(velocityY == 0)、フリングはトリガーされません。この種のイベントもインターセプトする場合は、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;
    }
    

これは機能しますが、フリングメソッドをオーバーライドすることは悪い考えかもしれません。公開されていますが、サブクラス化のためにほとんど設計されていません。現在、3つのことを実行します。プライベートmScrollerのフリングを開始し、可能なフォーカス変更を処理し、スクロールバーを表示します。これは、将来のAndroidリリースで変更される可能性があります。たとえば、プライベートmScrollerインスタンスは、2.3から3.0の間で、クラスをScrollerからOvershootScrollerに変更しました。この小さな違いをすべて覚えておく必要があります。いずれにせよ、将来の予期せぬ結果に備えてください。


2番目のステップ(2.)のcontainer.getHeight()とは何ですか?
Mitul Varmora 2016年

1
コンテナは、scrollView内にあるビューです。scrollViewには子を1つしか含めることができないため、コンテナーをgetChildAt(0)に置き換えることができます。
Alexey 2016年

2

ここにはいくつかのすばらしい答えがありますが、私のコードでは、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を繰り返して相互に呼び出すと、メモリリークが発生すると思います。
オリバーハウスラー2014年

2

スクロールトラッキングとスクロールエンディングを含む私のソリューションは次のとおりです。

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;
    }

}

2

これは過去に起こったと思います。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メソッドに気づかなかったのはいいですね!
Jordi Coscolla 2011年

3
ありがとう。このisFinished()メソッドにアクセスするにはどうすればよいですか?ScrollView.javaファイルを調べましたが、mScrollerはプライベートであり、アクセスする方法がわかりません。
user1053691 2011年

うーん、確かに。私は十分に近くに見えませんでした。だから私は最初にそれを試すと言ったのです:)。、、またはその他のスクロール関連のメソッドへの呼び出しを追跡するonScrollChangedなどscrollTo、他のことを行うことができます。または、ScrollViewコード全体をコピーしてそのフィールドを作成することもできますprotected。しかし、私はそれをお勧めしません。
フェリックス

1
リフレクションを介してmScrollerにアクセスしました。isFinished()も機能しません。スクロールビューが指の位置に到達するたびに、isFinished()がトリガーされます。これは、ほぼ継続的に行われます。両方のユーザーが指を離し、スクローラーがスクロールを停止すると、スクロール停止イベントが発生します。
amik 2013年

20
この答えは本当に有望に見えましたが、それは一種の行き止まりなので、おそらく削除する必要がありますか?
spaaarky21 2013

2

これは古いスレッドですが、私が思いついたより短いソリューションを追加したいと思います。

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

            handler.removeCallbacksAndMessages(null)

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

当然、1000ミリ秒の遅延があります。必要に応じて調整してください。


1

ZeroGの回答にいくつかの改善を加えました。主に過剰なタスク呼び出しをキャンセルし、すべてをプライベートOnTouchListenerとして実装するため、すべてのスクロール検出コードが1か所にまとめられます。

次のコードを独自の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() );

-1
        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...

            }

スニペットがお役に立てば幸いです:)


残念ながら、私はListViewではなくScrollViewを使用しています。でもありがとう。
user1053691 2011年

1
こんにちは?ListViewではなくScrollView。
ケビンパーカー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.