面试自定义控件回答点

相信大家在面试的时候经常会遇到自定义view相关的面试题,下面我给大家说一下回答的思路。
1、首先android的绘制流程,在activity创建的时候,ActivityThread会调用handleResumeActivity,此时DecorView会和ViewRootImpl会相关联,并把ViewRootImpl设置为DecorView的父类,View的绘制是从ProformTraverslas开始的。
2、接着就可以分析常见的三个方法 measure layout draw
3、如果有事件相关的要求的重写onTouchEvent方法 同时可以扩展回答事件拦截。
4、可以着扩展viewDragHalper 和gesturepractice 的区别以及用法
5、可以扩展到android 双缓存屏幕刷新机制,以及绘制卡顿等问题。
能回答到上面5点基本自定义view算完事。

下面我来一点点的分析
1、ActivityThread会收到内部类IApplicationThread发送的一个创建Activity的消息(AMS是如何给IApplicationThread发消息的这属于IBinder相关知识了),这个方法名为handleLancherActivity,在这个方法里面主要是顺序的调用Activity的生命周期了。performLancherActivity(用于activity的创建)、handleResumeActivity(用于绘制相关的是接下来主要分析的方法),performPauseActivityIfNeed(activity不可见时调用)
手撕一下performLancherActivity。如下图
在这里插入图片描述
2、接下来说onmeasure onlayout ondraw
onmeasure主要主要是测量控件的大小,详细说一下测量模式,在重写onMesurce的时候主要有两个参数widthMeasurceSpace 和heightMeasurceSpace,两个差不多,这里说一下widthMeasurceSpace。
widthMeasurceSapce 是一个32位的int值,前两位表示的是宽高的模式,分别有三种exactly(准确的)acmost(至少)和unspecified(未确认的),后面的30位标识具体的期望值。
widthMeasurceSapce 是由父类传递过来的,具体计算规则
1、如果父控件值确定宽度,子控件也确定宽度,那么MeasurceSapce 的mode 是exactly size是子控件的大小。
2、如果父控件确定宽度,子控件是match_parent,那么
MeasurceSapce的mode 是exactly size是父控件的大小。
3、如果控件确定宽度,子控件是wrap_content,那么MeasurceSapce的mode 是at_most size小于父控件size。

4、父控件是at_most,子控件确定宽度,那么measurceSapce的mode 是exactly size是子控件大小。
5、父控件是at_most,子控件为wrap_content,那么measurceSpace的mode at_most size是包含自己的内容的size
6、父控件是at_most,子控件是match_parent,mode是at_most size是父控件size。

7、父控件是未指定的,子控件是指定的 mode是exactly size是0.
8、父控件是未指定的,子控件是wrap_content 或是match_parent mode是未指定 size是0。
最后调用setMeasureDimension将测量的数据保存下来。
onlayout 主要是ViewGroup调用了根据自己的规则来放自View的位置。
ondraw ondraw方法里面会获取一个canvas,我可以用这个canvas来画我们想画的东西,例如矩形 椭圆 弧线 bitmap text等,也可以位画笔添加颜色风格等。可用通过requestLayout 来重新测量和布局,invalidate来重新绘制。

下来说一下事件的传递机制,在自动控件中也会用到这方面的相关知识,何时让父view响应事件何时子控件响应事件。
主要注意三个方法 dispathTouchEvent、onInterceptTouchEvent,和onTouchEvent,其中view控件是没有onInterceptTouchevent方法的。

ViewGroup 的dispathTouchEvent主要分为三步
1、是否拦截事件。
2、调用dispatchTransformedTouchEvent 递归dispathTouchEvent分发事件。
3、根据mFristTouchTarget,重新分发事件。

是否拦截事件 会根据down事件和mFristTouchTarget!= null来判断是否调用拦截相关的逻辑,所以down事件一定会走onInterceptTouchevent相关方法,或者有子view获取了Touch事件mFristTouchTarget不为null也会走相关拦截逻辑。

遍历ViewGroup中的所有子view,找到触摸点和view一致的view,调用子View的disPathTouchEvent方法,在这里面会先判断TouchListener有没有消耗事件,如果没有则会调用onTouchEvent方法返回true,则会将此View赋值给ViewGroup的mFristTouchTarget对象,并记录事件已经下发。

mFristTouchTarget 对mFristTouchTarget进行判断,如果为空则直接调用viewGroup自己的onToucheEvent方法。如果不为空但是父控件拦截了事件,则会下发cancel事件。(例如ScrollView里面添加一个子view,当我们触摸子View的时候事件能够正常传递到子view,但是当滑动的时候会触发ScrollView控件的拦截事件,scrollview收到事件,上一个子view只能收到一个cancel事件)

mFristTouchTarget 是一个链表,每一个手指的down都可以被记录成一个TouchTarget

requestDisallowInterceptTouchEvent(true) 要求父控件不拦截事件。

viewDragHalper 和gesturepractice 只是对onTouchEvent进行封装,帮助开发者更快更简单的处理拖拽事件(ViewDragHalper)和手势处理事件(gesturepractice)。

屏幕刷新机制可以参考https://juejin.im/post/5d837cd1e51d4561cb5ddf66

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值