【ConstrainLayout】ConstrainLayout布局的一些实用属性、实现UI百分比适配

3,085 阅读5分钟

ConstrainLayout 比起其他布局的优势

  1. 减少布局嵌套, 加快渲染速度。

  2. 可视化编辑 。

  3. 提供百分比的属性 ,可以方便的实现UI百分比适配。

  4. 比起RelativeLayout更加灵活,有着更强大的约束属性,可以实现各种效果。

ConstrainLayout 布局用的实用属性

更强大的"LinearLayout"

chain

image-20210923221720855

如图所示 第一个前面约束父布局,后面约束第二个。第二个前面约束第一个,后面约束第三个。第三个前面约第二个,后面约束父布局。即可生成一条水平的chain(垂直的chain上下约束即可),

在chain的第一个可以设置app:layout_constraintHorizontal_chainStyle="xxx" 默认spread

  1. spread:平均分剩余的空间作为间隔(包括第一个和最后一个)

image-20210923221720855

  1. spread_inside:平均分剩余的空间作为间隔

    image-20210923221805057

  2. packed:将各个元素合并在一起

    image-20210923221819962

weight

如果使用这两个属性 还支持app:layout_constraintVertical_weight="xxx" 效果类似LinearLayout的weight 分配设置的权重空间给该元素。同时需要把宽度或者高度设置成0dp(MATCH_CONSTRAINT)才能生效

如图 是将weight 分别设置成 1 2 3 的效果

image-20210923221504957

多个元素整体居中于某个元素

我们只需用将上面提到的chain,把几个元素连成一条链,然后将第一个的start约束到目标元素的start,最后一个的end约束到目标元素的end即可。

image-20210923222245877

bias

当元素左右或者上下有了约束后 可以使用

app:layout_constraintHorizontal_bias="XXX"app:layout_constraintVertical_bias="XXX"进行偏移量的调整(0~1)

如上图 如果我们想整体左对齐 我们可以设置app:layout_constraintHorizontal_bias="0" 效果如下图

image-20210924102509071

百分比适配的方案

guideline

constraintlayout里面可以使用

<androidx.constraintlayout.widget.Guideline
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"// 可以使用 vertical|horizontal 垂直或者水平的guideline
    app:layout_constraintGuide_percent="0.1"//在父布局里面所在的位置比例 
    />

这是一条垂直于父布局 在水平方向 百分之十的一条guideline

好了 有了这个 我们可以在父布局按比例设置guideline 然后让我们的控件约束于guideline就好了

比如:我们要得到一张宽度占屏幕百分之五十 居中的图片 我们可以分别在百分之二十五和百分之七十五的位置设置guideline 然后左右约束于guideline 然后宽度设置成0dp(MATCH_CONSTRAINT)效果如下

image-20210924104617112

dimensionRatio

我们都知道安卓手机的屏幕尺寸比例有很多种 人过我们单纯用guideline 并不能实现一张宽高1:1的图片

但是我们可以使用app:layout_constraintDimensionRatio="W:H"来帮我门解决这个问题

该属性是设置我们的控件的长宽比的,使用的前提是至少我们的width和height有一个是0dp。

比如:我们要获得一张1:1的图片 用上面的图片作为例子,我们只需要在上面的上面的基础上加上app:layout_constraintDimensionRatio="1:1"即可。

image-20210924110142547

该属性也可以使用在我们的卡片的布局上面

image-20210924110341222

比如我们要得到这样的卡片

我们可以画左右两条guideline 然后根据设计稿的宽高比设置app:layout_constraintDimensionRatio="W:H"效果如图

image-20210924110636181

width_percent|height_percent

发现我们每次都需要指定两条guideline来确定控件的大小 如果我们布局复杂的话 会导致我们的布局有非常多的guideline

所以我们可以利用app:layout_constraintHeight_percent="XXX"app:layout_constraintWidth_percent="XXX"这两个属性

以上面那个卡片为例子,根据设计图 该图片的宽度是屏幕的0.936 那么我们可以设置app:layout_constraintWidth_percent="0.936 "

这样我们就可以去掉后面的guidline

image-20210924111645698

举例子

image-20210924110341222

首先我们设置guideline

一共设置了5条guideline 这样就可以确定我们的布局的大概位置了

image-20210924113033791
    • 根据设计稿 图片宽度占0.142 所以我们设置app:layout_constraintWidth_percent="0.142"

    • 宽高比1:1 设置app:layout_constraintDimensionRatio="1:1"

    • top和start 约束到两条引导线

    • 两个textview 连成一条垂直的chain,style为packed。
    • top约束1的top ,buttom约束1的buttom,start约束到引导线。
    • 再设置textview间的margin即可。
    • 代码如下。
<TextView
    android:id="@+id/tv_1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="浪琴"
    app:layout_constraintBottom_toTopOf="@id/tv_2"
    app:layout_constraintStart_toStartOf="@id/v_guideline2"
    android:layout_marginBottom="2dp"
    app:layout_constraintTop_toTopOf="@id/image1"
    app:layout_constraintVertical_chainStyle="packed" />

<TextView
    android:id="@+id/tv_2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="近7日更新187件商品"
    app:layout_constraintBottom_toBottomOf="@id/image1"
    app:layout_constraintStart_toStartOf="@id/tv_1"
    app:layout_constraintTop_toBottomOf="@id/tv_1" />
    • 首先我们先把四个图片连成一条chain,style为spread_inside。
    • 其中第一个图片的start约束到引导线,最后一个的end约束到引导线,其他的互相之间进行约束。
    • 根据设计稿 图片宽度占0.165 所以我们设置app:layout_constraintWidth_percent="0.165"
    • 宽高比1:1 设置app:layout_constraintDimensionRatio="1:1"
    • 第一个ImageView的代码如下 其他的类似
    <ImageView
        android:id="@+id/img1"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintDimensionRatio="1:1"
        app:layout_constraintEnd_toStartOf="@id/img2"
        app:layout_constraintHorizontal_chainStyle="spread_inside"
        app:layout_constraintStart_toEndOf="@id/v_guideline2"
        app:layout_constraintTop_toTopOf="@id/h_guideline2"
        app:layout_constraintWidth_percent="0.165" />
    

最后效果如下

image-20210924115536533

其他布局都可以用类似的方法实现等比例布局,但此方案目前还仍有不足

  1. 字体大小无法按比例展示
  2. margin不能按比例设置