自定义View之四-滑动相关

1 滑动的三种方式

  • scrollTo和scrollBy
  • Animation
  • LayoutParams

1.1 scrollTo和scrollBy

1.view视图本身是无法滑动的,滑动的是view中的内容
2.scrollTo,scrollBy方法基于的坐标原点是view的左上角(不是屏幕左上角)

  • scrollTo
scrollTo(-100,-100)

1 scrollTo(x,y); -> x,y并不是代表坐标,而是表示偏移量
2 从(0,0)移动到(100,100),偏移量为(-100,-100),即view的内容分别向右向下各移动100
3 如果偏移量没有改变,那么重复调用view的内容也不会移动

  • scrollBy
scrollBy(-100,-100)

1 scrollBy(x,y)实际上就是调用了 scrollTo(mScrollX + x, mScrollY + y);
2 mScrollX、mScrollY指view内容的原始偏移量,x,y指当前偏移量(可以理解为相对于当前位置进行偏移)

2 滑动冲突

2.1滑动冲突的类型

  1. 子父方向不同
  2. 子父方向相同
  3. 前两种的嵌套

2.2滑动冲突的解决方案

  • 外部拦截法(父View做拦截判断)
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        boolean intercept = false;
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                intercept = false;
                break;
            case MotionEvent.ACTION_MOVE:
                if (需要拦截事件) {
                    intercept = true;
                } else {
                    intercept = false;
                }
                break;
            case MotionEvent.ACTION_UP:
                intercept = false;
                break;
            default:
                break;
        }
        return intercept;
    }

外部拦截法需要重写onIntercerptTouchEvent(),其中对于事件序列中的ACTION_DOWN事件不能拦截(因为一旦开始拦截,后续的事件将不再会传递给子孩子了,直接由自己来处理)

  • 内部拦截法(子View请求父布局做拦截判断)
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        boolean intercept = false;
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                getParent().requestDisallowInterceptTouchEvent(true);//请求父view不拦截事件
                break;
            case MotionEvent.ACTION_MOVE:
                if (父类需要此类点击事件) {
                    getParent().requestDisallowInterceptTouchEvent(false);
                }
                break;
            case MotionEvent.ACTION_UP:
                break;
            default:
                break;
        }
        return super.dispatchTouchEvent(ev);
    }

同时,父View需要重写onIntercerptTouchEvent

  @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            return false;
        } else {
            return true;
        }
    }

内部拦截法需要重写dispatchTouchEvent()和父View的onInterceptTouchEvent(),其中父view不能拦截ACTION_DOWN事件,因为ACTION_DOWN事件不受requestDisallowInterceptTouchEvent()影响,一旦父布局拦截,子view将无法通过requestDisallowInterceptTouchEvent()来控制事件传递。

你可能感兴趣的:(自定义View之四-滑动相关)