LinearHorizontalRecyclerView
来源:互联网 发布:口袋妖怪手办淘宝 编辑:程序博客网 时间:2024/05/29 12:00
最近在学习安卓,找点应用模仿一下界面
LinearHorizontalRecyclerView只是RecyclerView + LinearLayout + Horizontal而已
想要达到的效果是这样的先上图:
大家先看番剧更新这一区域,它是由一个RecyclerView + 水平线性管理器 组成的
现在我们向左滑一点点 假设滑动距离是10 此时手不要放开
这样第一个Item就有部分被遮住了, 然后再向右滑动超过10的距离,
就会发现现在变成ViewPager在滑动了 原因是因为 RV(RecyclerView的简称)已经滑到尽头了 所以事件就被扔给了父元素(ViewPager,VP) 而且以后RV再也捕获收到事件了(除非释放又开始)
这样的结果有时候是我们想要的效果 不过有的时候不是我们想要的
我现在想达到的效果是:"如果一开始RV就是在最左边并且你要向右滑,那么我才允许ViewPager捕获事件" 否则的话请先滑动到最左边 然后再次向右滑 然后对于最右边的情况也是一样
这样可以避免 用户滑动距离太大 或 RV里面的项比较少 而直接切换到下一个Page
于是我们需要重写RV
@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {switch (ev.getAction()) {case MotionEvent.ACTION_DOWN://一开始我们要无条件的请求不要拦截该事件 这样我们才有处理的机会getParent().requestDisallowInterceptTouchEvent(true);mLastX = ev.getX();mLastY = ev.getY();mMoveInited = false;//还没第一次movemParentCanIntercept = false;//父亲不允许拦截我break;case MotionEvent.ACTION_MOVE:float x = ev.getX();float y = ev.getY();if (!mMoveInited) {mMoveInited = true;//标记if (Math.abs(x - mLastX) > Math.abs(y - mLastY)) {//水平移动比较多
<span style="white-space:pre"></span>//判断一下该RV还能不能向左移动boolean canLeft =...
<span style="white-space:pre"></span>//判断一下该RV还能不能向右移动boolean canRight = ...
<span style="white-space:pre"></span>if ((x > mLastX && !canLeft) || (x < mLastX && !canRight)) {//当且仅当我不能向左走而你又要让我向左走(手右滑) 或 相反...getParent().requestDisallowInterceptTouchEvent(false);mParentCanIntercept = true;}} else {//垂直比移动比较多getParent().requestDisallowInterceptTouchEvent(false);mParentCanIntercept = true;}} else {//这里是第二次move及其以后的moveif (mParentCanIntercept)//mParentCanIntercept=true的话只有上面2个来源 都是可以允许父亲拦截我的getParent().requestDisallowInterceptTouchEvent(false);}mLastX = x;mLastY = y;break;}return super.dispatchTouchEvent(ev);}引入了若干个
mLastX 记录上一次的X, mLastY 记录上一次的Y, mMoveInited 用于是否已经过了第一个ACTION_MOVE, mParentCanIntercept用于表示是否该让父元素拦截
然后还有两个临时变量 canLeft 用于表示该RV能不能向左移动 canRight:表示该RV能不能向右移动
整体的判断逻辑还是比较简单的
有一个关键是如何获得
canLeft和canRight, 可以使用LinearLayoutManager的findFirstCompletelyVisibleItemPosition()和findLasttCompletelyVisibleItemPosition()方法
canLeft=((LinearLayoutManager)getLayoutManager()).findFirstCompletelyVisibleItemPosition()>0; 如果第一个元素不是完全可见的 那么就还有向左边走的空间canRight = ((LinearLayoutManager) getLayoutManager()).findLastCompletelyVisibleItemPosition() < getLayoutManager().getItemCount() - 1; 如果最后一个元素不是完全可见的 那么还有向右走的空间这样就OK了上面代码还同时解决了一个问题 就是:当你第一个ACTION_MOVE的时候 如果 做的比较多的是水平的移动 那么你以后只能进行水平移动 如果你做的比较多的是垂直移动 那么你以后只能做垂直移动(其实这个垂直移动很有可能被父元素捕获 从而RV失去事件 不过这一般是我们想要的)否则会出现一个情况就是:你左右滑动你的RV, 手不放, 然后变成上下滑动,手不放 这时候你就会丢失你的触摸事件 因为我们的RV是水平的 不允许上下滑动 所以一旦有上下滑动 就会被父元素捕获 从而导致RV失去事件(意思就是: 即使你从上下滑动再变成水平滑动,RV也不会理你了)
- LinearHorizontalRecyclerView
- CystalReport for VS 2013 中报表的显示问题
- python : import sqlite3 测试代码
- java int和integer的区别
- iOS 判断iphone ipad 系统版本
- PHP之——进制转换系统函数
- LinearHorizontalRecyclerView
- android aidl的调用
- javascript中的数据类型---数字
- 零子数组
- android环境搭建NDk和cdt
- C# 子窗口修改主窗口的控件
- ORACLE 中ROWNUM用法总结
- LeetCode 题解(241) : Palindrome Permutation
- VC编程DLL通知应用程序exe通信(使用自定义消息实现)