自定义控件经验录

本文详细介绍了Android控件的绘制过程,包括测量大小、布局、绘画内容三个阶段,并阐述了自定义控件时需要注意的问题。此外,还介绍了UI的本质及控件绘制的触发时机。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Android 控件的绘画过程?影响绘画的因素有哪些?

Android将控件的绘画过程按照顺序依次分成了几个过程:测量大小,布局,绘画内容。自定义控件时对应的是onMeasure(..),onLayout(..),onDraw(..)。在自定义控件过程中,需要确定控件的位置、大小。影响位置和大小的参数是内外边距跟内容。

UI的本质又是什么?

UI的本质是Window(实现类PhoneWindow)。Activity、Dialog显示的本质都是一个Window。Activity显示的内容就就放在了Window里面。在Window里面有一个DecorView(FrameLayout),我们调用Activity.setContentView()就是将内容放置在DecorView里面。

控件的绘画从什么时候开始的呢?

控件的绘画从Activity打开的时候开始,调用栈是:
1.ActivityThread.handleLaunchActivity(..)
2.ActivityThread.performLaunchActivity(..)
3.ActivityThread.handleResumeActivity(..)
4.ViewManager.updateViewLayout(..)(实现类WindowManagerImpl)
5.ViewRoot.setLayoutParams(..)
6.ViewRoot.scheduleTraversals(..)
7.ViewRoot.performTraversals(..)
...
真正开始执行绘画从ViewRoot(实现类ViewRootImpl)开始。主要的绘画过程都在ViewRootImpl.performTraversals()里:
1.measureHierarchy()调用了performMeasure()方法测量控件,容器会去测量子控件.直到所有控件测量完毕。
2.performLayout(),在这里执行控件的布局,这里同样需要循环调用子控件的布局方法,直到所有控件均布局完毕
3.performDraw() ,这里执行绘画过程,这里同父容器调用dispatchDraw()去绘画子控件。

自定义容器过程中,测量大小(onMeasure(int,int))时应该注意什么?

控件的测量模式有三种,"UNSPECIFIED"、“EXACTLY”、“AT_MOST”。当我们自定义容器大小(onMeasure(..)),我们需要根据测量模式去确定子控件的大小,然后再确定容器的大小。影响子控件的大小的参数有:容器的测量模式和容器的间距、子控件的外间距。如果子控件的测量模式不是"EXACTLY",那么容器给予子控件onMeasure(int,int)的参数值应该=容器测量模式得出的大小-容器内间距-子控件外间距。

自定义容器过程中,布局(onLayout(int,int,int,int))时应该注意什么?

当容器布局的时候,我们需要去确定子控件的位置。子控件的布局位置应该是减去容器内间距,子控件的外间距后的位置。例如容器的左内间距为10px,子控件的左外间距为10px.那么子控件的左位置应该是容器左边位置-容器左内间距-子控件左外间距。注意,布局时候的坐标都是屏幕的绝对坐标。即子控件onLayout方法中传入的坐标不是相对于父容器的坐标。

自定义控件过程中,测量大小(onMeasure(int,int))时应该注意什么?

绘制控件的时候不需要考虑外间距,需要考虑内间距。同样,也要根据测量模式确定控件的大小。当测量模式为AT_MOST的时候,我们要根据控件内容测量控件大小。

自定义控件常用方法

1、Context.getTheme().obtainStyledAttributes(int[]res)
说明:一般在控件构造方法中获取属性值。
2、Layout.getDesiredWidth(CharSequence source, TextPaint paint)
说明:可以获取文字的宽度,包括大小写,回车键等特殊字符都可以通过这个方法获取。
3、Paint.getTextBounds(String text, int start, int end, Rect bounds)
说明:获取文字的高度和位置。
4、ViewGroup.getChildMeasureSpec(int spec, int padding, int childDimension)
说明:根据容器的测量模式、容器的外间距、子控件的内间距、控件的测量模式获取传给子控件测量方法的参数值。注意,padding参数一般是容器的内间距和子控件的外间距之和。
5、ViewGroup.measureChild(View child, int parentWidthMeasureSpec,
int parentHeightMeasureSpec)
说明:测量子控件的大小。调用了ViewGroup.getChildMeasureSpec方法。
6、ViewGroup. measureChildWithMargins(View child,int parentWidthMeasureSpec, int widthUsed,int parentHeightMeasureSpec, int heightUsed)
说明:测量子控件的大小,这里把容器的外间距也算上了。
7、View.requestLayout()。
说明:强制更新整个绘画流程。
8、View.invaildate()
说明:更新绘制区域(不会更新整个绘画流程)。

转载于:https://www.cnblogs.com/zhouztashin/p/8042065.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值