当一个Activity获得了焦点后,它将被要求去绘制它的layout(也就是那句在onCreate方法里面的setContentView()方法所设置的layout)。android的framework会处理这个绘制的过程,但是这个Activity也必须提供这个将绘制的View的layout层级的根节点信息。
ps:这里需要解释下最后一句话。我们都知道,一个layout文件是一个包含了多个层级的xml文件。里面的各个xml节点信息就代表了一个又一个的layout层级——也就是这里所谓的“layout层级的根节点”。借由xml技术的本身特点,我们可以保证每个层级在layout中的唯一性,如此一来,我们就可以很方便地为我们即将绘制于某layout上的View进行绘制部位定位了。另外学过数据结构的同学应该知道,节点是数据结构“树”中的概念。所以根据这个,我推测,layout的xml文件信息被加载到内存中后,实际上是以一个“树”的形式存在的。
绘制某个View的工作从该View即将绘制的layout根节点开始。framework在这之前会预测量和绘制这个layout“树”。而绘制该layout“树”的工作则会这么做:遍历这个“树”,然后为每个占有了某个未使用区域的View预留出某个已知大小(该大小就是我们常常用到的layout_width和layout_height属性中所包含的信息)的区域供以后绘制View时使用。之后,各个ViewGroup会依次请求将它们的子View被绘制(通过ViewGoroup的draw方法),而每个View在被绘制的时候又会调用它自身的onDraw方法来把自身绘制出来。因为layout“树”是按顺序遍历的,这就意味着父View(例如ViewGroup)会在子View之前被绘制。
tips:framework不会绘制那些不在未使用区域的View,而且它会为View绘制背景。你可以强制性的去让一个View被绘制——通过利用invalidate()方法。
ps:绘制一个完整的layout的步骤大致如下:1、将layout.xml文件解析至内存,让这些layout信息以一个“树”的形式存在。2、framework遍历该“树”,从上到下依次绘制View。3、绘制View时,会在未使用的区域为即将绘制的该View预留空间,接着调用该View的draw方法来绘制它。
绘制一个layout包含了两大过程:一个是尺寸测试过程。该过程中会在layout“树”里自顶向下地对每个View进行尺寸测量。尺寸测量的工作由View类的measure(int, int)方法进行实现。在"树"遍历的工程中,每个View会调用该方法,然后通过读取一些开发者设定的信息(layout_height layout_width)来保存自己的尺寸信息。当尺寸测试过程进入尾声时,每一个View都已经保存了它的尺寸信息了。另一个过程就是具体的绘制了。在这个自顶向下遍历树的绘制过程中,每个父View会调用layout(int,
int, int, int)方法,并结合子View在尺寸测量过程中所保存的尺寸信息,来安放该子View在自己内部的位置。
当一个View的measure方法返回时,它的width和height——以及它的子View的——属性必须已经被设定完毕。一个View的width和height必须遵从它的父View的相关尺寸约束——这样就保证了在尺寸测试过程尾声时,所有的父View都能够顺利的接受它们的子View。一个父View可能会在其子View上多次调用measure方法。例如,父View可能会先调用它的子View的measure方法来得知它们究竟多大,进而好为它们预留绘制空间,然后父View有接着会又调用measure来测试是否该尺寸适合该View。
tips:通过调用requestLayout()可以初始化一个layout的相关信息。这个方法通常是View在发觉自己的当前所处范围不适合自己的当前情况时被主动调用。
在尺寸测试过程中,有两个类比较重要。一个是View.MeasureSpec。它被View用来告诉它的父View自己想要是多大以及如何地被放置。另一个是我们已经很熟悉的LayoutParams,它仅仅描述了这个View的height和width的信息。对于height和width,可以被如下指定:
1、一个确切的像素值
2、FILL_PARENT,这个意味着该height 或width和父View的相同(减去padding的像素值)。
3、WRAP_CONTENT,这个意味着该View的height和width以刚好包含其内容为准。
各个ViewGroup有自己相应的LayoutParams子类来实现各自个性化的设置需求。例如RelativeLayout有它自己的LayoutParams子类来设定其子View的相对位置。
MeasureSpecs被用来将父View的需求传递给子View。它可以被设置为以下三种模式之一:
-
UNSPECIFIED,父View对子View的尺寸大小没有特殊要求。
-
EXACTLY,父View需要把子View设置为某个特定的像素值。子View必须为这个值,而且要保证它的所有子View也在这个尺寸之内绘制。
-
AT_MOST,告诉子View一个最小的尺寸值。
分享到:
相关推荐
15.1.2 绘制优化 / 493 15.1.3 内存泄露优化 / 493 15.1.4 响应速度优化和ANR日志分析 / 496 15.1.5 List View和Bitmap优化 / 501 15.1.6 线程优化 / 501 15.1.7 一些性能优化建议 / 501 15.2 内存泄露...
----------------------------------- Android 编程基础 1 封面----------------------------------- Android 编程基础 2 开放手机联盟 --Open --Open --Open --Open Handset Handset Handset Handset Alliance ...
/ 484 14.4 JNI调用Java方法的流程 / 486 第15章 Android性能优化 / 489 15.1 Android的性能优化方法 / 490 15.1.1 布局优化 / 490 15.1.2 绘制优化 / 493 15.1.3 内存泄露优化 / 493 15.1.4 响应速度优化和...
通过 JNI 捆绑的 GIFLib 用于渲染帧。 这种方式应该比 WebView 或 ... 如果给定的 drawable 不是 GIF,那么提到的 Views 就像普通的 ImageView 和 ImageButton。 GifTextView 允许您将 GIF 用作复合可绘制对象和背景。
com .docentTSR.xFallView.views.XFallView android : id = " @+id/x_fall_view " android : layout_width = " match_parent " android : layout_height = " match_parent " app : viewsCount = " 80 " app : ...
同时增加了一些其他支持,并修复了一些bug,提升绘制速度。 Based on , add support to custom layout in CoverFlow, fix some bugs, add other function. GIF预览: 主要功能介绍 支持自定义布局。 支持多种view...
:index_pointing_up: 虽然上述库建立在普通的Android Views之上,而Android Views的历史可以追溯到Android的第一个发行版,但是Jetpack Compose仅使用画布和文本工具来绘制小部件。 :thinking_face: 因此,我是否...
拿到这个需求,首先想到的是自定义一个ImageView来实现此功能,即在onDraw()中绘制圆弧和文字。同时因为要保证圆弧的位置可以任意摆放,圆弧的颜色、透明度以及文字大小、颜色等都是可控的,所以增加了一些自定义...
一个库,可帮助在Android中创建形状的视图和布局 如果您可以编写表示所需形状的路径,则可以使用ViewShaper裁剪路径后的任何View并绘制阴影。 当所需形状比圆形或正方形复杂并且您无法创建XML形状用作View背景时,...
onDraw中根据坐标进行绘制。 计算出手指位置与控制盘中心的距离等信息,通过listener传递出去。代码示例样式设定有固定和浮动这两种风格,未来可能还会添加public enum PadStyle { FLOATING /* 随用户手指...
SnappingSeekBar 这是一个示例应用程序,其中包含我对捕捉搜索栏的实现。... com .tobishiba.SnappingSeekBarSample.views.SnappingSeekBar android : layout_width = " match_parent " android
Customize views with canvas. 是一个贝塞尔曲线效果的加载过渡动画。使用canvas绘制的自定义view。 View/效果 import/引入 project's build.gradle (工程下的 build.gradle) allprojects { repositories { ... ...