View的滑动冲突和解决方案
1.滑动冲突原因:
当有内外两层View同时可以滑动的时候,这个时候就会产生滑动冲突。
2.常见的冲突场景:
场景1:
场景2:
场景3:
4.解决方法种类:
(1)外部拦截法:
针对场景1,我们可以发现外部和内部的滑动方向不一样也就是说只要判断当前dy和dx的大小,如果dy>dx,那么当前就是竖直滑动,否则就是水平滑动。明确了这个我就就可以根据当前的手势开始拦截了。从view的事件分发中我们了解点击事件的分发顺序是 通过父布局分发,如果父布局没有拦截,即onInterceptTouchEvent返回false,才会传递给子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;
}
上面的代码差多就是外部拦截的通用模板了,在onInterceptTouchEvent方法中,
首先是ACTION_DOWN这个事件,父容器必须返回false,即不拦截事件,因为一旦父容器拦截了ACTION_DOWN这个事件,那么后续的ACTION_MOVE和ACTION_UP事件将直接交给父容器处理,这个时候事件没法继续传递给子元素了;
然后是ACTION_MOVE这个事件,这个事件可以根据需要决定是否拦截,如果父容器需要拦截就返回true,否则返回false;
最后是ACTION_UP这个事件,这里必须返回false,因为这个事件本身也没有太多意义。
so场景一的外部拦截解决方法:
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: {
int deltaX=x-mLastXIntercept;
int deltaY=y=mLastYIntercept;
if(Math.abs(deltaX)>Math.abs(deltaY)){
intercepted=true;
}else{
intercepted=false;
}
break;
}
case MotionEvent.ACTION_UP: {
intercepted = false;
break;
}
default:
break;
}
mLastXIntercept=x;
mLastYIntercept=y;
return intercepted;
}
场景二的外部拦截方法:
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: {
mLastYIntercept=y;
intercepted = super.onInterceptTouchEvent(event);
break;
}
case MotionEvent.ACTION_MOVE: {
if(listView.getFirstVisiblePosition()==0 &&y>mLastYIntercept){
intercepted=true;
}else if(listView.getLastVisiblePosition()==listView.getCount-1&&y <mLastYIntercept){
intercepted=false;
break;
}
intercepted = false;
break;
}
case MotionEvent.ACTION_UP: {
intercepted = false;
break;
}
default:
break;
}
mLastXIntercept=x;
mLastYIntercept=y;
return intercepted;
}
(2)内部拦截法
内部拦截法是指父容器不拦截任何事件,所有的事件都传递给子元素,如果子元素需要此事件就直接消耗掉,否则就交给父容器去处理
(android系统中,一次点击事件是从父view传递到子view中,每一层的view可以决定是否拦截并处理点击事件或者传递到下一层,如果子view不处理点击事件,则该事件会传递会父view,由父view去决定是否处理该点击事件。在子view可以通过设置此方法去告诉父view不要拦截并处理点击事件,父view应该接受这个请求直到此次点击事件结束)需要用到方法requestDisallowInterceptTouchEvent。
内部拦截通用模板:
public boolean onInterceptTouchEvent(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-mLastXIntercept;
int deltaY=y=mLastYIntercept;
if(父容器需要拦截的事件){
parent.requestDisallowInterceptTouchEvent(false); //父布局需要要拦截此事件
}
break;
}
case MotionEvent.ACTION_UP: {
intercepted = false;
break;
}
default:
break;
}
mLastXIntercept=x;
mLastYIntercept=y;
return super.dispathTouchEvent(event);
}
so 场景二的内部拦截解决方法:
//拦截除了Down事件以外的其他方法:
public boolean onInterceptTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
int action = event.getAction();
if(action == MotionEvent.ACTION_DOWN){
mLastXIntercept=x;
mLastYIntercept=y;
return super.dispathTouchEvent(event);
}else{
return true;
}
}
场景三建议使用内部拦截方法比较方便
View的滑动冲突和解决方案的更多相关文章
- 一个Demo带你彻底掌握View的滑动冲突
本文已授权微信公众号:鸿洋(hongyangAndroid)在微信公众号平台原创首发. 近期在又一次学习Android自己定义View这一块的内容.遇到了平时开发中常常碰到的一个棘手问题:View的滑 ...
- view的滑动冲突解决方案
一.常见的滑动冲突场景 1.外部滑动方向和内部滑动方向不一致 2.外部滑动方向和内部滑动方向一致 3.上面两种情况的嵌套 二.滑动冲突处理的原则 场景1的处理原则是:当用户左右滑动时,需要让外部的vi ...
- View的滑动冲突
一.常见的滑动冲突 场景1:外部滑动和内部滑动不一致 场景2:外部滑动和内部滑动一致 场景3:上面两种情况的嵌套 二.滑动冲突的处理方法 场景一:根据水平滑动还是竖直滑动判断到底由谁来拦截事件. 场景 ...
- 自定义控件(视图)2期笔记13:View的滑动冲突之 内部拦截法
1. 内部拦截法: 父容器不拦截事件,所有的事件全部都传递给子元素,如果子元素需要此事件就直接消耗掉,否则就交给父容器进行处理. 这种方法和Android中的事件分发机制不一样,需要配合request ...
- 自定义控件(视图)2期笔记12:View的滑动冲突之 外部拦截法
1. 外部拦截法: 点击事件通过父容器拦截处理,如果父容器需要就拦截,不需要就不拦截. 这种方法比较符合事件分发机制.外部拦截法需要重写父容器的onInterceptTouchEvent方法,在内部做 ...
- 自定义控件(视图)2期笔记11:View的滑动冲突之 概述
1. 引入: 滑动冲突可以说是日常开发中比较常见的一类问题,也是比较让人头疼的一类问题,尤其是在使用第三方框架的时候,两个原本完美的控件,组合在一起之后,忽然发现整个世界都不好了. 那到底是为什么会产 ...
- Android scrollview嵌套webview滑动冲突的解决方案
在Android开发中有时我们需要在scrollview中嵌套webview这时你会发现这两者的滑动事件产生了冲突导致:webview很难被滑动,即使被滑动了一点也非常不顺畅.解决方案也比较简单只需要 ...
- Android开发——View滑动冲突解决方案
0. 前言 我们在Android开发--事件分发机制详解中深入学习了事件分发机制,为我们解决Android开发中的滑动冲突问题做了初步准备.针对滑动冲突这里给出两种解决方案:外部拦截法和内部拦截法 ...
- (转载)Android滑动冲突的完美解决
Android滑动冲突的完美解决 作者:softwindy_brother 字体:[增加 减小] 类型:转载 时间:2017-01-24我要评论 这篇文章主要为大家详细介绍了Android滑动冲突的完 ...
随机推荐
- [JZOJ4759] 【雅礼联考GDOI2017模拟9.4】石子游戏
题目 描述 题目大意 在一棵树上,每个节点都有些石子. 每次将mmm颗石子往上移,移到根节点就不能移了. 双方轮流操作,问先手声还是后手胜. 有三种操作: 1. 询问以某个节点为根的答案. 2. 改变 ...
- IOS6 新特性之UIActivityViewController详解
新的IOS6增加了一些新特性.因为应用需要,所以在国庆的几天里.研究了一下IOS6的说明文档,然后大概地总结了一下UIActivityViewController的用法与大家分享. 首先 从实际效果入 ...
- webstorm中使用git管理服务器上的代码——入门级
一.首先要确保电脑已经成功安装好git了.(记住git的安装位置) 二.这里需要给webstorm配置一下:依次点击:file –> Settings –> Version Control ...
- 关于获取webview(窗口间关系)的方法
1.获取指定页面ID的webview plus.webview.getWebviewById('为页面设置的id值'): 该方法主要用于首页底部导航切换到子页面时不执行子页面的函数,因为在设置导航的时 ...
- 《DSP using MATLAB》Problem 8.3
代码: %% ------------------------------------------------------------------------ %% Output Info about ...
- java笔试之取近似值
写出一个程序,接受一个正浮点数值,输出该数值的近似整数值.如果小数点后数值大于等于5,向上取整:小于5,则向下取整. package test; import java.util.*; import ...
- C++面向对象高级编程(上)-Geekband
头文件和类声明 一定要注意使用防卫式的头文件声明: #ifndef _CLASSHEAD_ #define _CLASSHEAD_ . . . . #endif 基于对象和面向对象 : 基于对象 单一 ...
- 利用animate.css和es6制作文字向上滚动的效果
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <link rel= ...
- 微信小程序——tab导航栏
wxml: <view class="tab"> <view class="tab-left" bindtap="tabFun&q ...
- [洛谷]P1505 [国家集训队]旅游
题目链接: 传送门 题目分析: 树剖板,支持单点修改,区间取反,区间求最大值/最小值/和 区间取反取两次等于没取,维护一个\(rev\ tag\),每次打标记用\(xor\)打,记录是否需要翻转,\( ...