接上篇《android开发艺术探索》读书笔记(二)

No1:

通过MotionEvent对象可以得到点击事件发生的x和y坐标,getX/getY返回的是相对于当前View左上角的x和y坐标,而getRawX/getRawY返回的是相对于手机屏幕左上角的x和y坐标。

No2:

TouchSlop是系统所能识别的被认为是滑动的最小距离,这是一个常量,和设备有关,在不同设备上这个值可能是不同的,通过如下的方式可以获取这个常量

ViewConfiguration.get(getContext()).getScaledTouchSlop();

No3:

VelocityTracker -速度追踪

首先在View的onTouchEvent方法中追踪

VelocityTracker velocityTracker = VelocityTracker.obtain();
velocityTracker.addMovement(event);

采用如下方式来获取当前的速度

velocityTracker.computeCurrentVelocity(1000);
int xVelocity = (int)velocityTracker.getXVelocity();
int yVelocity = (int)velocityTracker.getYVelocity();

这里是指1000ms内手指在水平和竖直方向上滑过的像素

速度=(终点位置-起点位置)/时间段

重置并回收内存

velocityTracker.clear();
velocityTracker.recycle();

No4:

GestureDetector -手势检测

首先需要创建一个GestureDetector对象并实现OnGestrueListener接口

GestureDetector mGestureDetector = new GestureDetector(this);
//解决长按屏幕后无法拖动的现象
mGestureDetector.setIsLongpressEnabled(false);

接着,在待监听View的onTouchEvent方法中添加如下实现

boolean consume = mGestureDetector.onTouchEvent(event);
return consume;

No5:

No6:

如果只是监听滑动相关的,建议自己在onTouchEvent中实现

如果要监听双击这种行为的话,那么就使用GestureDector

No7:

View的scrollTo/scrollBy的滑动过程是瞬间完成的。

Scroller可以实现有过渡效果的滑动,Scroller本身无法让View弹性滑动,它需要和View的computeScroll方法配合才能实现。

Scroller scroller = new Scroller(mContext);

//缓慢滚动到指定位置
private void smoothScrollTo(int destX,int dextY){
int scrollX = getScrollX;
int delta = destX - scrollX;
//1000ms内滑动destX,效果就是慢慢滑动
mScroller.startScroll(scrollX,0,delta,0,1000);
invalidate();
} @Override
public void computeScroll(){
if(mScroller.computeScrollOffset()){
scrollTo(mScroller.getCurrX(),mScroller.getCurrY);
postInvalidate();
}
}

No8:

View的滑动有三种实现方式:

1.通过View本身提供的scrollTo/scrollBy实现滑动

2.通过动画给View施加平移效果来实现滑动

3.通过改变View的LayoutParams使得View重新布局从而实现滑动

No9:

scrollBy实际上也是调用了scrollTo方法,它实现了基于当前位置的相对滑动,而scrollTo则实现了基于所传递参数的绝对滑动。

scrollTo和scrollBy只能将View的内容进行移动,并不能将View本身进行移动。例如:TextView移动的是TextView中的文字,而不是TextView本身

No10:

View的三种滑动方式比较:

scrollTo/scrollBy:操作简单,适合对View内容的滑动

动画:操作简单,主要适用于没有交互的View和实现复杂的动画效果

改变布局参数:操作稍微复杂,适用于有交互的View

No11:

View跟手滑动效果

public boolean onTouchEvent(MotionEvent event){
int x = (int)event.getRawX();
int y = (int)event.getRawY();
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
int deltaX = x - mLastX;
int deltaY = y - mLastY;
int translationX = (int)ViewHelper.getTranslationX(this) + deltaX;
int translationY = (int)ViewHelper.getTranslationY(this) + deltaY;
ViewHelper.setTranslationX(this,translationX);
ViewHelper.setTranslationY(this,translationY);
break;
case MotionEvent.ACTION_UP;
break;
default:
break;
} mLastX = x;
mLastY = y;
return true;
}

No12:

Scroller滑动原理:当View重绘后会在draw方法中调用computeScroll,而computeScroll又会去向Scroller获取当前的scrollX和scrollY;然后通过scrollTo方法实现滑动;接着又调用postInvalidata方法来进行第二次重绘,这一次重绘的过程和第一次重绘一样,还是会导致computeScroll方法被调用;然后继续向Scroller获取scrollX和scrollY,并通过scrollTo方法滑动到新的位置,如此反复,知道整个滑动过程结束。

其中,computeScroll的作用就是计算当前View的滑动位置

No13:

ViewGroup默认不拦截任何事件,Android源码中ViewGroup的onInterceptTouchEvent方法默认返回false,

View没有onInterceptTouchEvent方法,一旦有点击事件传递给它,那么它的onTouchEvent方法就会被调用。

View的onTouchEvent默认都会消耗事件(返回true),除非它是不可点击的(clickable和longClickable同时为false)。

No14:

Window的实现类是PhoneWindow

No15:

如何根据坐标来得到滑动的方向呢?

1.可以依据滑动路径和水平方向所形成的夹角

2.依据水平方向和竖直方向上的距离差来判断

3.依据水平和竖直方向的速度差来做判断

No16:

外部拦截法需要重写父容器的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;
}
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;
}

内部拦截法需要配合requestDisallowInterceptTouchEvent,需要重写子元素的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);
}

