天天看點

小距離監聽ListView或者ScrollView上下滑動

我們知道,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 = ;

    @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 > ) {//距離大于20px判定為滑動,進行回調,這個距離根據自己需求來定,越小越敏感。
                        Log.d("lelele", "onTouchEvent() returned: down");
                        listener.scrollState(true);
                    }
                    if (dY < -) {
                        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 > ) {
                        listener.scrollState(true);
                    }
                    if (dY < -) {
                        listener.scrollState(false);
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                oldY = y;
                break;
            default:
                break;
        }
        return super.onTouchEvent(ev);
    }
           

以上。

繼續閱讀