我們知道,listview的onScrollListener的回調監聽只是返回firstVisibleItem,totalItem等,利用這些參數我們是無法做到小距離的滑動判斷的,特別是滑動的距離小於一個item高度的時候。
其實解決方式很簡直,我們可以繼承listView並且複寫onTouchEvent()方法,通過MotionEvent 來拿到想要的參數,繼而判斷上下滑動。注意,不要破壞原有的事件處理體系。
代碼很短,也很簡單。
/**
* Created by xingkong on 2016/11/23.
*/
public class ScrollListenerListView extends ListView {
public ScrollListenerListView(Context context) {
super(context);
}
public ScrollListenerListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ScrollListenerListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
private int oldY = 0;
@Override
public boolean onTouchEvent(MotionEvent ev) {
int y = (int) ev.getRawY();
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
oldY = y; //手指按下位置
break;
case MotionEvent.ACTION_MOVE:
int dY = y - oldY;//計算滑動距離
if (listener != null) {
if (dY > 20) {//距離大於20px判定爲滑動,進行回調,這個距離根據自己需求來定,越小越敏感。
Log.d("lelele", "onTouchEvent() returned: down");
listener.scrollState(true);
}
if (dY < -20) {
Log.d("lelele", "onTouchEvent() returned: up");
listener.scrollState(false);
}
}
break;
case MotionEvent.ACTION_UP:
oldY = y;//更新初始位置
break;
}
return super.onTouchEvent(ev);//這裏一定要super回去,不要破壞原有listview的滑動處理。
}
//以下就是接口回調。沒什麼好說的。
public interface OnScrollUpDownListener {
void scrollState(boolean statue);
}
private OnScrollUpDownListener listener;
public void setOnScrollUpDownListener(OnScrollUpDownListener listener) {
this.listener = listener;
}
}
使用的話也是很簡單,正常的監聽設置就行了。
mListView.setOnScrollUpDownListener(new ScrollListenerListView.OnScrollUpDownListener() {
@Override
public void scrollState(boolean statue) {
if (statue){//down
if (btn_ok.getVisibility() == View.GONE) {
mShowAction = AnimationUtils.loadAnimation(getContext(), R.anim.push_up_new);
btn_ok.setVisibility(View.VISIBLE);
btn_ok.setAnimation(mShowAction);
}
}else {//up
if (btn_ok.getVisibility() == View.VISIBLE) {
mHiddenAction = AnimationUtils.loadAnimation(getContext(), R.anim.push_down_new);
btn_ok.setVisibility(View.GONE);
btn_ok.setAnimation(mHiddenAction);
}
}
}
});
這裏代碼,沒有做fling處理。也有需要可以加上去,也是比較簡單,就不說了。ScrollView的處理類似。
————————————————————————————–分割線:
今天嘗試使用scrollview來做這個東西,發現down事件監聽不到。回想下事件分發,纔想起如果子控件能夠消化事件,那麼父控件是沒辦法回調onTouchEvent()方法的。所以,其實將以上處理邏輯放在 dispatchTouchEvent(MotionEvent ev),是不管怎樣都會回調的。
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
int y = (int) ev.getRawY();
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
oldY = y;
break;
case MotionEvent.ACTION_MOVE:
int dY = y - oldY;
if (listener != null) {
if (dY > 20) {
listener.scrollState(true);
}
if (dY < -20) {
listener.scrollState(false);
}
}
break;
case MotionEvent.ACTION_UP:
oldY = y;
break;
default:
break;
}
return super.onTouchEvent(ev);
}
以上。