推荐外部拦截法

《android开发艺术探索》读书笔记(三)--分发机制和滑动冲突的更多相关文章

  1. Android开发艺术探索读书笔记——01 Activity的生命周期

    http://www.cnblogs.com/csonezp/p/5121142.html 新买了一本书,<Android开发艺术探索>.这本书算是一本进阶书籍,适合有一定安卓开发基础,做 ...

  2. Android开发艺术探索读书笔记——进程间通信

    1. 多进程使用场景 1) 应用某些模块由于特殊需求须要执行在单独进程中. 如消息推送,使消息推送进程与应用进程能单独存活,消息推送进程不会由于应用程序进程crash而受影响. 2) 为加大一个应用可 ...

  3. android开发艺术探索读书笔记之-------view的事件分发机制

    View的点击事件的分发,其实就是对MotionEvent事件的分发过程,即当一个MotionEvent产生后,系统需要把这个事件传递给一个具体的View,而这个过程就是分发过程. 分发过程主要由以下 ...

  4. Android开发艺术探索——第二章:IPC机制(上)

    Android开发艺术探索--第二章:IPC机制(上) 本章主要讲解Android的IPC机制,首先介绍Android中的多进程概念以及多进程开发模式中常见的注意事项,接着介绍Android中的序列化 ...

  5. Android开发艺术探索——第二章:IPC机制(中)

    Android开发艺术探索--第二章:IPC机制(中) 好的,我们继续来了解IPC机制,在上篇我们可能就是把理论的知识写完了,然后现在基本上是可以实战了. 一.Android中的IPC方式 本节我们开 ...

  6. Android开发艺术探索学习笔记(三)

    第三章  View的事件体系 3.1 View基础知识 3.1.1 什么是view View 是Android中所有控件的基类,是一种界面层的控件的一种抽象,它代表了一个控件. 3.1.2 View的 ...

  7. Android开发艺术探索学习笔记(四)

    第四章 View的工作原理 4.1初识ViewRoot和DecorView ViewRoot是连接WindowManager和DecorView的纽带,View的三大流程均是通过ViewRoot来完成 ...

  8. Android开发艺术探索学习笔记(一)

    第一章 Activity的生命周期和启动模式 1.1Activity的生命周期全面解析 1.1.1典型情况下的生命周期分析 (1)在两个Activity进行切换时,当前的Activity的onPaus ...

  9. Android开发艺术探索学习笔记(十一)

    第十一章  Android的线程和线程池 从用途上来说,线程分为子线程和主线程,主线程主要处理和界面相关的事情,而子线程往往用于执行耗时的操作.AsyncTask,IntentService,Hand ...

  10. Android开发艺术探索学习笔记(十)

    第十章  Android的消息机制 面试中经常会被问到的一个问题:handler是如何在子线程和主线程中进行消息的传递的,这个问题通过了解Android的消息机制可以得到一个准确的答案. Androi ...

随机推荐

  1. margin 和 padding 的本质区别

    问题? 如何弄清 margin 和 padding之间的区别? 那,答案呢? margin 边界, padding 填充 假如有一个盒子,padding就相当于盒子的厚度,盒子大小固定,通过修改pad ...

  2. SqlSession 同步为注册,因为同步未激活

    Creating a new SqlSessionSqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7d620db9] ...

  3. webpack + vue

    开始之前 本文包含以下技术,文中尽量给与详细的描述,并且附上参考链接,读者可以深入学习: 1.webpack2.Vue.js3.npm4.ES6语法 前言 在对着产品高举中指怒发心中之愤后,真正能够解 ...

  4. IIS使用十大原则,(IIS过期时间,IIS缓存设置) 【转载】

    1. 自定义错误页虽然自定义错误页很简单,但只有少数管理员有效地利用了它.管理员可以在MMC中将HTTP错误信息映像到服务器上的绝对URL或是某个文件,更为详细的信息可以在这里找到.如果你嫌这太麻烦, ...

  5. UUID.randomUUID().toString()

    UUID.randomUUID().toString()是javaJDK提供的一个自动生成主键的方法.UUID(Universally Unique Identifier)全局唯一标识符,是指在一台机 ...

  6. Python-常用第三方库

    python常用框架及第三方库(转载) 一.Web框架 1.Django: 开源web开发框架,它鼓励快速开发,并遵循MVC设计,比较庞大,开发周期短.Django的文档最完善.市场占有率最高.招聘职 ...

  7. ubuntu下进入root错误解决方法

    1.进入root用户提示su: Authentication failure roots@ubuntu:~$ su - Password: su: Authentication failure 2.通 ...

  8. Android Training Note

    版本适配 Tip:为了能在几个Android版本中都能提供最好的特性和功能,你应该在你的app中使用Android Support Library,它能使你的app能在旧平台上使用最近的几个平台的AP ...

  9. 部署eolinker开源版接口管理

    想找一个API接口管理的软件,为了安全性和扩展性考虑,希望是开源的,而且可以在内网独立部署.网上翻找了资料,经过一份比对之后,最终采用eolinker.过去有使用过RAP,但是感觉界面实在是太丑了. ...

  10. ipcs、ipcrm、sysresv、kernel.shmmax

    ipcs.ipcrm.sysresv.kernel.shmmax 1.1  BLOG文档结构图 1.2  前言部分 1.2.1  导读和注意事项 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可 ...