Android: обнаружение прекращения прокрутки ScrollView

87

Я использую ScrollViewв Android, и где видимая часть ScrollViewимеет тот же размер, что и одна из ячеек внутри Scrollview. Каждая «ячейка» одинаковой высоты. Итак, что я пытаюсь сделать, это зафиксировать положение после ScrollViewпрокрутки.

В настоящее время я обнаруживаю, когда пользователь коснулся ScrollViewи когда они начали прокрутку и отработать это оттуда, но это довольно глючно. Он также должен работать, когда пользователь просто щелкает по нему, и он прокручивается, а затем замедляется.

На iPhone есть что-то вроде функции, didDecelerateи там я могу выполнить любой код, который захочу, когда ScrollViewпрокрутка закончится. Есть такое с Андроидом? Или есть какой-то код, на который я мог бы взглянуть, чтобы найти лучший способ сделать это?

Я просмотрел документы Android и не нашел ничего подобного.

user1053691
источник

Ответы:

102

Недавно мне пришлось реализовать описанную вами функцию. Что я сделал, так это чтобы Runnable проверял, прекратил ли ScrollView прокрутку, сравнивая значение, возвращаемое getScrollY (), когда onTouchEvent впервые запускается со значением, возвращаемым через время, определенное переменной newCheck .

См. Код ниже (рабочее решение):

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

        }
});

Кстати, я использовал несколько идей из других ответов, чтобы сделать это в своем приложении. Надеюсь это поможет. Любые вопросы, не стесняйтесь спрашивать. Ура.

tulio84z
источник
11
Спасибо, давно искал что-то подобное. Вместо этого используется для HorizontalScrollView, который (очевидно) тоже работает. Только getScrollY () нужно заменить на getScrollX ()
Schnodahipfe
2
Пробовал их все здесь. Это ЕДИНСТВЕННЫЙ, который работает.
Mike6679
23

Вот еще одно исправление, IMHO, ошибки события OnEndScroll в ScrollView.

Его вдохновил достойный ответ. Просто поместите этот класс в свой проект (измените пакет, чтобы он соответствовал вашему собственному) и используйте приведенный ниже 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 Хороший, простой ответ. Изменить значение разности , 2чтобы 0.5fотразить оригинальный ScrollView«s MAX_SCROLL_FACTORзначение.
Фил
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; если (mOnEndScrollListener! = ноль) {mOnEndScrollListener.onScrollEnded (); }}}
Snicolas
Это не всегда работает. Как и в эмуляторе, не всегда вызывается public void fling (int velocityY). Порог конца прокрутки иногда превышает 20 пикселей.
Эндрю Фенг
9

Я создал подкласс (Horizontal) 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);
}

Я использовал значение 1 для SlowDownThreshold, так как он всегда кажется разницей последнего события 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)? (х <= 0): (х> = getMaxScrollAmount ()); if (Math.abs (x - oldx)> 1 &&! end) {начало прокрутки; } else {scroll end}
Циничный Бандера
Это не работает на некоторых устройствах, например, GS3. На моем GS3 разница между y и старым y МОЖЕТ быть 1 в середине прокрутки. Но на моем Nexus 4 он работает отлично. Не знаю почему.
Bryan
Не работает и на Samsung Galaxy Note 2, и на Asus Memo Pad 7. Я также вижу приращение 1 в середине прокрутки на этих устройствах.
Оливер Хауслер
7

Мой подход заключается в определении состояния прокрутки по временной метке, изменяемой каждый раз при вызове 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
    }

}
Лин Ю Ченг
источник
Отличное решение. Работает как положено.
Оливер Хауслер
Спасибо за ваш код. Как определить метод прослушивания начала прокрутки из вашего кода. пожалуйста, посмотрите мой вопрос stackoverflow.com/questions/27864700/…
MAMurali 09
7

Вот еще одно решение, на мой взгляд, довольно простое и чистое, естественно вдохновленное ответами выше. Обычно после того, как пользователь завершил проверку жестов, после небольшой задержки (здесь 50 мсек) 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);
    }
}
ZeroG
источник
3

В таком простом случае, как вы описали, вы, вероятно, сможете обойтись без переопределения метода fling в своем настраиваемом режиме прокрутки. Метод Fling вызывается для выполнения «замедления» каждый раз, когда пользователь поднимает палец от экрана.

Итак, что вам следует сделать, это примерно так:

  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. Subclass 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.
    }
    
  3. Fling не сработает, если пользователь прекратит прокрутку до того, как поднял палец (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 изменил свой класс с Scroller на OvershootScroller между 2.3 и 3.0. Вы должны иметь в виду все эти небольшие отличия. В любом случае будьте готовы к непредвиденным последствиям в будущем.

Алексей
источник
Что такое container.getHeight () на втором шаге (2.)?
Mitul Varmora
1
контейнер - это представление, которое находится внутри scrollView. Поскольку scrollView может содержать только 1 дочерний элемент, вы можете заменить контейнер на getChildAt (0).
Алексей
3

Мое решение - это вариант отличного решения Лин Ю Ченг, которое также определяет, когда прокрутка началась и остановилась.

Шаг 1. Определите HorizontalScrollView и 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. Добавьте класс CustomHorizontalScrollView:

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
2

Здесь есть отличные ответы, но мой код может определять, когда прокрутка останавливается, без необходимости расширения класса ScrollView. каждый экземпляр представления может вызывать getViewTreeObserver (). удерживая этот экземпляр ViewTreeObserver, вы можете добавить OnScrollChangedListener с помощью функции addOnScrollChangedListener ().

заявляем следующее:

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

вам может потребоваться больше или меньше времени между этими проверками, но при прокрутке этот список вызывается очень быстро, поэтому он будет работать очень быстро.

Збун
источник
Я не пробовал в этом случае, но по своему опыту могу предположить, что повторяющийся и ответный вызов postDelayed из onScrollChanged вызовет утечку памяти.
Оливер Хауслер
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
3
Благодарю. Как мне получить доступ к этому методу isFinished ()? Я взглянул на файл ScrollView.java, mScroller является частным, и я не могу сказать, как получить к нему доступ.
user1053691
Хм, действительно. Я не смотрел достаточно близко. Вот почему я сказал, что сначала попробую :). Вы можете делать другие вещи, как отслеживать звонки onScrollChanged, scrollToили любой другой способ прокрутки связанной. В качестве альтернативы вы можете просто скопировать весь ScrollViewкод и создать это поле protected. Хотя я бы не рекомендовал это.
Феликс
1
Доступ к mScroller через отражение. Не работает, isFinished () срабатывает каждый раз, когда scrollview достигает положения вашего пальца, что происходит почти постоянно. Событие остановки прокрутки должно срабатывать, когда оба пользователя отпускают палец, а скроллер перестает прокручивать.
amik
20
Этот ответ выглядел действительно многообещающим, но, поскольку он как бы тупиковый, может быть, его следует удалить?
spaaarky21,
2

это старый поток, но я хотел бы добавить более короткое решение, которое я придумал:

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

            handler.removeCallbacksAndMessages(null)

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

Естественно есть задержка в 1000 миллисекунд. Отрегулируйте это, если вам нужно.

пепинобр
источник
1

Я внес некоторые улучшения в ответ 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() );
Вайден
источник
-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...

            }

Надеюсь, что фрагмент поможет :)

Хорди Косколла
источник
К сожалению, я использую ScrollView, а не ListView. Спасибо хоть.
user1053691
1
Здравствуйте? ScrollView, а не ListView.
Кевин Паркер