Android屏幕适配终极方案之ConstraintLayout约束布局以及ConstraintLayout百分比布局应用

1.介绍
2.为什么要用ConstraintLayout
3.如何使用ConstraintLayout
3.1 添加依赖
3.2 相对定位
3.3 角度定位
3.4 边距
3.5 偏移
3.6 尺寸约束
3.6.1 使用指定的尺寸
3.6.2使用wrap_content,让控件自己计算大小
3.6.3 使用 0dp (MATCH_CONSTRAINT)设置百分比布局:
3.6.4 宽高比
3.7 链
4.辅助工具
4.1 Optimizer
4.2 Barrier
4.3 Group
4.4 Placeholder
4.5.Guideline
5.综合案例

可视化界面PreView操作请参考:https://blog.csdn.net/guolin_blog/article/details/53122387

注意:1.官方的模板默认使用 ConstraintLayout。
2.ConstraintLayout属性不能在嵌套布局中使用,不能使用match_parent。
3. android:layout_width=“0dp”
android:layout_height=“0dp”
都设置为0dp时,控件大小需要特殊处理,否则不显示。详情见综合案例。
4.constraintlayout,滑动问题还没有很好的解决。可以使用百分比布局。

1.介绍

约束布局ConstraintLayout 是一个ViewGroup,可以在Api9以上的Android系统使用它,它的出现主要是为了解决布局嵌套过多的问题,以灵活的方式定位和调整小部件

2.为什么要用ConstraintLayout

  1. 在开发过程中经常能遇到一些复杂的UI,可能会出现布局嵌套过多的问题,嵌套得越多,设备绘制视图所需的时间和计算功耗也就越多
  2. ConstraintLayout使用起来比RelativeLayout更灵活,性能更出色!
  3. ConstraintLayout可以按照比例约束控件位置和尺寸,能够更好地适配屏幕大小不同的机型。

3.如何使用ConstraintLayout


3.1 配置

1.添加依赖(创建项目时自动添加)
首先我们需要在app/build.gradle文件中添加ConstraintLayout的依赖,如下所示。

 implementation 'com.android.support.constraint:constraint-layout:1.1.3'

2.如果使用app属性需要在ConstraintLayout中添加

 xmlns:app="http://schemas.android.com/apk/res-auto"

3.如果有报错
ConstraintLayout中 xmlns:tools=“http://schemas.android.com/tools
TextView中加上:tools:ignore=“MissingConstraints”(等同下图)
在这里插入图片描述

<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">
    </android.support.constraint.ConstraintLayout>


3.2 相对定位

常用属性:

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


3.3 角度定位

角度定位指的是可以用一个角度和一个距离来约束两个空间的中心。举个例子:

   <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_constraintCircle="@+id/TextView1"
        app:layout_constraintCircleAngle="120"
        app:layout_constraintCircleRadius="160dp" />

上面例子中的TextView2用到了3个属性:
app:layout_constraintCircle="@+id/TextView1"
app:layout_constraintCircleAngle=“120”(角度)
app:layout_constraintCircleRadius=“160dp”(距离)
指的是TextView2的中心在TextView1的中心的120度,距离为160dp,效果如下:
在这里插入图片描述

3.4 边距

3.4.1 margin
ConstraintLayout的边距常用属性如下: android:layout_marginStart android:layout_marginEnd android:layout_marginLeft android:layout_marginTop android:layout_marginRight android:layout_marginBottom 注:控件在ConstraintLayout里面要实现margin,必须先约束该控件在ConstraintLayout里的相对位置且margin只能大于等于0。 例:

不生效:

<android.support.constraint.ConstraintLayout 
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/TextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="20dp"
        android:layout_marginTop="20dp" />
</android.support.constraint.ConstraintLayout>

生效:

<android.support.constraint.ConstraintLayout 
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

<TextView
    android:id="@+id/TextView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="20dp"
    android:layout_marginTop="00dp" 
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintTop_toTopOf="parent"/>
</android.support.constraint.ConstraintLayout>
 控件可见性,有三种状态,分别为:visible, invisilbe,gone.。visible表示控件可见
