导航:首页 > 操作系统 > androidui元素

androidui元素

发布时间:2024-07-15 06:02:10

android UI绘制之View绘制的工作原理

这是AndroidUI绘制流程分析的第二篇文章,主要分析界面中View是如何绘制到界面上的具体过程。

ViewRoot 对应于 ViewRootImpl 类,它是连接 WindowManager 和 DecorView 的纽带,View的三大流程均是通过 ViewRoot 来完成的。在 ActivityThread 中,当 Activity 对象被创建完毕后,会将 DecorView 添加到 Window 中,同时会创建 ViewRootImpl 对象,并将 ViewRootImpl 对象和 DecorView 建立关联。

measure 过程决定了 View 的宽/高, Measure 完成以后,可以通过 getMeasuredWidth 和 getMeasuredHeight 方法来获取 View 测量后的宽/高,在几乎所有的情况下,它等同于View的最终的宽/高,但是特殊情况除外。 Layout 过程决定了 View 的四个顶点的坐标和实际的宽/高,完成以后,可以通过 getTop、getBottom、getLeft 和 getRight 来拿到View的四个顶点的位置,可以通过 getWidth 和 getHeight 方法拿到View的最终宽/高。 Draw 过程决定了 View 的显示,只有 draw 方法完成后 View 的内容才能呈现在屏幕上。

DecorView 作为顶级 View ,一般情况下,它内部会包含一个竖直方向的 LinearLayout ,在这个 LinearLayout 里面有上下两个部分,上面是标题栏,下面是内容栏。在Activity中,我们通过 setContentView 所设置的布局文件其实就是被加到内容栏中的,而内容栏id为 content 。可以通过下面方法得到 content:ViewGroup content = findViewById(R.android.id.content) 。通过 content.getChildAt(0) 可以得到设置的 view 。 DecorView 其实是一个 FrameLayout , View 层的事件都先经过 DecorView ,然后才传递给我们的 View 。

MeasureSpec 代表一个32位的int值,高2位代表 SpecMode ,低30位代表 SpecSize , SpecMode 是指测量模式,而 SpecSize 是指在某种测量模式下的规格大小。
SpecMode 有三类,如下所示:

UNSPECIFIED

EXACTLY

AT_MOST

LayoutParams需要和父容器一起才能决定View的MeasureSpec,从而进一步决定View的宽/高。

对于顶级View,即DecorView和普通View来说,MeasureSpec的转换过程略有不同。对于DecorView,其MeasureSpec由窗口的尺寸和其自身的LayoutParams共同确定;

对于普通View,其MeasureSpec由父容器的MeasureSpec和自身的Layoutparams共同决定;

MeasureSpec一旦确定,onMeasure就可以确定View的测量宽/高。

小结一下

当子 View 的宽高采用 wrap_content 时,不管父容器的模式是精确模式还是最大模式,子 View 的模式总是最大模式+父容器的剩余空间。

View 的工作流程主要是指 measure 、 layout 、 draw 三大流程,即测量、布局、绘制。其中 measure 确定 View 的测量宽/高, layout 确定 view 的最终宽/高和四个顶点的位置,而 draw 则将 View 绘制在屏幕上。

measure 过程要分情况,如果只是一个原始的 view ,则通过 measure 方法就完成了其测量过程,如果是一个 ViewGroup ,除了完成自己的测量过程外,还会遍历调用所有子元素的 measure 方法,各个子元素再递归去执行这个流程。

如果是一个原始的 View,那么通过 measure 方法就完成了测量过程,在 measure 方法中会去调用 View 的 onMeasure 方法,View 类里面定义了 onMeasure 方法的默认实现:

先看一下 getSuggestedMinimumWidth 和 getSuggestedMinimumHeight 方法的源码

可以看到, getMinimumWidth 方法获取的是 Drawable 的原始宽度。如果存在原始宽度(即满足 intrinsicWidth > 0),那么直接返回原始宽度即可;如果不存在原始宽度(即不满足 intrinsicWidth > 0),那么就返回 0。

接着看最重要的 getDefaultSize 方法:

如果 specMode 为 MeasureSpec.UNSPECIFIED 即未指定模式,那么返回由方法参数传递过来的尺寸作为 View 的测量宽度和高度;
如果 specMode 不是 MeasureSpec.UNSPECIFIED 即是最大模式或者精确模式,那么返回从 measureSpec 中取出的 specSize 作为 View 测量后的宽度和高度。

看一下刚才的表格:

当 specMode 为 EXACTLY 或者 AT_MOST 时,View 的布局参数为 wrap_content 或者 match_parent 时,给 View 的 specSize 都是 parentSize 。这会比建议的最小宽高要大。这是不符合我们的预期的。因为我们给 View 设置 wrap_content 是希望View的大小刚好可以包裹它的内容。

因此:

如果是一个 ViewGroup,除了完成自己的 measure 过程以外,还会遍历去调用所有子元素的 measure 方法,各个子元素再递归去执行 measure 过程。

ViewGroup 并没有重写 View 的 onMeasure 方法,但是它提供了 measureChildren、measureChild、measureChildWithMargins 这几个方法专门用于测量子元素。

如果是 View 的话,那么在它的 layout 方法中就确定了自身的位置(具体来说是通过 setFrame 方法来设定 View 的四个顶点的位置,即初始化 mLeft , mRight , mTop , mBottom 这四个值), layout 过程就结束了。

如果是 ViewGroup 的话,那么在它的 layout 方法中只是确定了 ViewGroup 自身的位置,要确定子元素的位置,就需要重写 onLayout 方法;在 onLayout 方法中,会调用子元素的 layout 方法,子元素在它的 layout 方法中确定自己的位置,这样一层一层地传递下去完成整个 View 树的 layout 过程。

layout 方法的作用是确定 View 本身的位置,即设定 View 的四个顶点的位置,这样就确定了 View 在父容器中的位置;
onLayout 方法的作用是父容器确定子元素的位置,这个方法在 View 中是空实现,因为 View 没有子元素了,在 ViewGroup 中则进行抽象化,它的子类必须实现这个方法。

1.绘制背景( background.draw(canvas); );
2.绘制自己( onDraw );
3.绘制 children( dispatchDraw(canvas) );
4.绘制装饰( onDrawScrollBars )。

dispatchDraw 方法的调用是在 onDraw 方法之后,也就是说,总是先绘制自己再绘制子 View 。

对于 View 类来说, dispatchDraw 方法是空实现的,对于 ViewGroup 类来说, dispatchDraw 方法是有具体实现的。

通过 dispatchDraw 来传递的。 dispatchDraw 会遍历调用子元素的 draw 方法,如此 draw 事件就一层一层传递了下去。dispatchDraw 在 View 类中是空实现的,在 ViewGroup 类中是真正实现的。

如果一个 View 不需要绘制任何内容,那么就设置这个标记为 true,系统会进行进一步的优化。

当创建的自定义控件继承于 ViewGroup 并且不具备绘制功能时,就可以开启这个标记,便于系统进行后续的优化;当明确知道一个 ViewGroup 需要通过 onDraw 绘制内容时,需要关闭这个标记。

参考:《Android开发艺术探索》

② android镄剈i鏄浠涔堟剰镐濓纻

