2.Android 高级UI<二>之事件分发机制&滑动冲突(2024精华版)

目录:

1.事件分发机制是怎么样的?

2.View与ViewGroup的事件分发有什么区别

3.onTouch和onTouchevent和onClick的执行顺序?

4.如何理解消费?

5.Button和ImageView有什么不一样?

6.可以达到父控件和子空间同时点击吗?

7.ListView上的button,点击button2个控件同时要有相应,应该怎么处理?

点击事件被拦截,但是相传到下面的view,如何操作?

8.请简述Android事件传递机制, ACTION_CANCEL事件何时触发?

  1. 滑动冲突源码分析

  2. 滑动冲突的几种解决方案的使用场景?什么时候用内部拦截?

11. 滑动冲突实践,实例: recleview嵌套recleview

1.事件分发机制是怎么样的?

1.1 事件分发机制分为2种:View事件的分发和ViewGroup事件分发机制

总结ViewGroup发现:dispathcTouchEvent开始-----disallownotIntercepter---onInterceptTouchEvent-----1.子类dispath() 2.父类TouchEvent方法

viewGroup分发.jpg

然后我们来看一下View中dispatchTouchEvent方法的源码:

public boolean dispatchTouchEvent(MotionEvent event) {
   if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
           mOnTouchListener.onTouch(this, event)) {
       return true;
   }
   return onTouchEvent(event);
}
1.2 view总结: 整个View的事件转发流程是:(原理是dispatchTouchEvent)
public boolean dispatchTouchEvent(MotionEvent event) {
    if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
            mOnTouchListener.onTouch(this, event)) {
        return true;
    }
    return onTouchEvent(event);
}
1.3 完整的总结:
分发机制总图.png

1). 事件分发机制是一种责任链模式, Android事件分发是先传递到ViewGroup,再由ViewGroup传递到View的。

2). 在ViewGroup中可以通过onInterceptTouchEvent方法对事件传递进行拦截,onInterceptTouchEvent方法返回true代表不允许事件继续向子View传递,返回false代表不对事件进行拦截,默认返回false。

3). 子View中如果将传递的事件消费掉,ViewGroup中将无法接收到任何事件。

4). .在ViewGroup中onInterceptTouchEvent方法若反回false,那么触屏事件会继续向下传递,

但如果没有子View去处理这个事件,即子view的onTouchEvent没有返回True

则最后还是由ViewGroup去处理这个事件,也就又执行了自己的onTouchEvent。

备注: ViewGroup 类中,实际是没有onTouchEvent 方法的,但是由于ViewGroup 继承自View,

1.4 深层次的总结: (从InputChannel)

在attach()方法的时候,通过上面的流程图我们知道,当我们的PhoneWindow创建完成之后,我们也在该Window上注册了InputChannel并与IMS通信,

IMS把事件写入InputChannel,WindowInputEventReceiver对事件进行处理并最终还是通过InputChannel反馈给IMS。

InputChannel最重要的!!!!!!!!

总结:兜兜转转一大圈我们神经都被绕弯了,我们在这里总结一下,当我们触摸(点击)屏幕时,

Android输入系统IMS通过对事件的加工处理再合适的Window接收者并通过InputChannel向Window派发加工后的事件,

并触发InputReceiver的onInputEvent的调用,由此产生后面一系列的调用,把事件派发给整个控件树的根DecorView

而DecorView又上演了一出偷梁换柱的把戏,先把事件交给Activity处理,在Activity中又把事件交还给了我们的DecorView。自此沿着控件树自上向下依次派发事件。

输入事件 .jpg

2.View与ViewGroup的事件分发有什么区别

ViewGruop的事件分发:

多了一个拦截事件的方法:onInterceptTouchEvent

ViewGroup的dispathcTouchEvent方法:里面有onInterceptTouchEvent方法

区别表格.jpg

3.onTouch和onTouchevent和onClick的执行顺序?

