小距離監聽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 = 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);
    }

以上。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章