ScrollLayout ScrollTo ScrollBy 事件传递

ScrollTo、ScrollBy说明

ScrollTo和ScrollBy滑动的是该View的显示内容(子View),并不改变该View的坐标
ScrollTo:它是滑动到指定位置
ScrollBy:它是基于当前位置的相对滑动(内部最终也会调用ScrollTo)

注意
x和y不是坐标点,是偏移量,坐标系:左正上正

演示

如果事件传递不是太清楚的同学可以先看这两篇博客
Android事件传递机制详解
super.dispatchTouchEvent(event)使用

ScrollLayout的dispatchTouchEvent各个事件

DOWN事件

case MotionEvent.ACTION_DOWN:dX = eX;lastY = dY = eY;isMoveValid = false;isEventValid = true;//首次进入getScrollY为0,当eY点击区域在offsetY距离下边,则进入//当点击距离在offsetY上边则进入elseif (getScrollY() + eY > offsetY) {//当动画正在执行时,事件不往View中传递if (!(factor == 0 || factor == 1)) {isEventValid = false;} else {//当子View为非滑动事件如TextView,LinearLayoutd等会调用它们的onTouchEvent的所有事件//当子View为滑动事件如ListView,RecyclerView等不会调用onTouchEvent的Down事件,而是从Move事件开始调用子Viewsuper.dispatchTouchEvent(ev);}return true;}return false;

代码上都已经注释很清楚了,如果点击到子View上则进入if语句内,否则返回false,不处理事件

MOVE事件

case MotionEvent.ACTION_MOVE://当动画正在执行时,点击滑动不起作用if (!isEventValid) return false;//下滑offset就是负数,上滑就是正数int offset = (int) (lastY - eY);lastY = eY;//当展开时,继续上滑则RecyclerView获取滑动事件,super.dispatchTouchEvent(ev)返回true//当展开时,下滑时则RecyclerView不处理滑动事件,super.dispatchTouchEvent(ev)返回false//当关闭时,上滑时TextView不处理滑动事件,super.dispatchTouchEvent(ev)返回falseif ((status == STATUS_EXTEND|| status == STATUS_CLOSE)&& super.dispatchTouchEvent(ev)) {return true;}if (!isMoveValid&& Math.abs(eY - dY) > touchSlop&& Math.abs(eY - dY) > Math.abs(eX - dX)) {isMoveValid = true;}if (isMoveValid) {//滑动的距离已经小于底部关闭的距离时,直接scrollTo到关闭距离if (getScrollY() + offset <= offsetClose) {scrollTo(0, offsetClose);status = STATUS_CLOSE;if (listener != null) {listener.onScrollChange(status);}//滑动距离大于展开距离时,直接scrollTo到展开距离} else if (getScrollY() + offset >= offsetExtend) {scrollTo(0, offsetExtend);status = STATUS_EXTEND;setRecyclerViewLastY(true);if (listener != null) {listener.onScrollChange(status);}} else {//偏移量坐标  左正上正//跟随手指慢慢移动,scrollBy(0, offset);if (listener != null) {if (getScrollY() > offsetB) {listener.onScrollProgress(255 * getScrollY() / offsetY);} else {listener.onScrollProgress(0);}listener.onScrollChange(STATUS_ING);}}}return true;

在Move事件里,主要就是事件的传递和拦截,通过scrollBy实现子View跟随手指移动,通过scrollTo实现到达指定位置。通过onScrollChange实现底部TextView的显隐,通过onScrollProgress实现背景色、标题栏的颜色渐变

CANCEL、UP事件

case MotionEvent.ACTION_CANCEL:case MotionEvent.ACTION_UP://当动画正在执行时,点击滑动不起作用if (!isEventValid)return false;if (isMoveValid&& getScrollY() > offsetClose&& getScrollY() < offsetExtend) {//通过动画的方式,实现子View到达指定位置    dealUp(getScrollY());isMoveValid = false;return true;}setRecyclerViewLastY(status);break;

在CANCEL、UP事件里,如果没有直接滑动到关闭、展开的位置,则通过dealUp方法以动画的方式把子View滚动到关闭、展开的位置,如果手机滑动到了关闭、展开的位置,则直接返回super.dispatchTouchEvent(ev)

属性动画滚动子View

animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {factor = (float) animation.getAnimatedValue();//这里打印会先打印出:1,然后再从0-1打印,因为每次在start时,都会先调用stopLogUtils.i("liuyzz--onAnimation--:", "" + factor);//curY可为负数或正数float scrollY = curY + (finalY - curY) * factor;scrollTo(0, (int) scrollY);postInvalidate();if (listener != null) {listener.onScrollChange(STATUS_ING);//大于设置的展开距离后才设置颜色渐变if (getScrollY() > offsetB) {listener.onScrollProgress(255 * getScrollY() / offsetY);} else {listener.onScrollProgress(0);}}}});

通过onAnimationUpdate更新子View的位置并设置背景色、标题栏的颜色渐变

ScrollRecyclerView的dispatchTouchEvent各个事件

DOWN事件

case MotionEvent.ACTION_DOWN:LogUtils.i("liuyzz:recyclerview:", "---down");lastY = eY;canScroll = true;super.onTouchEvent(e);return true;

因为是滚动列表,所以父View的dispatchTouchEvent不会调用ScrollRecyclerView的Down事件,而是从Move事件开始调用

MOVE事件

case MotionEvent.ACTION_MOVE:if (!canScroll) {return false;}//下滑负  上滑正int offset = (int) (lastY - eY);lastY = eY;LogUtils.i("liuyzz:recyclerview:", ""+canScroll+"-isTop:"+isTop()+"-offset:"+offset);canScroll = !isTop() || offset > 0;super.onTouchEvent(e);//如果不写,ScrollRecyclerView就不能滑动return canScroll;   

在Down事件中,通过isTop和offset确定move事件是否处理事件

isTop方法

private boolean isTop() {LayoutManager manager = getLayoutManager();if (manager == null|| !(manager instanceof LinearLayoutManager)) {return false;}//显示区域最上面一条信息的positionint visibleItemPosition = ((LinearLayoutManager) manager).findFirstVisibleItemPosition();View childView = getChildAt(0);//getChildAt(0)只能获得当前能看到的item的第一个LogUtils.i("liuyzz:recyclerview:", "position:"+visibleItemPosition+"-top:"+childView.getTop());//坐标系 下正右正return childView != null && visibleItemPosition <= 0 && childView.getTop() >= 0;
}

CANCEL、UP事件

case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:canScroll = true;super.onTouchEvent(e);return true;

在CANCEL、UP事件中,只是重置状态

ScrollTextView的dispatchTouchEvent各个事件

DOWN事件

case MotionEvent.ACTION_DOWN:dX = eX;dY = eY;isClickValid = true;return true;

MOVE事件

case MotionEvent.ACTION_MOVE:if (isClickValid&& (Math.abs(eY - dY) > touchSlop|| Math.abs(eY - dY) > Math.abs(eX - dX))) {isClickValid = false;}return isClickValid;

在Move事件中,如果是滑动事件,则置isClickValid为false,自己不处理事件,事件会上传到ScrollLayout处理,如果不是滑动事件,则处理事件

UP事件

case MotionEvent.ACTION_CANCEL://这里的目的是模拟一个点击事件if (isClickValid && listener != null) {listener.onClick(this);}return isClickValid;

在Up事件中,如果Move中不处理事件(isClickValid=false),则在Up中也不处理事件,如果Move中处理了事件,则在Up中也处理事件,并且也模拟了一个TextView的点击事件

注意
如果重写了某View的onTouchEvent方法,则该View的onClickListener就会失效

总结
代码才是最好的老师,如果您刚开始没有思路,那么看上面这些代码估计也看的云里雾里,因为这些代码只便于有思路而不知具体实现或在某个地方不是太清楚的复习使用。如果您想理清全部逻辑,还请您下载源码,慢慢嚼咽

源码下载

Demo下载

仿百度地图抽屉拖拽效果相关推荐

  1. Android实现高德地图上拉,ScrollLayout:上拉滑动上滑拖出,类似高德地图百度地图抽屉拖拽效果...

    摘要 在ScrollView或者ListView里面使用ViewPager.支持手势上拉滑出,中途停顿,下滑退出页面,类似高德地图百度地图内场景抽屉拖拽效果效果 Gif动画 类似使用 Demo 下载A ...

  2. vuedraggable能实现自由拖拽功能吗?_基于 vue.js 仿禅道主页拖拽效果

    今天给大家分享一个超不错的Vue仿禅道首页拖拽布局VueDndKon. vue-dnd-kon 基于vuedraggable实现的仿禅道首页拖拽项目.支持模块上下及左右自由拖动布局. 主页分为左右两栏 ...

  3. 仿QQ消息气泡拖拽效果

    此次的自定义View是仿qq消息列表,消息气泡拖拽效果. 1.原理介绍:自定义view,绘制原始点圆,touch点圆,然后将两圆用贝塞尔曲线连接并填充. 2.应用WindowManager,将自定义v ...

  4. Android 仿QQ 聊天消息拖拽效果

    可拖拽的气泡效果 自定义view WateView public class WateView extends FrameLayout {//定义一个文本控件private TextView text ...

  5. 不一样的 9 宫格图片展示,仿 Nice 首页图片列表 9 图样式,并实现拖拽效果

    ImageNice9Layout 项目地址:wobiancao/ImageNice9Layout  简介:不一样的 9 宫格图片展示,仿 Nice 首页图片列表 9 图样式,并实现拖拽效果 写在开头: ...

  6. android气泡聊天消息背景,Android使用贝塞尔曲线仿QQ聊天消息气泡拖拽效果

    本文实例为大家分享了Android仿QQ聊天消息气泡拖拽效果展示的具体代码,供大家参考,具体内容如下 先画圆,都会吧.代码如下: public class Bezier extends View { ...

  7. DOM 案例——(美团外卖下拉框菜单、半透明——信息滑入、模态窗口拖拽效果、放大镜效果、滚动条滑到一定位置的固定导航栏、12306购票网站多级联动、斗鱼TV无规则弹幕特效、百度搜索条动态输入下拉瀑布)

    目录 1.缓动动画--美团外卖下拉框菜单 2.半透明--信息滑入 3.模态窗口拖拽效果 4.放大镜效果 5.滚动条滑到一定位置的固定导航栏 6.12306购票网站多级联动 7.斗鱼TV无规则弹幕特效 ...

  8. Android仿QQ消息拖拽效果(二)

    前言 本文参考辉哥贝塞尔曲线 - QQ消息汽包拖拽,前面我们使用二阶贝塞尔曲线绘制了拖拽圆点效果Android仿QQ消息拖拽效果(一)(二阶贝塞尔曲线使用),这里我们在此基础之上实现仿QQ消息拖拽爆炸 ...

  9. 微信小程序之『仿 QQ 消息气泡拖拽消失』

    转载:请写明掘金原文链接及作者名 '小小小' 一个潜心研究小程序QQ群:139128168 ← 点击加群 今天带来的是仿QQ消息气泡拖拽消失特效,源码中很多地方还是有很多不足,希望大家一起齐心协力,给 ...

最新文章

  1. 边缘计算+SDN:为物联网腾飞插上翅膀
  2. Linux基础命令使用
  3. 你应该知道的 MongoDB 最佳实践
  4. DS1819 对应版本的FFMPEG_Qt音视频开发33-ffmpeg安卓版
  5. python英文高频句统计_使用Python 统计高频字数的方法
  6. urllib2设置代理
  7. 当我们在谈论HTTP缓存时我们在谈论什么
  8. 学会做“男人”—Linux Man的使用技巧
  9. pandas输出csv某一列的数据
  10. html跑马灯_用Excel居然能做“跑马灯”,而且还这么简单!
  11. Advanced+Apple+Debugging(2)
  12. Linux 下,系统时间毫秒级命名文件
  13. 除系统分区外未找到其它非系统分区导致软件无法运行解决方案
  14. Cache之直接映射
  15. 爬虫学习笔记(一)初识爬虫
  16. css中的background的几个属性(background-attachment/background-origin,background-clip等)
  17. Vijos1982 NOIP2015Day2T2 子串 substring 动态规划
  18. 360搜索引擎能否给苦逼的站长们带来希望?
  19. Ubuntu安装语言包
  20. 计算机声音管理器不见了,电脑Realtek高清晰音频管理器不见了怎么办

热门文章

  1. 当CV工程师碰到了拷贝粘贴的需求——useClipboard的使用及源码解析
  2. nmap把端口定义为六种状态的解读
  3. JavaEE项目实战(OA系统)之十八_流程审批之一
  4. 服务器安全与网络安全监测
  5. DAEMON Tools for mac 虚拟光驱 中文破解版下载
  6. 颜值即正义,献礼就业季,打造多颜色多字体双飞翼布局技术简历模版(Resume)
  7. 你永远别想吃垮一家自助餐厅
  8. 9277计算机音乐,抖音9277伴奏深七演唱的歌曲完整版分享_9277背景音乐mp3原声版...
  9. dedecms 模板引用php文件名,织梦DEDECMS模板文件名介绍与说明
  10. 使用BT下载是否会损毁SSD?