View.dispatchEvent----ontouch-----ontouchEvent(方法down,up,判断onclick时间)---onclick
   
   
//子控件的ontouch方法影响子控件的函数
//onTouch====onTouchEvent====onClick;
/**
* 检验view的事件分发顺序,点击---dispatch-  Ontouch返回值为ture  不执行---ontouchEvent---onclick
*/
button1.setOnTouchListener(new View.OnTouchListener() {
   @Override
   public boolean onTouch(View v, MotionEvent event) {
       Log.d("TAG", "button1  on touch"+event.getAction());
       return true;
   }
});

/**
* 检验view的事件分发顺序, 点击---dispatch-  Ontouch返回值为false执行---ontouchEvent---onclick
*/
button2.setOnTouchListener(new View.OnTouchListener() {
   @Override
   public boolean onTouch(View v, MotionEvent event) {
       Log.d("TAG", "button1  on touch" + event.getAction());
       return false;
   }
});

ontouch先执行,如果返回true,ontouchEvent,onClick都不执行

ontouch先执行,如果返回false,ontouchEvent,然后再是onclick方法

如果不重写onTouchListerner方法。

onTouchEvent如果返回true,不会执行onclick方法

onTouchEvent如果返回false,会执行onclick方法

onclick默认调用的是onTouchEvent。因为ontouch事件默认返回是false。那么就会响应onTochEvent。(onTouchEvent

总结:onTouch优先于onTouchEvent

1).看判断条件。如果没有mOnTouchListener ,ontouch不执行,onTouchEvent执行

2).如果有mOnTouchListener,并且onTouch =true,onTouchEvent不执行

  1. .如果有mOnTouchListener,并且onTouch =false,onTouchEvent执行

4.如何理解消费?view事件分发机制的案例

4.1 总结:

如果onTouch为true,代表消费了。不会执行onTouchevent了

如果子类的onTouchevent为true,代表消费了,父类不会执行onTouchevent

基本上就是返回true,就是消费了

4.2 案例说明
案例.jpg

当一个Touch事件(触摸事件为例)到达根节点,即Acitivty的ViewGroup时,它会依次下发,下发的过程是调用子View(ViewGroup)的dispatchTouchEvent方法实现的。

简单来说,就是ViewGroup遍历它包含着的子View,调用每个View的dispatchTouchEvent方法,而当子View为ViewGroup时,又会通过调用ViwGroup的dispatchTouchEvent方法继续调用其内部的View的dispatchTouchEvent方法。

上述例子中的消息下发顺序是这样的:①-②-⑤-⑥-⑦-③-④。

dispatchTouchEvent方法只负责事件的分发,它拥有boolean类型的返回值,当返回为true时,顺序下发会中断。

在上述例子中如果⑤的dispatchTouchEvent返回结果为true,那么⑥-⑦-③-④将都接收不到本次Touch事件

5.Button和ImageView有什么不一样?

Button和ImageView效果不一样:一个是自带点击,一个是要自己控制点击

onTouch能够得到执行需要两个前提条件,第一mOnTouchListener的值不能为空,第二当前点击的控件必须是enable的。因此如果你有一个控件是非enable的,

那么给它注册onTouch事件将永远得不到执行。对于这一类控件,如果我们想要监听它的touch事件,就必须通过在该控件中重写onTouchEvent方法来实现。

<wiz_code_mirror><pre class=" CodeMirror-line " role="presentation">/*ImageView默认是不能点击事件的,要想点击的话必须手动设置/</pre>

/**ImageView默认是不能点击事件的,要想点击的话必须手动设置*/
imageView.setClickable(true);

imageView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Log.e("TAG","imageView setOnTouchListener");
    }
});

6.可以达到父控件和子空间同时点击吗?

如下

7.ListView上的button,点击button2个控件同时要有相应,应该怎么处理?

7.1 具体方案:在listView的OnInterceptTouchEvent()方法里面。判断区域。是否拦截

在listView的空白区域:执行listview的onTouchEvent方法。拦截button

在button的点击区域: 不拦截,消费button的onTouchEvent事件。

当父控件是布局而子控件是控件时,如果要设置点击效果,可以在父布局里面加上android:clickable="true" ,在子控件里面设置android:clickable="false",并设置状态跟随父布局android:duplicateParentState="true",至于效果,则随自己写吧

