Skip to content

Instantly share code, notes, and snippets.

@marteinn
Last active May 2, 2023 22:35
Show Gist options
  • Select an option

  • Save marteinn/9427072 to your computer and use it in GitHub Desktop.

Select an option

Save marteinn/9427072 to your computer and use it in GitHub Desktop.
ScrollView with a OnBottomReachedListener for Android. MIT license (https://opensource.org/licenses/MIT).
package se.marteinn.ui;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ScrollView;
/**
* Triggers a event when scrolling reaches bottom.
*
* Created by martinsandstrom on 2010-05-12.
* Updated by martinsandstrom on 2014-07-22.
*
* Usage:
*
* scrollView.setOnBottomReachedListener(
* new InteractiveScrollView.OnBottomReachedListener() {
* @Override
* public void onBottomReached() {
* // do something
* }
* }
* );
*
*
* Include in layout:
*
* <se.marteinn.ui.InteractiveScrollView
* android:layout_width="match_parent"
* android:layout_height="match_parent" />
*
*/
public class InteractiveScrollView extends ScrollView {
OnBottomReachedListener mListener;
public InteractiveScrollView(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
}
public InteractiveScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public InteractiveScrollView(Context context) {
super(context);
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
View view = (View) getChildAt(getChildCount()-1);
int diff = (view.getBottom()-(getHeight()+getScrollY()));
if (diff == 0 && mListener != null) {
mListener.onBottomReached();
}
super.onScrollChanged(l, t, oldl, oldt);
}
// Getters & Setters
public OnBottomReachedListener getOnBottomReachedListener() {
return mListener;
}
public void setOnBottomReachedListener(
OnBottomReachedListener onBottomReachedListener) {
mListener = onBottomReachedListener;
}
/**
* Event listener.
*/
public interface OnBottomReachedListener{
public void onBottomReached();
}
}
@mendhak

mendhak commented Apr 17, 2017

Copy link
Copy Markdown

@alcntml thanks for your snippet. I've posted a modified version of yours here, IMO the scroll up and down were switched. Also made the 'bottom' detection a tad bit forgiving 😁

@sbouiachref

Copy link
Copy Markdown

I encountered a problem. ie, Sometimes OnBottomReached is firing multiple times. Anyone has the same problem ???? Please help me to solve this

@sbouiachref

Copy link
Copy Markdown

I encountered a problem. ie, Sometimes OnBottomReached is firing multiple times. Anyone has the same problem ???? Please help me to solve this

@shuresnepali

shuresnepali commented Jul 24, 2017

Copy link
Copy Markdown

How do i use it/call it from main Activity...help me i am having trouble ???

@Croydon

Croydon commented Nov 16, 2017

Copy link
Copy Markdown

@marteinn Under which license do you publish this?

@marteinn

Copy link
Copy Markdown
Author

@Croydon MIT. Will clarify in the description.

@sevar83

sevar83 commented Feb 17, 2018

Copy link
Copy Markdown

One-liner in Kotlin:

fun ViewGroup.isScrolledToBottom() = getChildAt(childCount - 1).bottom - height - scrollY == 0

@wahyuade

wahyuade commented Mar 1, 2018

Copy link
Copy Markdown

good, it's work

@jemshit

jemshit commented Apr 25, 2018

Copy link
Copy Markdown

topReach is fired multiple times

@klaszlo8207

klaszlo8207 commented Jul 30, 2018

Copy link
Copy Markdown

fixed version

public class MyScrollView extends ScrollView {

OnBottomReachedListener mListener;

private boolean bottomreached = false;

public MyStickyScrollView(Context context, AttributeSet attrs,
                          int defStyle) {
    super(context, attrs, defStyle);
}

public MyStickyScrollView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public MyStickyScrollView(Context context) {
    super(context);
}

@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
    View view = getChildAt(getChildCount()-1);
    int diff = (view.getBottom()-(getHeight()+getScrollY()));

    if (diff == 0 && mListener != null && !bottomreached) {
        mListener.onBottomReached();
        bottomreached = true;
    }
    else {
        bottomreached = false;
    }

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

// Getters & Setters
public OnBottomReachedListener getOnBottomReachedListener() {
    return mListener;
}

public void setOnBottomReachedListener(
        OnBottomReachedListener onBottomReachedListener) {
    mListener = onBottomReachedListener;
}


/**
 * Event listener.
 */
public interface OnBottomReachedListener{
    void onBottomReached();
}

}
only fires 1 time

@mecoFarid

Copy link
Copy Markdown

diff ==0 is dangerous because it may never hit 0 as of various brand screen configurations. diff <= 0 is kinda useless because it's gonna trigger top/bottomReached multiple times.

@Wizard254

Copy link
Copy Markdown

So far, great thanks for your work, works just as expected.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment