-
-
Save marteinn/9427072 to your computer and use it in GitHub Desktop.
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(); | |
} | |
} |
Hi Marteein
- if (mListener != null) should contain all the code but the super;
- diff check, should be <= 0;
- paddingBottom is missing from the calculation, so you should add it. You can look the original code from ScrollView methods.
- Also remove the useless cast to View
Kind Regards.
Davide
Hi Marteein,
this is a great solution, but how do I trigger the Keyboard state? Because if it fades in, the new bottom is the top of the keyboard
Hi,i have updated your code. My version support "OnTopReachedListener".
Thanks for your help <3
package org.altervista.xsparter.www.updatelayout;
import android.view.View;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ScrollView;
public class InteractiveScrollView extends ScrollView {
OnBottomReachedListener mListener;
OnTopReachedListener mListener2;
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();
}
else if (getScrollY() == 0 && mListener2 != null) {
mListener2.onTopReached();
}
super.onScrollChanged(l, t, oldl, oldt);
}
// Getters & Setters
public OnBottomReachedListener getOnBottomReachedListener() {
return mListener;
}
public void setOnBottomReachedListener(
OnBottomReachedListener onBottomReachedListener) {
mListener = onBottomReachedListener;
}
public OnTopReachedListener getOnTopReachedListener() {
return mListener2;
}
public void setOnTopReachedListener(
OnTopReachedListener onTopReachedListener) {
mListener2 = onTopReachedListener;
}
/**
* Event listener.
*/
public interface OnBottomReachedListener{
public void onBottomReached();
}
public interface OnTopReachedListener{
public void onTopReached();
}
}
Thank you all :-)
Thank you )) good job ))
Thanks a lot man , Cheers !!
First of all thank you very much for this.!
I ran into a problem with this. My case is, when reach the bottom, I'm enabling the save button. It works like a charm in the small screen. But when I'm using it the tablet where the screen is big enough not to scroll, the button is still disabled. I'd like to enable the button in this case, please suggest me what I can I do to get this working. Thank you again :)
I have updated your code. It is support "OnScrolledDownListener" and "OnScrolledUpListener".
public class InteractiveScrollView extends ScrollView{
private OnBottomReachedListener onBottomReachedListener;
private OnTopReachedListener onTopReachedListener;
private OnScrolledDownListener onScrolledDownListener;
private OnScrolledUpListener onScrolledUpListener;
public InteractiveScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public InteractiveScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public InteractiveScrollView(Context context) {
super(context);
init();
}
private void init() {
setFadingEdgeLength(0);
setVerticalFadingEdgeEnabled(false);
setHorizontalFadingEdgeEnabled(false);
setOverScrollMode(ScrollView.OVER_SCROLL_NEVER);
}
@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 && onBottomReachedListener != null) {
onBottomReachedListener.onBottomReached(t);
} else if (getScrollY() <= 0 && onTopReachedListener != null) {
onTopReachedListener.onTopReached(t);
} else{
if(t<oldt){
if (onScrolledDownListener != null){
onScrolledDownListener.onScrolledDown(t);
}
}else if (t>oldt){
if (onScrolledUpListener != null){
onScrolledUpListener.onScrolledUp(t);
}
}
}
super.onScrollChanged(l, t, oldl, oldt);
}
//Getters & Setters
public OnBottomReachedListener getOnBottomReachedListener() {
return onBottomReachedListener;
}
public void setOnBottomReachedListener(OnBottomReachedListener onBottomReachedListener) {
this.onBottomReachedListener = onBottomReachedListener;
}
public OnTopReachedListener getOnTopReachedListener() {
return onTopReachedListener;
}
public void setOnTopReachedListener(OnTopReachedListener onTopReachedListener) {
this.onTopReachedListener = onTopReachedListener;
}
public void setOnScrolledDownListener(OnScrolledDownListener onScrolledDownListener){
this.onScrolledDownListener = onScrolledDownListener;
}
public OnScrolledDownListener getOnScrolledDownListener() {
return onScrolledDownListener;
}
public void setOnScrolledUpListener(OnScrolledUpListener onScrolledUpListener){
this.onScrolledUpListener = onScrolledUpListener;
}
public OnScrolledUpListener getOnScrolledUpListener() {
return onScrolledUpListener;
}
/**
* Event listener.
*/
public interface OnBottomReachedListener{
public void onBottomReached(int scrollY);
}
public interface OnTopReachedListener{
public void onTopReached(int scrollY);
}
public interface OnScrolledDownListener{
public void onScrolledDown(int scrollY);
}
public interface OnScrolledUpListener{
public void onScrolledUp(int scrollY);
}
}
I encountered a problem. ie, Sometimes OnBottomReached is firing multiple times. Anyone has the same problem ???? Please help me to solve this
I encountered a problem. ie, Sometimes OnBottomReached is firing multiple times. Anyone has the same problem ???? Please help me to solve this
I encountered a problem. ie, Sometimes OnBottomReached is firing multiple times. Anyone has the same problem ???? Please help me to solve this
How do i use it/call it from main Activity...help me i am having trouble ???
@marteinn Under which license do you publish this?
@Croydon MIT. Will clarify in the description.
One-liner in Kotlin:
fun ViewGroup.isScrolledToBottom() = getChildAt(childCount - 1).bottom - height - scrollY == 0
good, it's work
topReach is fired multiple times
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
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.
So far, great thanks for your work, works just as expected.
Thank you.