package com.util.ListenedScrollView;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.ScrollView;
/**
* 带有滚动监听的ScrollView
*
* @author 拉风的道长(OSChina.net)
*
*/
public class ListenedScrollView extends ScrollView {
private static final String TAG = ListenedScrollView.class.getSimpleName();
// 检查ScrollView的最终状态
private static final int CHECK_STATE = 0;
// 外部设置的监听方法
private OnScrollListener onScrollListener;
// 是否在触摸状态
private boolean inTouch = false;
// 上次滑动的最后位置
private int lastT = 0;
/**
* 构造方法
*
* @param context
*/
public ListenedScrollView(Context context) {
super(context);
}
/**
* 构造方法
*
* @param context
* @param attrs
*/
public ListenedScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* 构造方法
*
* @param context
* @param attrs
* @param defStyleAttr
*/
public ListenedScrollView(Context context, AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
inTouch = true;
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
inTouch = false;
lastT = getScrollY();
checkStateHandler.removeMessages(CHECK_STATE);// 确保只在最后一次做这个check
checkStateHandler.sendEmptyMessageDelayed(CHECK_STATE, 5);// 5毫秒检查一下
break;
default:
break;
}
Log.d(TAG, "inTouch = " + inTouch);
return super.onTouchEvent(ev);
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
if (onScrollListener == null) {
return;
}
Log.d(TAG, "t = " + t + ", oldt = " + oldt);
if (inTouch) {
if (t != oldt) {
// 有手指触摸,并且位置有滚动
Log.i(TAG, "SCROLL_STATE_TOUCH_SCROLL");
onScrollListener.onScrollStateChanged(this,
OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
}
} else {
if (t != oldt) {
// 没有手指触摸,并且位置有滚动,就可以简单的认为是在fling
Log.w(TAG, "SCROLL_STATE_FLING");
onScrollListener.onScrollStateChanged(this,
OnScrollListener.SCROLL_STATE_FLING);
// 记住上次滑动的最后位置
lastT = t;
checkStateHandler.removeMessages(CHECK_STATE);// 确保只在最后一次做这个check
checkStateHandler.sendEmptyMessageDelayed(CHECK_STATE, 5);// 5毫秒检查一下
}
}
onScrollListener.onScrollChanged(l, t, oldl, oldt);
}
private Handler checkStateHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (lastT == getScrollY()) {
// 如果上次的位置和当前的位置相同,可认为是在空闲状态
Log.e(TAG, "SCROLL_STATE_IDLE");
onScrollListener.onScrollStateChanged(ListenedScrollView.this,
OnScrollListener.SCROLL_STATE_IDLE);
// from http://blog.chinaunix.net/uid-20782417-id-1645164.html
if (getScrollY() + getHeight() >= computeVerticalScrollRange()) {
onScrollListener.onBottomArrived();
} else {
Log.d(TAG, "没有到最下方");
}
}
}
};
/**
* 设置滚动监听事件
*
* @param onScrollListener
* {@link OnScrollListener} 滚动监听事件(注意类的不同,虽然名字相同)
*/
public void setOnScrollListener(OnScrollListener onScrollListener) {
this.onScrollListener = onScrollListener;
}
/**
* 滚动监听事件
*
* @author 拉风的道长
*
*/
public interface OnScrollListener {
/**
* The view is not scrolling. Note navigating the list using the
* trackball counts as being in the idle state since these transitions
* are not animated.
*/
public static int SCROLL_STATE_IDLE = 0;
/**
* The user is scrolling using touch, and their finger is still on the
* screen
*/
public static int SCROLL_STATE_TOUCH_SCROLL = 1;
/**
* The user had previously been scrolling using touch and had performed
* a fling. The animation is now coasting to a stop
*/
public static int SCROLL_STATE_FLING = 2;
/**
* 滑动到底部回调
*/
public void onBottomArrived();
/**
* 滑动状态回调
*
* @param view
* 当前的scrollView
* @param scrollState
* 当前的状态
*/
public void onScrollStateChanged(ListenedScrollView view,
int scrollState);
/**
* 滑动位置回调
*
* @param l
* @param t
* @param oldl
* @param oldt
*/
public void onScrollChanged(int l, int t, int oldl, int oldt);
}
}
ListenedScrollView
一个带有监听的ScrollView。
使用方法
与ScrollView使用基本一致
XML中
<com.util.ListenedScrollView
android:id="@+id/listenedScrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
...
/>
代码中
ListenedScrollView listenedScrollView = (ListenedScrollView)findViewById(R.id.listenedScrollView);
//设置监听。
listenedScrollView.setOnScrollListener(new ListenScrollView.OnScrollListener() {
@Override
public void onBottomArrived() {
//滑倒底部了
}
@Override
public void onScrollStateChanged(ScrollView view, int scrollState) {
//滑动状态改变
}
@Override
public void onScrollChanged(int l, int t, int oldl, int oldt) {
//滑动位置改变
}
});
带有滚动监听的ScrollView
最新推荐文章于 2023-08-27 00:54:08 发布