Reputation: 7624
I am using a horizontal scroll view and i want to keep the first item hidden under certain circumstances. Now i used the on touch listener to see how much the user has scrolled and to see of this first item/view is visible or not and then would do a scrollTo() based on some calculations. Everything was fine till i realised that this doesn't take care of fling cases where the user just flings and the horizontal scroll view scroll for some distance. So, i am not able to make the correct calculations. Thus, I have realised that the best would be to check if the first item is visible or not only once the horizontal scroll view has finally stopped scrolling, as a result of either touch or fling.
But i couldn't find a way which tells me when the horizontal scroll bar as stopped scrolling and is still.
Could someone please help me figure this out?
Thanks.
Upvotes: 1
Views: 3776
Reputation: 872
Extend the ScrollView to add a scroll listener. Then you can use that custom View and receive the events in the listener (the code is with an scrollView, but converting it to HorizontalScrollView should be pretty straightforward).
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.ScrollView;
public class ScrollViewWithListener extends ScrollView{
private boolean mCurrentlyTouching;
private boolean mCurrentlyFling;
public interface ScrollViewListener {
public void onScrollChanged(ScrollViewWithListener scrollView, int x, int y, int oldx, int oldy);
public void onEndScroll();
}
private ScrollViewListener scrollViewListener = null;
public ScrollViewWithListener(Context context) {
super(context);
}
public ScrollViewWithListener(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ScrollViewWithListener(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void setScrollViewListener(ScrollViewListener scrollViewListener) {
this.scrollViewListener = scrollViewListener;
}
@Override
public void fling(int velocityY) {
super.fling(velocityY);
mCurrentlyFling = true;
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
if (scrollViewListener != null) {
scrollViewListener.onScrollChanged(this, l, t, oldl, oldt);
}
if (Math.abs(t - oldt) < 2 || t >= getMeasuredHeight() || t == 0) {
if(!mCurrentlyTouching){
if (scrollViewListener != null) {
Log.d("SCROLL WITH LISTENER", "-- OnEndScroll");
scrollViewListener.onEndScroll();
}
}
mCurrentlyFling = false;
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
mCurrentlyTouching = true;
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
mCurrentlyTouching = false;
if(!mCurrentlyFling){
if (scrollViewListener != null) {
Log.d("SCROLL WITH LISTENER", "-- OnEndScroll");
scrollViewListener.onEndScroll();
}
}
break;
default:
break;
}
return super.onTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
mCurrentlyTouching = true;
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
mCurrentlyTouching = false;
if(!mCurrentlyFling){
if (scrollViewListener != null) {
Log.d("SCROLL WITH LISTENER", "-- OnEndScroll");
scrollViewListener.onEndScroll();
}
}
break;
default:
break;
}
return super.onInterceptTouchEvent(ev);
}
}
Then you use it in your xml like this:
<com.example.ScrollViewWithListener
android:id="@+id/scrollWithListener"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TEST" />
</com.example.ScrollViewWithListener>
Don't forget to set the listener you want to be notified with the scroll changes.
Upvotes: 5