浠涔堟槸Android UI锛
Android UI鎸囩殑鏄疉ndroid绯荤粺涓镄勭敤鎴风晫闱锛屽嵆鐢ㄦ埛鍦ㄤ娇鐢ˋndroid璁惧囨椂镓鐪嫔埌镄勫悇绉岖晫闱㈠拰浜や簰鏂瑰纺銆侫ndroid UI閲囩敤浜嗕竴绉岖О涓衡淢aterial Design钬濈殑璁捐¢庢牸锛屽叾涓鍖呮嫭浜呜稿氩厓绱犲拰浜や簰鏂瑰纺锛屼緥濡傛寜阍銆佹枃链妗嗐佽彍鍗曘佸脊鍑烘嗙瓑绛夈傚紑鍙戜汉锻桦彲杩愪笡鍜屼互浣跨敤Android鎻愪緵镄𪞝PI鍜屽紑鍙戝伐鍏锋潵鍒涘缓镊宸辩殑鐢ㄦ埛鐣岄溃銆
Android UI镄勭壒镣
Android UI镄勭壒镣规槸澶氭牱鍖栧拰鍙瀹氩埗鍖栥侫ndroid寮鍙戣呭彲浠ヤ娇鐢ㄥ悇绉嶅唴缃缁勪欢鍜岃嚜宸卞垱寤虹殑缁勪欢锛屽垱寤哄嚭钖勭崭笉钖岄庢牸鍜屽舰鐘剁殑鐢ㄦ埛鐣岄溃銆备笌姝ゅ悓镞讹纴寮鍙戣呬篃鍙浠ユ牴鎹镊宸辩殑闇姹备慨鏀圭郴缁熻嚜甯︾殑缁勪欢锛屼互杈惧埌镟村ソ镄勭敤鎴蜂綋楠屻侫ndroid UI杩樻敮鎸佸氱偣瑙︽带鍜屾坠锷胯瘑鍒绛夐珮绾у姛鑳斤纴璁╃敤鎴蜂笌璁惧囩殑浜や簰镟村姞镊铹跺拰鐩磋伞
Android UI镄勯吨瑕佹
Android UI瀵逛簬鐢ㄦ埛浣挞獙闱炲父閲嶈併备竴涓浼樼镄勭敤鎴风晫闱㈠彲浠ユ彁鍗囩敤鎴峰瑰簲鐢ㄧ殑锽灭埍搴﹀拰浣跨敤浣挞獙锛岃屼竴涓绯熺硶镄勭晫闱㈠垯浼氲╃敤鎴锋劅鍒颁笉阃傜敋镊虫斁寮冧娇鐢ㄣ傚洜姝ら儜鍜岋纴寮鍙戜汉锻橀渶瑕佽姳璐瑰ぇ閲忕殑镞堕棿鍜岀簿锷涙潵涓鸿嚜宸辩殑搴旂敤璁捐″嚭浼橀泤镄勭敤鎴风晫闱㈠拰娴佺晠镄勭敤鎴蜂綋楠屻傚悓镞讹纴璋锋瓕鍏鍙镐篃榧揿姳鍜屾敮镞佺洴鎸佸紑鍙戣呮瀯寤虹﹀悎Material Design瑙勮寖镄勫簲鐢锛屼娇寰楃敤鎴峰湪浣跨敤Android璁惧囨椂銮峰缑镟村ソ镄勪綋楠屻

③ Android UI设计的基本元素有哪些

移动端的App界面,不论是iOS还是Android ,一般都由四个元素组成,分别是:状态栏(status bar)、导航栏(navigation)、主菜单栏(submenu)、内容区域(content)。

状态栏:主要用于显示信号、运营商、电量等手机状态的区域;
导航栏:主要显示当前界面的名称,包含相应的功能或者页面间的跳转按钮;
主菜单栏:类似于页面的主菜单,提供整个应用的分类内容的快速跳转;
内容区域:展示应用提供的相应内容;

需要注意的一点就是,由于Android在4.0之后移除了实体键而使用屏幕下方的虚拟键,所以,Android将iOS中的主菜单从下方移动到了上方,从而避免误操作虚拟键。

说到这里,就不得不说,虽然android和iOS都是移动端的操作系统,但是他们在UI设计还是存在很大的差异性。这是为什么呢? 其实这基本上都是因为iOS的闭源导致的,由于它的商业化,导致很多设计被申请了专利,Android在很多地方都必须有所不同,说的最多的就是iOS的弹性滚动,其实Android的ScrollView要实现这样的效果,只需要修改一个参数的值即可,但是由于这个效果iOS申请的专利,所以Android就无法使用了。

④ 如何获取Android UI元素

appium android获取元素方式:
1. 1.元素标签(tagname) 通过UI的控件类型ListtextFieldsList=driver.findElements(By.tagName( textfield ));
2. 元素的位置(xpath) 具有一核迹蔽定约束的路径抽州祥象标示, 基于XPath方式改州;
3. 元素的值(name) driver.findElement(By.name( Save )).click();通过元素的文本, 标签, 或者id标示;
4. 元素的IDdriver.findElement(By.id(com.example.android.contactmanager:id/contactNameEditText )).getText();

阅读全文

与androidui元素相关的资料

热点内容
python数字字符串转数字 浏览:657
c程序员可以转互联网吗 浏览:490
深圳交医保用什么app 浏览:461
pdf合并成一张 浏览:670
ie9文件夹怎么查看ftp 浏览:62
唯品会python解密 浏览:852
安卓高拍仪有什么用 浏览:241
同步盘用什么app好 浏览:188
服务器上下载是什么意思 浏览:169
s6怎么接电话加密 浏览:152
电脑的命令指令符打不开怎么办 浏览:535
可编程逻辑器件cpld开发板 浏览:888
加装文件夹图片 浏览:425
27岁程序员offer 浏览:619
中国建筑史梁思成pdf 浏览:198
单片机双核与单核区别 浏览:850
xss攻击需要编译的符号 浏览:140
南京单片机寻址 浏览:897
自制西门子编程电缆 浏览:807
服务器还叫什么名 浏览:712