View的点击事件

以下总结来自: 柯元旦 <Android内部核析>


View的工作原理    第一章:


View系统定义了从用户输入消息到消息处理的全过程


其中 键盘消息和触屏消息由于各个硬件的不同会导致不同的变量,所以到窗口管理系统之间有一个   消息处理前端  , 通过前端的处理让标识同一行为的不同变量变成统一变量方便Android识别.

接下来,WmS根据窗口的状态判断是哪个窗口在与用户进行交互,并将消息发送到该窗口上. (窗口是由WmS创建的)

对于Android  ,窗口管理系统的主体代码都在WindowManagerService类中.


View系统获得消息后会对消息进行分发,如果任务是一个后台任务,则不会引起界面的变化,如果任务会引起界面的变化,那么View系统则要重新绘制界面.

绘制过程如下:


①:measure    计算该窗口中各个部件的大小  但是并不是的View操作改变前台界面都会引起View的重绘,比如EditText,仅仅是输入文字的话是不会引起View的重绘的.只有当View的大小产生了改变才会引起重绘.

View内部有一个变量进行这一类区分,只有当View的大小引起改变的时候才会measure控件大小.因此,这也是有时候ListView多次调用getView的原因了.


②为所有视图分配位置

View系统本身并不限定视图的位置,FrameWork为了方便提供了几个基本的ViewGroup作为父视图,这些视图内的子视图会按照定义的方式自动获取位置


③把视图绘制到屏幕上

当系统知道了控件大小和位置后就可以绘制到屏幕上了,在绘制的时候系统内部为每一个窗口创建了一个画布(Canvas)对象,并把这个Canvas传递给从根视图到所有的子视图.并且每次传递的时候都会进行一次裁剪.所以从子视图的角度看每次画布都是从0.0开始绘制的


---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


用户消息类型:  按键消息(KeyEvent)  点消息(Pointer)  轨迹球消息(基本不被用到)


1:按键消息



这里要注意一点:当你长按的时候  虽然Repeat会一直增 但是会在第一次和第二次之间有个间隔  之后就不会有间隔了,原因是:CPU速度太快,如果你是按一下,你人为的感知是按了一下但是CPU可能认为你按了多次,这样就会造成你按了一次但是跳跃多次的效果.所以在第一次和第二次直接有一个间隔 (这个间隔是实现在 消息处理前端  的)  后面的则不再有间隔 , 消息处理前端会默认的进行一个LongClick处理,但是有时候我们本身的View也要处理LongClick  这两个是不冲突的

第一个LongClick:生理长按  一般是默认延时0.5s

第二个LongClick,当用户按下的时候首先会判断该View是否Clickable如果是且不是第一个LongClick 则会回调长按的接口实例进行长按的逻辑处理


2:触摸消息



这里有多点触摸等,但是Android并未提供多点触摸的API ,所以如果要用的话只能自己写了



---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

按键消息的派发过程

首先在ViewRoot中有一个InputHanlder对象 ,当底层得到了按键消息后会调用哦刚到分发处理函数 deliverKeyEvent()  该函数分三步

①:mView.dispatchKeyEventPreIme()  这个方法是在输入法获取到之前调用的,所以如果想在输入法之前拦截掉可重载这个方法 

②:接下来把消息发送到输入窗口,若不存在则发到真实视图.

③:调用deliverKeyEventToViewHierarchy() 将消息派发到真正的视图.该步骤又可分为四部

1:判断该消息是否会导致离开触摸模式,一般都是返回false

2:调用mView.dispatchKeyEvent90将消息派发给根视图.对于应用窗口而言.根视图就是PhoneWindow的DecvorView,对于非应用窗口则mView就是任何ViewGroup的一个实现.,比如状态栏,仅仅是一个FrameLayout视图,该函数内部才真正处理了按键消息.回调程序员锁处理的消息代码

        3:如果应用程序中没有处理该消息,则默认会判断该消息是否会引起视图焦点的变化.如果会则进行焦点的切换.  (这点还没搞懂)

        4:最后处理完按键消息,此时应该返回.如果sendDeno为true.即WmS需要客户窗口发送执行完毕的回执.则在返回之前调用一次  finishInputEvent();

总结 调用过程大致如下:

如果窗口存在输入法窗口,则把按键消息交给输入法窗口处理,不过在处理之前程序员可以重载preIme函数截获一些特别的按键消息,
输入法如果没有消耗该消息,则进入View树进行处理,处理完酥油消息后如果WmS要求发送执行完毕回执,则调用finishInputEvent()




下一章:根视图的派发过程  dispatchTouchEvent的派发过程










  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值