7.2 案例分析4种情况:

1).如何让子类只有触摸事件,没有点击事件

2).如何让子类既有触摸事件又有点击事件

3).如何让父类只有触摸事件,没有点击事件

4).如何让父类既有触摸事件又有点击事件

分析总结:

  1. .onTouch为true,事件被消费了,ontouchevent不执行,点击也就不会执行
button.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Log.d("peng"," button.setOnTouchListener"+event.getAction());
        return true;
    }
});

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Log.d("peng"," button.setOnClickListener");
    }
});

2). onTouch为false,ontouchevent会执行,这样,点击事件会执行

button.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Log.d("peng"," button.setOnTouchListener"+event.getAction());
        return false;
    }
});

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Log.d("peng"," button.setOnClickListener");
    }

    
    默认情况下,子view的onTouchEvent返回true,消费
        
@Override
public boolean onTouchEvent(MotionEvent event) {
    boolean pass=super.onTouchEvent(event);
    Log.d("peng","onTouchEvent onTouchEvent"+pass);
    return pass;
}
  1. .父类想要响应,子类不能消费,onTouch false ,onTouchEvent 也为false,onTouch 为false
button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Log.d("peng"," button.setOnClickListener");
    }
});


viewHead.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Log.d("peng"," viewHead.setOnTouchListener"+event.getAction());
        return true;
    }
});

viewHead.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Log.d("peng"," viewHead.setOnClickListener");
    }
});

public class Myview extends android.support.v7.widget.AppCompatButton {
    public Myview(Context context) {
        super(context);
    }

    public Myview(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public Myview(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.d("peng","Myview onTouchEvent onTouchEvent"+false);
        return false;
    }
  1. .父类想要响应,子类不能消费,onTouch false ,onTouchEvent 也为false,onTouch 为false .父类的onTouchEvent也要重写true,代表消费了。
@Override
public boolean onTouchEvent(MotionEvent event) {
    Log.d("peng","MyParentView onTouchEvent");
    return true;
}

子控件拿到事件之后,先判断是否设置了OnTouchListener, 如果设置了,则调用OnTouchListener的onTouch方法,如果返回true,事件已经处理到此结束,则跳过onTouchEvent方法,否则调用onTouchEvent方法

7.3 点击事件被拦截,但是想传到下面的view,如何操作?

反向制约:重写子类的requestDisallowInterceptTouchEvent()方法返回true,就不会执行父类的onInterceptTouchEvent(),即可将点击事件传到下面的View。

7.4 我想让webview在应用里面后台运行?看不到界面

2个viewGoup

1个webview和一个ViewGroup(包含4个btn)

点击btn的时候,会消费掉事件

问题:viewgroup点击空白也是会有事件的,如何给他添加监听

加入点击空白页面,Viewgroup的子View消费掉。(webview的子空间)

问题:不想让子控件消费怎么做

1).可以自己消费掉,ontouch==true。不再传递了,onclick事件就不会执行

  1. .可以让另外一个viewgourp自己消费掉。

ontouch==true,自己的onclick不会在执行,但是这个子view还是响应了

原因:因为没有拦截,走了子类的dispathevent方法。子类的dispathevent----ontouch---子类的onclick方法消费了。

所以消费是onclick和ontouch方法,但是onclick方法也是要先调用ontouch---ontouchevnet----onclick。

总结:最后的消费指的时onTouch事件

7.5 有一个布局,然后有一个textview,然后想点击整个布局有点击事件

结果发现:点击textview的区域没有响应,因为textview把焦点占用了。为了让整个区域都有效果的话,把textview设置成

android:clickable="false"
按钮视图.jpg
<TextView
    android:id="@+id/tv_sport_data_second_value"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="@dimen/dp_20"
    android:textColor="@color/color_333333"
    android:textStyle="bold"
    android:clickable="false"
    android:text="0"
    android:layout_below="@id/ll_second_title"
    android:layout_marginTop="@dimen/dp_6"

<RelativeLayout
    android:id="@+id/rl_sport_data_second"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    >

