android-基础知识-布局

本文详细介绍了Android的七大布局,重点讲解了LinearLayout的weight属性和ConstraintLayout的使用,包括相对定位属性、角度定位、尺寸约束等。同时讨论了UI布局优化,如减少嵌套、避免过度绘制,并介绍了UI布局适配方法,特别是smallestWidth限定符的优势。

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

android-基础知识-布局

一.七大布局

七大布局分别为:线性布局(LInearLayout)、相对布局(RelativeLayout)、帧布局(FrameLayout)、表格布局(TableLayout)、绝对布局(absoluteLayout)、网格布局(GridLayout)、约束布局(ConstraintLayout)

1.相似属性之间的区别:
  1. gravity的 start 和left的区别:

        left是绝对的左边,start会根据不同的国家习惯改变。

        比如在从右向左顺序阅读的国家,start代表的就是在右边
  2. fill_parent 和 match_parent:

        Android2.2中match_parent和fill_parent是一个意思两个参数意思一样,match_parent更贴切,于是从2.2开始两个词都可以用。那么如果考虑低版本的使用情况你就需要用fill_parent了

1.LinearLayout:

1.weight 属性分析
  1. 整体思路:
  • 0dp 按整体1 计算比例 如weight分别为1、2、3。那么实际比例为1、2、3
  • wrap_content :先wrap_content 分配大小,然后剩余比例分配,注意:wrap_content 最大占1
  • march_parent: 按占1分配
  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:

简书地址引用:

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加载方式 :

  1. view.inflate:避免调用多次,因为inflate一次后 viewstub就被替换成根布局了,多次调用会报错
  2. 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

有两种启动方式:

  1. 借助Android SDK中的DDMS工具
  2. 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布局适配

  1. dp px 2. .9图片

传统dp适配方式的缺点

  1. android中的dp在渲染前会将dp转为px,计算公式:
  • px = density * dp;
  • density = dpi / 160;
  • px = dp * (dpi / 160);
  1. 屏幕尺寸、分辨率、像素密度(dpi)三者关系

    像素密度dpi=√{(长度像素数^2 + 宽度像素数^2)}/ 屏幕尺寸

    比如:屏幕分辨率为:1920*1080,屏幕尺寸为5吋的话,那么dpi为440。
  2. 代码中过去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 限定符适配呢?

  1. 屏幕分辨率限定符适配是根据屏幕分辨率的,Android设备分辨率一大堆,而且还要考虑虚拟键盘,这样就需要大量的 dimens.xml 文件。因为无论手机屏幕的像素多少,密度多少,90% 的手机的最小宽度都为 360dp,所以采用 smallestWidth 限定符适配只需要少量 dimens.xml 文件即可。
  2. 屏幕分辨率限定符适配采用的是 px 单位,而 smallestWidth 限定符适配采用的单位是 dp 和 sp,dp 和 sp 是google 推荐使用的计量单位。又由于很多应用要求字体大小随系统改变,所以字体单位使用 sp 也更灵活。
  3. 屏幕分辨率限定符适配需要设备分辨率与 values-xx 文件夹完全匹配才能达到适配,而 smallestWidth 限定符适配寻找 dimens.xml 文件的原理是从大往小找,例如设备的最小宽度为 360dp,就会先去找 values-360dp,发现没有则会向下找 values-320dp,如果还是没有才找默认的 values 下的 demens.xml 文件,所以即使没有完全匹配也能达到不错的适配效果。
插件 ScreenMatch

以设计图最小宽度(单位为 dp)作为基准值,生成所有设备对应的 dimens.xml 文件

mipmap文件夹关系:

header 1mipmap-lhdpimipmap-mdpimipmap-hdpimipmap-xhdpimipmap-xxhdpimipmap-xxxhdpi
dpi范围(0-120]dpi(120-160]dpi(160-240]dpi(240-320]dpi(320-480]dpi(480-640]dpi
1dp对应px(luffy)0.7511.5234

当合适的mipmap文件夹中没有对应的图片的时候,会优先往高的找,会优先找最近的

mipmap文件夹图片优先使用规则

当合适的mipmap文件夹中没有对应的图片的时候,会优先往高的找,会优先找最近的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值