Android: виявлення, коли ScrollView припиняє прокрутку


84

Я використовую операційну систему ScrollViewAndroid, і там, де видима частина ScrollViewмає такий самий розмір, як одна з комірок всередині Scrollview. Кожна "клітина" однакової висоти. Отже, я намагаюся закріпити позицію після ScrollViewпрокрутки.

В даний час я виявляю, коли користувач торкнувся ScrollViewі коли він почав прокручувати та розробляти його звідти, але це досить глючить. Він також повинен працювати, коли користувач просто натискає його, і він прокручується, а потім сповільнюється.

На iPhone є функція, яка нагадує, didDecelerateі там я можу робити будь-який код, який мені потрібно, коли ScrollViewзакінчується прокрутка. Чи є така річ з Android? Або є якийсь код, який я міг би переглянути, щоб з’ясувати кращий спосіб зробити це?

Я переглянув документи Android і не зміг знайти нічого подібного.

Відповіді:


101

Нещодавно мені довелося реалізувати функцію, яку ви описали. Що я зробив, це мав 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");

        }
});

До речі, я використав кілька ідей з інших відповідей, щоб зробити це у своєму додатку. Сподіваюся, це допомагає. Будь-які питання сміливо задавайте. Ура.


11
Дякую, шукали віками щось подібне. Замість цього використовується в для HorizontalScrollView, що (очевидно) також працює. Тільки getScrollY () повинен бути замінений на getScrollX ()
Schnodahipfe

1
Спробував їх усіх тут. Це ЄДИНИЙ, який працює.
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; if (mOnEndScrollListener! = null) {mOnEndScrollListener.onScrollEnded (); }}}
Сніколас

Це не завжди працює. Як і в емуляторі, не завжди викликається публічне переміщення порожнеч (int velocityY). Поріг кінця прокрутки іноді перевищує 20 пікселів.
Ендрю Фенг,

9

Я підкласував (горизонтальний) 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, інакше в даний час Touching залишатиметься істинним, якщо ви відкриєте іншу активність за кліком.
Цинічний Бандера

Ще одне виправлення: у onScrollChanged () вам також потрібно перевірити кінець прокрутки, навіть якщо уповільнення ще не 1. Ось так: логічний кінець = (oldx> x)? (x <= 0): (x> = getMaxScrollAmount ()); if (Math.abs (x - oldx)> 1 &&! end) {прокрутка початку; } else {закінчення прокрутки}
Cynichniy Bandera

Це не працює на деяких пристроях, тобто GS3. На моєму GS3 різниця між y та старим y МОЖЕ бути 1 протягом середини прокрутки. Хоча це чудово працює на моєму Nexus 4. Я не впевнений чому.
Bryan

Не працює на Samsung Galaxy Note 2 і Asus Memo Pad 7. Я також бачу збільшення на 1 в середині прокрутки на цих пристроях.
Oliver Hausler

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
    }

}

Чудове рішення. Працює як слід.
Oliver

Дякуємо за ваш код. Як виявити метод прослуховування запуску прокрутки з вашого коду. будь ласка , дивіться моє запитання stackoverflow.com/questions/27864700 / ...
MAMurali

6

Ось ще одне рішення, на мій погляд, досить просте і чисте, природно натхнене наведеними вище відповідями. В основному, після закінчення жестом користувача перевірте, чи все ще змінюється 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;
    }
}

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

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

Крок 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

У такому простому випадку, як ви описали, ви, мабуть, зможете уникнути переважного методу перекидання у своєму користувацькому режимі прокрутки. Метод 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. Метод перекладу підкласу та НЕ викликайте реалізацію суперкласу.

    @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. Перекидання не спрацьовує, якщо користувач припинить прокрутку перед підняттям пальця (швидкістьY == 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.)?
Мітул Вармора

1
контейнер - це вид, який знаходиться всередині scrollView. Оскільки scrollView може містити лише 1 дочірню організацію, ви можете замінити контейнер на getChildAt (0).
Олексій

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 land :)) і з’ясувати, як можна розширити клас, щоб забезпечити функціональність, яку ви шукаєте. Це те, що я спробував би спочатку:

 @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 () запускається щоразу, коли прокрутка досягає положення вашого пальця, що майже безперервно. Подія зупинки прокрутки має спрацьовувати, коли обидва користувачі відпускають палець, а скролер зупиняє прокрутку.
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.
Кевін Паркер,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.