    <LinearLayout
        android:id="@+id/ll_second_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:gravity="center_vertical"
        >
        <TextView
            android:id="@+id/tv_sport_data_second_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="@color/color_333333"
            android:textSize="@dimen/dp_14"
            android:text="@string/string_sport_rank_total_sport"
            ></TextView>

8.请简述Android事件传递机制, ACTION_CANCEL事件何时触发?

1). 关于ACTION_CANCEL何时被触发,系统文档有这么一种使用场景:在设计设置页面的滑动开关时,如果不监听ACTION_CANCEL,在滑动到中间时,如果你手指上下移动,就是移动到开关控件之外,则此时会触发ACTION_CANCEL,而不是ACTION_UP,造成开关的按钮停顿在中间位置。
意思是当滑动的时候就会触发,不知道大家搞没搞过微信的长按录音,有一种状态是“松开手指,取消发送”,这时候就会触发ACTION_CANCEL。

2). 简单来说不是一个完整的手势响应 例如:子控件只是响应了down 而父控件把子控件的up事件拦截了 这个时候就会触发cancel事件。

详细:当控件收到前驱事件(什么叫前驱事件?一个从DOWN一直到UP的所有事件组合称为完整的手势,中间的任意一次事件对于下一个事件而言就是它的前驱事件)之后,后面的事件如果被父控件拦截,那么当前控件就会

9. 滑动冲突源码分析

10. 滑动冲突的几种解决方案的使用场景?什么时候用内部拦截?

10. 1 外部拦截法:(根据自己的业务拦截子view),重写一个方法

即父View根据需要对事件进行拦截。逻辑处理放在父View的onInterceptTouchEvent方法中。我们只需要重写父View的onInterceptTouchEvent方法,并根据逻辑需要做相应的拦截即可。

public boolean onInterceptTouchEvent(MotionEvent event) {
        boolean intercepted = false;
        int x = (int) event.getX();
        int y = (int) event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN: {
                intercepted = false;
                break;
            }
            case MotionEvent.ACTION_MOVE: {
                if (满足父容器的拦截要求) {
                    intercepted = true;
                } else {
                    intercepted = false;
                }
                break;
            }
            case MotionEvent.ACTION_UP: {
                intercepted = false;
                break;
            }
            default:
                break;
        }
        mLastXIntercept = x;
        mLastYIntercept = y;
        return intercepted;
    }

注意点:

1). ACTION_DOWN 一定返回false,不要拦截它,否则根据View事件分发机制,后续ACTION_MOVE 与 ACTION_UP事件都将默认交给父View去处理!

2). ACTION_MOVE方法中进行判断,根据业务逻辑需要,如果需要父View处理则返回true,否则返回false,事件分发给子View去处理。

3). ACTION_UP也需要返回false,如果返回true,并且滑动事件交给子View处理,那么子View将接收不到ACTION_UP事件,子View的onClick事件也无法触发。

  • 而父View不一样,如果父View在ACTION_MOVE中开始拦截事件,那么后续ACTION_UP也将默认交给父View处理!
  • 可以直接用super。默认都是不拦截
可以直接用super。默认都是不拦截
/***
 * 如果不写整个方法的话:就会响应子类的touchEvent方法,而不响应自己viewGroup的方法
 * @param
 * @return
 */
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN://0
            mXDown = ev.getRawX();
            mXLastMove = mXDown;
            break;
        case MotionEvent.ACTION_MOVE://2
            mXMove = ev.getRawX();//获取相对于屏幕的x值
            float diff = Math.abs(mXMove - mXDown);
            mXLastMove = mXMove;
            // 当手指拖动值大于TouchSlop值时,认为应该进行滚动,拦截子控件的事件
            if (diff > mTouchSlop) {
                return true;
            }
            break;
        case MotionEvent.ACTION_UP://1
            break;
    }

    boolean superResult = super.onInterceptTouchEvent(ev);
    Log.d("ScrollerLayout", "superResult" + superResult+"ev"+ev.getAction());
    return superResult;
}

具体:

1.down 不拦截,否则up收不到,点击事件也会没有

2.move 更加业务判定。得到子view,滑动的距离和item的位置决定

3.up 不拦截

10.1.2 具体案例写法

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    boolean intercepted = false;
    int y = (int) event.getY();

    switch (event.getAction()) {

        case MotionEvent.ACTION_DOWN: {
            nowY = y;
            intercepted = super.onInterceptTouchEvent(event);
            break;
        }
        case MotionEvent.ACTION_MOVE: {
            if(mListView.getFirstVisiblePosition()==0
                    && y>nowY){
                intercepted = true;
                break;
            }
            else if(mListView.getLastVisiblePosition()==mListView.getCount()-1
                    && y<nowY){
                intercepted = true;
                break;
            }
            intercepted = false;
            break;
        }
        case MotionEvent.ACTION_UP: {
            intercepted = false;
            break;
        }
        default:
            break;
    }

    return intercepted;
} 

10.2 内部拦截法:(拦截子view) (重写2个方法,都是事件分发的方法)

即父View不拦截任何事件,所有事件都传递给子View,子View根据需要决定是自己消费事件还是给父View处理。这需要子View使用requestDisallowInterceptTouchEvent方法才能正常工作。下面是子View的dispatchTouchEvent方法的伪代码:

1). 父View需要重写onInterceptTouchEvent方法:

为什么要重写父类的 onInterceptTouchEvent?因为默认不拦截,你需要的是拦截它

 public boolean onInterceptTouchEvent(MotionEvent event) {

        int action = event.getAction();
        if (action == MotionEvent.ACTION_DOWN) {//down不拦截,给子类
            return false;
        } else {//拦截
            return true;
        }
    }

2). 重写子类的dispatchTouchEvent()方法

 public boolean dispatchTouchEvent(MotionEvent event) {
        int x = (int) event.getX();
        int y = (int) event.getY();

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN: {
                parent.requestDisallowInterceptTouchEvent(true); // 父类不拦截, 子类处理
                break;
            }
            case MotionEvent.ACTION_MOVE: {
                int deltaX = x - mLastX;
                int deltaY = y - mLastY;
                if (父容器需要此类点击事件) {
                    parent.requestDisallowInterceptTouchEvent(false);//请求父类拦截, 父类处理
                }
                break;
            }
            case MotionEvent.ACTION_UP: {
                break;
            }
            default:
                break;
        }

        mLastX = x;
        mLastY = y;
        return super.dispatchTouchEvent(event);
    }

10.2.1 内部拦截法总结:

1). 父View不能拦截ACTION_DOWN事件,由于ACTION_DOWN不受FLAG_DISALLOW_INTERCEPT标志位控制,一旦父容器拦截ACTION_DOWN那么所有的事件都不会传递给子View。

2). View的dispatchTouchEvent方法的ACTION_DOWN中, parent.requestDisallowInterceptTouchEvent(true)2). 滑动策略的逻辑放在子View的dispatchTouchEvent方法的ACTION_MOVE中,如果父容器需要获取点击事件则调用 parent.requestDisallowInterceptTouchEvent(false)方法,让父容器去拦截事件。如果不需要,则相反

10.2.2 内部拦截法原理:

1). 内部拦截法也叫View分发反向制约的方法? 2). 拦截不拦截,由2个东西决定的。一个是requestDisllowIntercepter和onInterceptTouchEvent()2个决定的。

原因:但是子元素可以通过requestDisallowInterceptTouchEvent来干预父元素的分发过程,但是down事件除外(因为down事件方法里,会清除所有的标志位)。

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    if (mInputEventConsistencyVerifier != null) {
        mInputEventConsistencyVerifier.onTouchEvent(ev, 1);
    }

    // If the event targets the accessibility focused view and this is it, start
    // normal event dispatch. Maybe a descendant is what will handle the click.
    if (ev.isTargetAccessibilityFocus() && isAccessibilityFocusedViewOrHost()) {
        ev.setTargetAccessibilityFocus(false);
    }

