被遗弃的竹签

时间:2018-01-28 12:18:21来源:杰瑞文章网点击:作文字数:700字
这个知识点是在太大了,是年多个知识点的汇总,很难搞,高级的页面视图效果和动画都离不开他,我们必须想一切办法搞明白~ 这对这部分内容我也是新手,本文负责记录下找到的资料,分类汇总下。 处理思路 在开发中,滑动冲突有很多,比如ScrollView嵌套ListView、ScrollView嵌套ViewPager、ViewPager嵌套ScrollView等等各种嵌套之后的滑动冲突 归根结底可以分为两种: 同方向滑动冲突: 比如ScrollView嵌套ListView,或者是ScrollView嵌套自己 不同方向滑动冲突: 比如ScrollView嵌套ViewPager,或者是ViewPager嵌套ScrollView,这种情况其实很典型。现在大部分应用最外层都是ViewPager+Fragment 的底部切换(比如微信)结构,这种时候,就很容易出现滑动冲突。不过ViewPager里面无论是嵌套ListView还是ScrollView,滑动冲突是没有的,毕竟是官方的东西,可能已经考虑到了这些,所以比较完善。 处理思路也可以分2种: 从外层处理 从内层处理 从外层处理 比如在外层滑动容器中,判断滑动方向,不是外层滑动容易方向而是内层滑动控件方向的,外层就不拦截了,交给内层 从内层处理 一般,官方提供的 layout,view 都不会拦截 action_down,这个事件,所以内层滑动控件的 dispatchTouchEvent -> onInterceptTouchEvent 肯定执行一次的,这时我们可以在内层 view 的 onInterceptTouchEvent 方法中请求忽略外层容器拦截事件 getParent().requestDisallowInterceptTouchEvent(true) ,然后我们判断是不是需要我们消费的事件,不是的话我们不消费,交给上一层去处理。 内层控件若是 view 的话,是没有 onInterceptTouchEvent 方法的,那么 getParent().requestDisallowInterceptTouchEvent(true) 写在哪里呢 setOnTouchListener,OnTouchListener.onTouch 方法在 view 的事件处理中最先执行,是个合适的位置 参考资料看这个 Android滑动冲突解决方法(一) 大体的思路基本都是根据这个逻辑走的,下面我们看看具体的滑动冲突的情况。 ScrollView嵌套ViewPager冲突 自定义一个MyScrollView继承ScrollView,重写 onInterceptTouchEvent方法,在 Action_Move事件中判断,如果水平滑动距离大于竖直滑动距离,则return false,表示不拦截事件,把事件分发到下一级控件,交由下一级处理 public class MyScrollView extends ScrollView{ private float xDistance; private float yDistance; private float xLast; private float yLast; /** * 在该方法中进行判断 */ @Override public boolean onInterceptTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: xDistance = yDistance = 0.0f; xLast = ev.getX(); yLast = ev.getY(); break; case MotionEvent.ACTION_MOVE: final float curX = ev.getX(); final float curY = ev.getY(); xDistance += Math.abs(curX - xLast); yDistance += Math.abs(curY - yLast); if(xDistance > yDistance) return false; break; default: break; } return super.onInterceptTouchEvent(ev); } } 参考资料: Android中事件传递机制 - 滑动冲突 ScrollView 嵌套 ScrollView 在 onInterceptTouchEvent 事件拦截函数内巧用 getParent().requestDisallowInterceptTouchEvent(true) 就可以让所有的父控件不拦截我们的事件了。 @Override public boolean onInterceptTouchEvent(MotionEvent ev) { getParent().requestDisallowInterceptTouchEvent(true); return super.onInterceptTouchEvent(ev); } 参考例子: ScrollView嵌套ScrollView的滑动冲突 NestedScrollView 嵌套 RecyclerView 这是最简单的处理嵌套滚动冲突的办法了,典型案例:NestedScrollView 嵌套 RecyclerView 参考例子: NestedScrollView+RecyclerView优雅的解决滑动冲突 给 RecyclerView 设置禁止滚动,RecyclerView 就会忽略 view 的复用机制,当前屏幕控件恩那个显示多少条 item ,就显示多少条 item,剩下的会被忽略。 这适用于 item 数量能偶一屏显示的列表。对于数量多的列表需要考重写布局管理器 //布局文件的RecyclerView中设置 android:nestedScrollingEnabled="false" //或者Java代码设置 recyclerView.setNestedScrollingEnabled(false); 说下缺点,禁用 RecyclerView 的滚动之后,在滚动嵌套中,局域内层的 RecyclerView 还是会首先收到触摸事件的,对于非滚动方向的事件在处理后,上层滚动控件比如 NestedScrollView 是收不到的。 典型的例子就是在这个嵌套页面中,我们在内层列表的位置斜的角度稍微大点上下滑,你会发现我滑动的手势被列表吃了,外面的滚动控件不会滚动。 viewpager嵌套 webview webview 中加载的网页有时是需要处理手势操作的,比如页面头部位有一个 binner ,是页面的部分需要手势操作而不是页面全部,页面的手势操作需要 webview 能够消费手势事件才行。若是此时 webview 的外部是像 viewpager 这样也需要消费手势事件的话就产生事件冲突了,那么应该怎么做到平衡呢,原则是内层的控件需要时优先吧手势事件给内层控件,内层控件不需要时声明不消费事件,交给上一级处理。 参考这个例子: Viewpager与webview滑动冲突的解决方案 网页提供 js 方法,告知我们页面可滑动元素距屏幕顶部的位置,并调用 JAVA 方法同步我们的代码内,然后在 webview 的 onTouch (view 没有 onInterceptTouchEvent 方法) 方法中获取当前触摸点的距离屏幕左上角的位置,然后和页面中可滑动元素距屏幕左上角的位置做比对,触摸点在页面可滑动元素范围内,webview 就接受事件,若不再那么 webview 就不接受事件, @Override public boolean onTouch(View view, MotionEvent motionEvent) { //获取y轴坐标 float y = motionEvent.getRawY(); switch (motionEvent.getAction()) { case MotionEvent.ACTION_DOWN: getHTMLPosition(); if (null != mPagerDesc) { int top = mPagerDesc.top; int bottom = top + (mPagerDesc.bottom - mPagerDesc.top); //将css像素转换为android设备像素并考虑通知栏高度 top = (int) (top * metric.density) + height bottom = (int) (bottom * metric.density) + height //如果触摸点的坐标在轮播区域内,则由webview来处理事件,否则由viewpager来处理 if (y > top && y < bottom) { webview.requestDisallowInterceptTouchEvent(true); } else { webview.requestDisallowInterceptTouchEvent(false); } } break; case MotionEvent.ACTION_UP: break; case MotionEvent.ACTION_MOVE: break; } 禁止 Viewpager 滑动 平时我们有时是由这个需求的,那么怎么处理 Viewpager 呢,其实看过上面之后,这个问题给为其实可以自己解决的了了。 我们不让 Viewpager 拦截事件,Viewpager 就那不到事件就不能滑动,我们不让 Viewpager 消费事件,那么在 Viewpager 内层的 view 不处理事件时把事件回传给上级的 Viewpager 时,Viewpager 也不会实际产生话滑动,我们把 Viewpager 实际处理事件的代码全部删掉。然后这么写就行 public class CustomViewPager extends ViewPager { @Override public boolean onInterceptTouchEvent(MotionEvent ev) { return false; } @Override public boolean onTouchEvent(MotionEvent ev) { return false; } } 最后说下 我们在处理 view 时,大家要是不想在每次都重写 view.setOnTouchListener 方法,那么就自己定义一个继承 view 的类,然后在构造方法中自己调一下 setOnTouchListener 方法,传自己的 OnTouchListener 对象进去 小例子:view 只处理 x 轴放先发的滑动,y 轴方向的发回给外层容器 xml = 外层容器 public class MyLayout extends FrameLayout { @Override public boolean onInterceptTouchEvent(MotionEvent event) { if( event.getAction() == MotionEvent.ACTION_MOVE ){ Log.d("AAA", " 外层容器_onInterceptTouchEvent: "); return true; } return false; } } 自定义 view public class MyView extends View { public MyView(Context context) { super(context); setOnTouchListener(touchListener); } public MyView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); setOnTouchListener(touchListener); } public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setOnTouchListener(touchListener); } View.OnTouchListener touchListener = new View.OnTouchListener() { int lastX, lastY; int x, y; @Override public boolean onTouch(View v, MotionEvent event) { getParent().requestDisallowInterceptTouchEvent(true); if (event.getAction() == MotionEvent.ACTION_DOWN) { lastX = (int) event.getX(); lastY = (int) event.getY(); } if (event.getAction() == MotionEvent.ACTION_MOVE) { x = (int) event.getX(); y = (int) event.getY(); if (Math.abs(x - lastX) >= Math.abs(y - lastY)) { Log.d("AAA", "内层获取事件,判定方向为 x 轴滑动,处理事件"); getParent().requestDisallowInterceptTouchEvent(true); } else { Log.d("AAA", "内层获取事件,判定方向为 y 轴滑动,事件交给外层容器处理"); getParent().requestDisallowInterceptTouchEvent(false); } } return true; } }; }
作文投稿

被遗弃的竹签一文由杰瑞文章网免费提供,本站为公益性作文网站,此作文为网上收集或网友提供,版权归原作者所有,如果侵犯了您的权益,请及时与我们联系,我们会立即删除!

杰瑞文章网友情提示:请不要直接抄作文用来交作业。你可以学习、借鉴、期待你写出更好的作文。

被遗弃的竹签相关的作文:

    无相关信息

说说你对这篇作文的看法吧