3.4.2 goneMargin
goneMargin主要用于约束的控件可见性被设置为gone的时候使用的margin值,属性如下: layout_goneMarginStart layout_goneMarginEnd layout_goneMarginLeft layout_goneMarginTop layout_goneMarginRight layout_goneMarginBottom

补充:控件可见性,有三种状态,分别为:visible, invisilbe,gone.。visible表示控件可见,invisible表示控件不可见,但是任然占用空间,gone表示不见,且不占用空间。
举个例子:
假设TextView2的左边约束在TextView1的右边,并给TextView2设一个app:layout_goneMarginLeft=“20dp”:
效果如下,TextView2在TextView1的右边,且没有边距
在这里插入图片描述
这个时候把TextView1的可见性设为gone,TextView1消失后,TextView2有一个距离左边10dp的边距。效果如下:
在这里插入图片描述

3.5 偏移

layout_constraintHorizontal_bias=“percent” 水平偏移
layout_constraintVertical_bias=“percent” 垂直偏移

举个例子:

<TextView
        android:id="@+id/TextView1"
        ...
        app:layout_constraintHorizontal_bias="0.3"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent" />

效果如下:
在这里插入图片描述

3.6 尺寸约束

  1. 使用指定的尺寸

  2. 使用wrap_content,让控件自己计算大小
    当控件的高度或宽度为wrap_content时,可以使用下列属性来控制最大、最小的高度或宽度:
    android:minWidth 最小的宽度
    android:minHeight 最小的高度
    android:maxWidth 最大的宽度
    android:maxHeight 最大的高度

  3.  使用 0dp (MATCH_CONSTRAINT)设置百分比布局:
    

    1.layout_width或者 layout_height 设置为0dp(只能一个)
    2.设置 layout_constraintWidth_percent="percent"或者 layout_constraintHeight_percent=“percent”

  4. 宽高比

当宽或高至少有一个尺寸被设置为0dp时或为wrap_content时,可以通过以下属性设置宽高比:

layout_constraintDimensionRatio ="1:1"
app:layout_constraintDimensionRatio="H,2:3"指的是 高:宽=2:3
app:layout_constraintDimensionRatio="W,2:3"指的是 宽:高=2:3


3.7 Chainl链

1.如果两个或以上控件通过下图的方式约束在一起,就可以认为是他们是一条链(图为横向的链,纵向同理)。
在这里插入图片描述
代码:

<TextView
        android:id="@+id/TextView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/TextView2" />

    <TextView
        android:id="@+id/TextView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toRightOf="@+id/TextView1"
        app:layout_constraintRight_toLeftOf="@+id/TextView3"
        app:layout_constraintRight_toRightOf="parent" />

    <TextView
        android:id="@+id/TextView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toRightOf="@+id/TextView2"
        app:layout_constraintRight_toRightOf="parent" />

以下链的内容转自:https://www.jianshu.com/p/2c125a8074ca

2.一个链条里面的第一个元素即为头,水平最左边,垂直最上边的控件,链头的作用是控制整个链条的属性,如上面的A控件就是链头。
3.在链头上面设置margin,整个链条都会响应这个margin,比如设置链头的一个左边android:layout_marginStart=“10dp”,这整个链条都会响应这个margin
在这里插入图片描述
4.Chain Style
在这里插入图片描述
链条可以设置不同的style,通过设置下面两个属性分别设置水平或者垂直(在链头设置):

layout_constraintHorizontal_chainStyle
layout_constraintVertical_chainStyle

而style包括三种:

  • spread(默认)-元素被分散开:
    在这里插入图片描述

  • spread_inside-与spread类似,只是链条的端点不会被分散链接:在这里插入图片描述

  • packed-链条内的元素将被捆在一起:

在这里插入图片描述
同时还有两种组合,在链条里面,可以使用weight和bias:

