android-基础知识-布局
一.七大布局
七大布局分别为:线性布局(LInearLayout)、相对布局(RelativeLayout)、帧布局(FrameLayout)、表格布局(TableLayout)、绝对布局(absoluteLayout)、网格布局(GridLayout)、约束布局(ConstraintLayout)
1.相似属性之间的区别:
- gravity的 start 和left的区别:
left是绝对的左边,start会根据不同的国家习惯改变。
比如在从右向左顺序阅读的国家,start代表的就是在右边 - fill_parent 和 match_parent:
Android2.2中match_parent和fill_parent是一个意思两个参数意思一样,match_parent更贴切,于是从2.2开始两个词都可以用。那么如果考虑低版本的使用情况你就需要用fill_parent了
1.LinearLayout:
1.weight 属性分析
- 整体思路:
- 0dp 按整体1 计算比例 如weight分别为1、2、3。那么实际比例为1、2、3
- wrap_content :先wrap_content 分配大小,然后剩余比例分配,注意:wrap_content 最大占1
- march_parent: 按占1分配
- 实例分析:
(1). LinearLayout 三个布局依次为全为 match_parent weight 1、2、3。结果为2:1:0。
原因:
- step 1:个个都是fill_parent,但是屏幕只有一个啦,那么1 - 3 = - 2 fill_parent
- step 2:依次比例是1/6,2/6,3/6
- step 3:先到先得,先分给one,计算: 1 - 2 * (1/6) = 2/3 fill_parent 接着到two,计算: 1 - 2 * (2/6) = 1/3 fill_parent 最后到three,计算 1 - 2 * (3/6) = 0 fill_parent
- step 4:所以最后的结果是:one占了两份,two占了一份,three什么都木有
(2). LinearLayout 两个布局AB依次为match_parent wrap_content,weight 1、1。结果为1:0。
(3). LinearLayout 两个布局AB依次为wrap_content match_parent,weight 1、1。结果为<=1:1。
- 当wrap_content 占1/3时 剩余空间 1-1/3-1=-1/3。分配空间A 1/2-1/3=1/6。B 1-1/6=5/6 结果AB 1:5
- 当wrap_content 占1时 AB 1:1
-
(4). LinearLayout 两个布局AB依次为wrap_content wrap_content,weight 1、1。结果为1:1。
2.ConstraintLayout:
2.1 介绍
约束布局ConstraintLayout是一个ViewGroup,可以在Api9以上的Android系统使用它,它的出现主要是为了解决布局嵌套过多的问题,以灵活的方式定位和调整小部件。从 Android Studio 2.3 起,官方的模板默认使用 ConstraintLayout。
2.2.为什么要用ConstraintLayout
在开发过程中经常能遇到一些复杂的UI,可能会出现布局嵌套过多的问题,嵌套得越多,设备绘制视图所需的时间和计算功耗也就越多。
- 减少嵌套:上下左右位置可以对齐其他控件的上下左右。
- 有些人考虑到了嵌套布局带来的风险,所以用一个RelativeLayout来装下所有的控件。那么问题来了,既然用RelativeLayout可以解决问题,为什么还要使用ConstraintLayout呢?因为ConstraintLayout使用起来比RelativeLayout更灵活,性能更出色!还有一点就是ConstraintLayout可以按照比例约束控件位置和尺寸,能够更好地适配屏幕大小不同的机型。
2.3. 下面来看看相对定位的常用属性:
layout_constraintLeft_toLeftOf
layout_constraintLeft_toRightOf
layout_constraintRight_toLeftOf
layout_constraintRight_toRightOf
layout_constraintTop_toTopOf
layout_constraintTop_toBottomOf
layout_constraintBottom_toTopOf
layout_constraintBottom_toBottomOf
layout_constraintBaseline_toBaselineOf
layout_constraintStart_toEndOf
layout_constraintStart_toStartOf
layout_constraintEnd_toStartOf
layout_constraintEnd_toEndOf
2.4. 角度定位:
app:layout_constraintCircle="@+id/TextView1"(以谁为中心)
app:layout_constraintCircleAngle=“120”(角度)
app:layout_constraintCircleRadius=“150dp”(中心距离)
2.5 margin
- 在使用margin的时候要注意两点:
- 控件必须在布局里约束一个相对位置
- margin只能大于等于0
2.6 goneMargin
- goneMargin主要用于约束的控件可见性被设置为gone的时候使用的margin值
举个例子:
1.假设TextView2的左边约束在TextView1的右边,并给TextView2设一个app:layout_goneMarginLeft="10dp"
2.这个时候,TextView2左边没有边距
3.这个时候把TextView1的可见性设为gone
4.TextView1消失后,TextView2有一个距离左边10dp的边距。
2.4 尺寸约束
- 使用指定的尺寸
- 使用wrap_content,让控件自己计算大小
当控件的高度或宽度为wrap_content时,可以使用下列属性来控制最大、最小的高度或宽度:
android:minWidth 最小的宽度
android:minHeight 最小的高度
android:maxWidth 最大的宽度
android:maxHeight 最大的高度
注意!当ConstraintLayout为1.1版本以下时,使用这些属性需要加上强制约束,如下所示:
app:constrainedWidth=”true”
app:constrainedHeight=”true” - 使用 0dp (MATCH_CONSTRAINT)
官方不推荐在ConstraintLayout中使用match_parent,可以设置 0dp (MATCH_CONSTRAINT) 配合约束代替match_parent - 宽高比
当宽或高至少有一个尺寸被设置为0dp时,可以通过属性layout_constraintDimensionRatio设置宽高比,举个例子:
<TextView
android:id="@+id/TextView1"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
宽设置为0dp,宽高比设置为1:1,这个时候TextView1是一个正方形
2.5 辅助工具
2.5.1 Optimizer
- 当我们使用 MATCH_CONSTRAINT 时,ConstraintLayout 将对控件进行 2 次测量,ConstraintLayout在1.1中可以通过设置 layout_optimizationLevel 进行优化,可设置的值有:
- none:无优化
- standard:仅优化直接约束和屏障约束(默认)
- direct:优化直接约束
- barrier:优化屏障约束
- chain:优化链约束
- dimensions:优化尺寸测量
-
2.5.2 Barrier
假设有3个控件ABC,C在AB的右边,但是AB的宽是不固定的,这个时候C无论约束在A的右边或者B的右边都不对。当出现这种情况可以用Barrier来解决。Barrier可以在多个控件的一侧建立一个屏障,屏障位置在AB的右边最长边。
这个时候C只要约束在Barrier的右边就可以了,代码如下
TextView
android:id="@+id/TextView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/TextView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@+id/TextView1" />
<android.support.constraint.Barrier
android:id="@+id/barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="right"
app:constraint_referenced_ids="TextView1,TextView2" />
<TextView
android:id="@+id/TextView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toRightOf="@+id/barrier" />
app:barrierDirection为屏障所在的位置,可设置的值有:bottom、end、left、right、start、top
app:constraint_referenced_ids为屏障引用的控件,可设置多个(用“,”隔开)
2.6 Group
Group可以把多个控件归为一组,方便隐藏或显示一组控件
<android.support.constraint.Group
android:id="@+id/group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible"
app:constraint_referenced_ids="TextView1,TextView3" />
2.7 Placeholder
Placeholder指的是占位符。在Placeholder中可使用setContent()设置另一个控件的id,使这个控件移动到占位符的位置。
2.8 Guideline
Guildline像辅助线一样,在预览的时候帮助你完成布局(不会显示在界面上)。
Guildline的主要属性:
android:orientation 垂直vertical,水平horizontal
layout_constraintGuide_begin 开始位置
layout_constraintGuide_end 结束位置
layout_constraintGuide_percent 距离顶部的百分比(orientation =horizontal时则为距离左边)
二.UI布局优化
1.卡顿原因
- 人为在UI线程中做轻微耗时操作,导致UI线程卡顿;
- 布局Layout过于复杂,无法在16ms内完成渲染;
- 同一时间动画执行的次数过多,导致CPU或GPU负载过重;
- View过度绘制,导致某些像素在同一帧时间内被绘制多次,从而使CPU或GPU负载过重;
- View频繁的触发measure、layout,导致measure、layout累计耗时过多及整个View频繁的重新渲染;
- 内存频繁触发GC过多(同一帧中频繁创建内存),导致暂时阻塞渲染操作;
- 冗余资源及逻辑等导致加载和执行缓慢;
- ANR;
2. include merge viewStub
viewStub加载方式 :
- view.inflate:避免调用多次,因为inflate一次后 viewstub就被替换成根布局了,多次调用会报错
- setVisiable:原因会调inflate
建议调用setVisiable方法,源码里面做了第一次visiable时inflate的判断
3.不用设置不必要的背景,避免过度绘制
4.UI优化工具 Layout Inspector,HierarchyViewer
Sdk 25.3.0 以后HierarchyViewer被废弃了,取而代之的是Layout Inspector
功能:检查布局嵌套情况,以及布局边界
5.检测UI卡顿工具 TraceView ,BlockCanary,Lint
5.1 TraceView
有两种启动方式:
- 借助Android SDK中的DDMS工具
- Androidstudio自带的traceview查看(Android profiler)。
profiler可以查看cpu memory network 每个方法的耗时时间等
5.2 Lint
详情链接引用自 https://blog.youkuaiyun.com/luzhenyuxfcy/article/details/79398761
Lint 怎么用
Android studio Analyze ->Inspect Code ->
Lint优化哪些问题
- 遗漏的翻译(没用上的翻译)比如国际化未被翻译的字段值
- 布局性能(以前是 layoutopt工具,可以解决无用布局、嵌套太多、布局太多)
- 未使用到资源
- 不一致的数组大小
- 国际化问题(硬编码)
- 图标的问题(重复的图标,错误的大小)
- 可用性问题(如不指定的文本字段的输入型)
- manifest文件的错误
三.UI布局适配
- dp px 2. .9图片
传统dp适配方式的缺点
- android中的dp在渲染前会将dp转为px,计算公式:
- px = density * dp;
- density = dpi / 160;
- px = dp * (dpi / 160);
- 屏幕尺寸、分辨率、像素密度(dpi)三者关系
像素密度dpi=√{(长度像素数^2 + 宽度像素数^2)}/ 屏幕尺寸
比如:屏幕分辨率为:1920*1080,屏幕尺寸为5吋的话,那么dpi为440。 - 代码中过去density方式:
public int dip2px(float dipValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dipValue * scale + 0.5f);
}
屏幕分辨率限定符与 smallestWidth 限定符适配原理
详细链接(部分引用自 https://www.jianshu.com/p/1302ad5a4b04)
我这里要讲的是使用 swdp限定符,即 smallestWidth(最小宽度) 限定符 来进行适配,使用这种方式只需要少量 dimens.xml 文件即可达到适配,而且根本不用考虑虚拟按键的问题。如果只适配手机,dimens.xml 文件所占的体积只有 100 多 KB,即使加上平板和 TV,也就500多KB,完全可以接收。这种方案已经在自己多个项目中应用过了,经过几十台手机测试过,基本不会出现适配有问题的情况。制作生成对应 dimens.xml 文件插件(后面会讲)的作者也说过他在待过的两家大公司实践过,所以请放心使用。
屏幕分辨率限定符:
屏幕分辨率限定符适配需要在 res 文件夹下创建各种屏幕分辨率对应的 values-xxx 文件夹,生成各种分辨率对应的 dimens.xml 文件。
文件以px 为单位适配
smallestWidth 限定符 适配原理
- smallestWidth 限定符适配原理与屏幕分辨率限定符适配原理一样,系统都是根据限定符去寻找对应的 dimens.xml 文件。例如程序运行在最小宽度为 360dp 的设备上,系统会自动找到对应的 values-sw360dp 文件夹下的 dimens.xml 文件。
- 区别就在于屏幕分辨率限定符适配是拿 px 值等比例缩放,而 smallestWidth 限定符适配是拿 dp 值来等比缩放而已。
- 需要注意的是“最小宽度”是不区分方向的,即无论是宽度还是高度,哪一边小就认为哪一边是“最小宽度”。
为什么选择 smallestWidth 限定符适配?
既然原理都一样,都需要多套 dimens.xml 文件,那为什么要选择 smallestWidth 限定符适配呢?
- 屏幕分辨率限定符适配是根据屏幕分辨率的,Android设备分辨率一大堆,而且还要考虑虚拟键盘,这样就需要大量的 dimens.xml 文件。因为无论手机屏幕的像素多少,密度多少,90% 的手机的最小宽度都为 360dp,所以采用 smallestWidth 限定符适配只需要少量 dimens.xml 文件即可。
- 屏幕分辨率限定符适配采用的是 px 单位,而 smallestWidth 限定符适配采用的单位是 dp 和 sp,dp 和 sp 是google 推荐使用的计量单位。又由于很多应用要求字体大小随系统改变,所以字体单位使用 sp 也更灵活。
- 屏幕分辨率限定符适配需要设备分辨率与 values-xx 文件夹完全匹配才能达到适配,而 smallestWidth 限定符适配寻找 dimens.xml 文件的原理是从大往小找,例如设备的最小宽度为 360dp,就会先去找 values-360dp,发现没有则会向下找 values-320dp,如果还是没有才找默认的 values 下的 demens.xml 文件,所以即使没有完全匹配也能达到不错的适配效果。
插件 ScreenMatch
以设计图最小宽度(单位为 dp)作为基准值,生成所有设备对应的 dimens.xml 文件
mipmap文件夹关系:
header 1 | mipmap-lhdpi | mipmap-mdpi | mipmap-hdpi | mipmap-xhdpi | mipmap-xxhdpi | mipmap-xxxhdpi |
---|---|---|---|---|---|---|
dpi范围 | (0-120]dpi | (120-160]dpi | (160-240]dpi | (240-320]dpi | (320-480]dpi | (480-640]dpi |
1dp对应px(luffy) | 0.75 | 1 | 1.5 | 2 | 3 | 4 |
当合适的mipmap文件夹中没有对应的图片的时候,会优先往高的找,会优先找最近的
mipmap文件夹图片优先使用规则
当合适的mipmap文件夹中没有对应的图片的时候,会优先往高的找,会优先找最近的