if (actionMasked == MotionEvent.ACTION_DOWN
        || mFirstTouchTarget != null) {
    final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
    if (!disallowIntercept) {
        intercepted = onInterceptTouchEvent(ev);
        ev.setAction(action); // restore action in case it was changed
    } else {
        intercepted = false;
    }

10.3 从内容逆向思维分析

1). 有时候,我们不想去修改引入的第三方控件,或者说是无法修改时。就必须考虑从当前从Touch传递事件中最后的那个View逆向考虑。

首先,由Android中View的Touch事件传递机制,我们知道Touch事件,首先必然由最外层View拦截,如果无法更改这个最外层View,那么是不是就没辙了呢?

其实不然,Android这么高大上的系统必然考虑到了这个问题,好了废话不说,先看代码

解决方案:onTouch方法中每次进入就设定父View不拦截此次事件,然后在MOTION_MOVE时候,根据滑动的距离判断再决定是父View是否有权利拦截Touch事件(即滑动行为)。

    carouselView.setOnTouchListener( new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            carouselView.getParent().requestDisallowInterceptTouchEvent( true );
            int x = ( int ) event.getRawX();
            int y = ( int ) event.getRawY();

            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                lastX = x;
                lastY = y;
                break ;
                case MotionEvent.ACTION_MOVE:
                int deltaY = y - lastY;
                int deltaX = x - lastX;
                if (Math.abs(deltaX) < Math.abs(deltaY)) {
                    carouselView.getParent().requestDisallowInterceptTouchEvent( false );
                } else {
                    carouselView.getParent().requestDisallowInterceptTouchEvent( true );
                }
                default :
                break ;
            }
            return false ;
        }
}
2). 一个viewpager2里面放了很多图片。但是图片又可以大于屏幕,导致滑动冲突。浏览图片 ViewPager2和HorizontalScrollView滑动冲突 结果:Viewpager2不能重新怎么办?它是final类。导致内部拦截和外部拦截不适用!

重写onTouchListener();

10.4 down,move ,Up,都是否需要拦截总结?

1). ACTION_DOWN,都不要拦截子类

在这里,首先down事件父容器必须返回false ,因为若是返回true,也就是拦截了down事件,

那么后续的move和up事件就都会传递给父容器,子元素就没有机会处理事件了。

其次是up事件也返回了false,一是因为up事件对父容器没什么意义,其次是因为若事件是子元素处理的,却没有收到up事件会让子元素的onClick事件无法

2). 要在MotionEvent.ACTION_MOVE根据情况,是父类滑动还是子类滑动

10.5 滑动冲突的几种解决方案的使用场景?什么时候用内部拦截?

主要用内部拦截,系统里面的,horscorrlview和,比如recyleview.

原因: 你只能重新你可以的, 能达到的view(主要看你哪个View是你自己的)

11. 滑动冲突实践,实例: recleview嵌套recleview

11. 1 一个ScrowView(父类)和一个RecycleView(子类)

他说重写子类的onIntecepter方法,让子类拦截,消费掉

11.2 ViewPager中嵌套ViewPager怎么处理滑动冲突?

1).重写canScroll()方法

2).自己手写
11.3 一个scorview和一个日期选择器
分析:scorllView是父类,datapinker是子类(viewGroup)

现在现象:在分辨率比较小的手机中,有时候滑动scorllView,有时候滑动dataPinker

需要实现的效果:拦截scorllView。超过1屏的时候,自己滑动

private void doMove(MotionEvent event)
{

    mMoveLen += (event.getY() - mLastDownY);

    if (mMoveLen > MARGIN_ALPHA * mMinTextSize / 2)
    {
        // 往下滑超过离开距离
        moveTailToHead();
        mMoveLen = mMoveLen - MARGIN_ALPHA * mMinTextSize;
    } else if (mMoveLen < -MARGIN_ALPHA * mMinTextSize / 2)
    {
        // 往上滑超过离开距离
        moveHeadToTail();
        mMoveLen = mMoveLen + MARGIN_ALPHA * mMinTextSize;
    }

    mLastDownY = event.getY();
    invalidate();
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容