-spread + weight-将元素的尺寸设置为MATCH_CONSTRAINT时,可以与weight平分空间:
在这里插入图片描述

  • packed + bias- 前面说过bias是偏重的意思,这里就是将链条集体偏重:

  • 在这里插入图片描述
    综合案例:
    在这里插入图片描述

     <!-- weight chain -->
     <TextView
         android:id="@+id/weightStart"
         android:layout_width="0dp"
         app:layout_constraintHorizontal_weight="1" />
    
     <TextView
         android:id="@+id/weightCenter"
         android:layout_width="0dp"
         app:layout_constraintHorizontal_weight="2" />
    
     <TextView
         android:id="@+id/weightEnd"
         android:layout_width="0dp"
         app:layout_constraintHorizontal_weight="2" />
    
     <!-- spread chain-->
     <TextView
         android:id="@+id/spreadStart"
         app:layout_constraintBottom_toTopOf="@id/weightStart"
         app:layout_constraintEnd_toStartOf="@id/spreadCenter"
         app:layout_constraintStart_toStartOf="parent" />
    
     <TextView
         android:id="@+id/spreadCenter" />
    
     <TextView
         android:id="@+id/spreadEnd" />
    
     <!-- packed chain -->
     <TextView
         android:id="@+id/packedStart"
         app:layout_constraintHorizontal_chainStyle="packed" />
    
     <TextView
         android:id="@+id/packedCenter" />
    
     <TextView
         android:id="@+id/packedEnd" />
    
     <!-- spread_inside chain -->
     <TextView
         android:id="@+id/insideStart"
         app:layout_constraintHorizontal_chainStyle="spread_inside" />
    
     <TextView
         android:id="@+id/insideCenter"/>
    
     <TextView
         android:id="@+id/insideEnd" />
    
     <!-- packed chain with bias -->
     <TextView
         android:id="@+id/packedBiasStart"
         app:layout_constraintHorizontal_bias="0.2"
         app:layout_constraintHorizontal_chainStyle="packed" />
    
     <TextView
         android:id="@+id/packedBiasCenter" />
    
     <TextView
         android:id="@+id/packedBiasEnd" />
    

4.辅助工具

以下辅助工具内容转自:https://www.jianshu.com/p/17ec9bd6ca8a

4.1 Optimizer

当我们使用 MATCH_CONSTRAINT 时,ConstraintLayout 将对控件进行 2 次测量,ConstraintLayout在1.1中可以通过设置 layout_optimizationLevel 进行优化,可设置的值有:
none:无优化
standard:仅优化直接约束和屏障约束(默认)
direct:优化直接约束
barrier:优化屏障约束
chain:优化链约束
dimensions:优化尺寸测量

4.2 Barrierr

在这里插入图片描述
假设有3个控件ABC,C在AB的右边,但是AB的宽是不固定的,这个时候C无论约束在A的右边或者B的右边都不对。当出现这种情况可以用Barrier来解决。Barrier可以在多个控件的一侧建立一个屏障,如下所示:
在这里插入图片描述
这个时候C只要约束在Barrier的右边就可以了,代码如下:

<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为屏障引用的控件,可设置多个(用“,”隔开)

4.3 Groupr

Group可以把多个控件归为一组,方便隐藏或显示一组控件,举个例子:

<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_constraintLeft_toRightOf="@+id/TextView1" />
<TextView
    android:id="@+id/TextView3"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:layout_constraintLeft_toRightOf="@id/TextView2" />

在这里插入图片描述
现在有3个并排的TextView,用Group把TextView1和TextView3归为一组,再设置这组控件的可见性,如下所示:

    <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" />

在这里插入图片描述

4.4 Placeholder

Placeholder指的是占位符。在Placeholder中可使用setContent()设置另一个控件的id,使这个控件移动到占位符的位置。举个例子:

<android.support.constraint.Placeholder
        android:id="@+id/placeholder"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:content="@+id/textview"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/textview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#cccccc"
        android:padding="16dp"
        android:text="TextView"
        android:textColor="#000000"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

