seekbar长按和拖动事件冲突的解决办法

由于seekbar的拖动更改进度的监听是由AbsSeekBar的onTouchEvent来触发 因此可以通过重新onTouchEvent来实现
AbsSeekBar的onTouchEvent源码如下

@Override
    public boolean onTouchEvent(MotionEvent event) {
        if (!mIsUserSeekable || !isEnabled()) {
            return false;
        }
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if (isInScrollingContainer()) {
                    mTouchDownX = event.getX();
                } else {
                    startDrag(event);
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if (mIsDragging) {
                    trackTouchEvent(event);
                } else {
                    final float x = event.getX();
                    if (Math.abs(x - mTouchDownX) > mScaledTouchSlop) {
                        startDrag(event);
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                if (mIsDragging) {
                    trackTouchEvent(event);
                    onStopTrackingTouch();
                    setPressed(false);
                } else {

                    onStartTrackingTouch();
                    trackTouchEvent(event);
                    onStopTrackingTouch();
                }
                invalidate();
                break;
            case MotionEvent.ACTION_CANCEL:
                if (mIsDragging) {
                    onStopTrackingTouch();
                    setPressed(false);
                }
                invalidate(); // see above explanation
                break;
        }
        return true;
    }

由源码可见OnSeekBarChangeListener 的回调是在MotionEvent.ACTION_UP和MotionEvent.ACTION_CANCEL进行执行的 所以可以根据用户按住的时间,来决定是否这两个action是否调用父类的action

代码如下

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.support.v7.widget.AppCompatSeekBar;
import android.util.AttributeSet;
import android.view.MotionEvent;
/**
 * Created by jsc on 2017/7/13.
 */
public class LongTouchSeekBar extends AppCompatSeekBar {
    private long downTime;
    private LongClickListener longClickListener;
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == 1 && !hasLongTouch) {
                hasLongTouch = true;
                if (longClickListener != null) longClickListener.onLongClick();
            }
        }
    };
    private float lastY;
    private float lastX;
    public LongTouchSeekBar(Context context) {
        this(context, null);
    }
    public LongTouchSeekBar(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
    public LongTouchSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
    private boolean hasLongTouch = false;//是否已经执行长按操作
    private boolean possibleLongTouch = true;//可能是长按
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float y = event.getY();
        float x = event.getX();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                hasLongTouch = false;//初始化 是否已经执行过长按事件
                possibleLongTouch = true;//初始化  是否可能为长按模式
                lastY = y;
                lastX = x;
                downTime = System.currentTimeMillis();//记录按下的时间
                if (!handler.hasMessages(1)) {//如果消息队列中已有消息 则不在重新发送
                    handler.sendEmptyMessageDelayed(1, 800);
                }
                return super.onTouchEvent(event);
            case MotionEvent.ACTION_MOVE:
            //移动时如果x|y滑动了一段距离 则不可能为长按事件 即将 possibleLongTouch置为false
                if (lastX != 0 && lastY != 0 && (Math.abs(y - lastY) > 5 || Math.abs(x - lastX) > 5)) {
                    possibleLongTouch = false;
                    handler.removeMessages(1);
                    return super.onTouchEvent(event);
                }
                lastY = y;
                lastX = x;
                break;
            case MotionEvent.ACTION_UP:
                lastX = 0;
                lastY = 0;
                handler.removeMessages(1);
                if (System.currentTimeMillis() - downTime > 800 && possibleLongTouch) {
                    if (!hasLongTouch) {//如果已经执行过长按操作  则不需要再次执行
                        hasLongTouch = true;
                        if (longClickListener != null) {
                            longClickListener.onLongClick();
                        }
                    }
                    return true;
                }
                return super.onTouchEvent(event);
            case MotionEvent.ACTION_CANCEL:
                handler.removeMessages(1);
                lastX = 0;
                lastY = 0;
                return super.onTouchEvent(event);
        }
        return false;
    }
    public void setLongClickListener(LongClickListener longClickListener) {
        this.longClickListener = longClickListener;
    }
    public interface LongClickListener {
        void onLongClick();
    }
}

你可能感兴趣的:(view)