新建一个Placeholder约束在屏幕的左上角,新建一个TextView约束在屏幕的右上角,在Placeholder中设置 app:content="@+id/textview",这时TextView会跑到屏幕的左上角。效果如下:
在这里插入图片描述

4.5 Guideliner

Guildline像辅助线一样,在预览的时候帮助你完成布局(不会显示在界面上)。
Guildline的主要属性:
android:orientation 垂直vertical,水平horizontal
layout_constraintGuide_begin 开始位置
layout_constraintGuide_end 结束位置
layout_constraintGuide_percent 距离顶部的百分比(orientation = horizontal时则为距离左边)
举个例子:

<android.support.constraint.Guideline
    android:id="@+id/guideline1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    app:layout_constraintGuide_begin="50dp" />

<android.support.constraint.Guideline
    android:id="@+id/guideline2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    app:layout_constraintGuide_percent="0.5" />

guideline1为水平辅助线,开始位置是距离顶部50dp,guideline2位垂直辅助线,开始位置为屏幕宽的0.5(中点位置),效果如下:
在这里插入图片描述

5.综合案例

固定百分比高度:
在这里插入图片描述

<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">


    <TextView
        android:id="@+id/tab_layout"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@color/colorAccent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintHeight_percent="0.06"
        tools:ignore="MissingConstraints" />


</android.support.constraint.ConstraintLayout>

在这里插入图片描述

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.constraint.Guideline
        android:id="@+id/guideline"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:orientation="vertical"
        app:layout_constraintGuide_percent=".5"/>

    <Button
        android:id="@+id/button"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Button"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/guideline"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="0dp"
        android:text="Button"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/guideline"
        app:layout_constraintTop_toBottomOf="@+id/button" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@color/colorAccent"
        android:text="TextView"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toRightOf="@+id/guideline"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>

在这里插入图片描述
固定百分比:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:cardview="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    >

    <android.support.constraint.Guideline
        android:id="@+id/guideline1"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:orientation="vertical"
        app:layout_constraintGuide_percent=".05"/>
    <android.support.constraint.Guideline
        android:id="@+id/guideline2"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:orientation="vertical"
        app:layout_constraintGuide_percent=".20"/>
            <ImageView
                android:id="@+id/iv_portrait"
                android:layout_width="0dp"
                android:layout_height="0dp"
                app:layout_constraintLeft_toRightOf="@+id/guideline1"
                app:layout_constraintRight_toLeftOf="@+id/guideline2"
                app:layout_constraintDimensionRatio="1:1"
                android:orientation="horizontal"
                android:src="@mipmap/ic_launcher"
                tools:ignore="MissingConstraints" />

    <android.support.constraint.Guideline
        android:id="@+id/guideline3"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:orientation="vertical"
        app:layout_constraintGuide_percent=".25"/>
    <android.support.constraint.Guideline
        android:id="@+id/guideline4"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent=".05"/>
    <android.support.constraint.Guideline
        android:id="@+id/guideline5"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent=".7"/>
    <TextView
        android:id="@+id/tv_title"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="@+id/guideline4"
        app:layout_constraintLeft_toRightOf="@+id/guideline3"
        app:layout_constraintRight_toRightOf="parent"
        android:text="新闻标题"
        android:textColor="@color/blue_light"
        android:textSize="20sp"
        android:textStyle="bold"
        tools:ignore="MissingConstraints"
        tools:layout_editor_absoluteX="135dp"
        tools:layout_editor_absoluteY="16dp" />

    <TextView
        android:id="@+id/tv_desc"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="@+id/guideline5"
        app:layout_constraintLeft_toRightOf="@+id/guideline3"
        app:layout_constraintRight_toRightOf="parent"
        android:text="新闻部分内容"
        android:textColor="@android:color/black"
        tools:ignore="MissingConstraints"
        tools:layout_editor_absoluteX="135dp"
        tools:layout_editor_absoluteY="47dp" />
</android.support.constraint.ConstraintLayout>
  • 11
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

隔壁de小刘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值