ConstraintLayout 学习

ConstraintLayout官网学习地址

       最近发现使用ConstraintLayout这个布局方式的公司越来越多了,趁着最近比较空闲,利用空余时间来学习应用下,主要是根据官方的文档来进行分析理解~

一、ConstraintLayout 官方文档的理解学习

    ConstraintLayout allows you to create large and complex layouts with a flat view hierarchy (no nested view groups). It's similar to RelativeLayout in that all views are laid out according to relationships between sibling views and the parent layout, but it's more flexible than RelativeLayout and easier to use with Android Studio's Layout Editor.

     All the power of ConstraintLayout is available directly from the Layout Editor's visual tools, because the layout API and the Layout Editor were specially built for each other. So you can build your layout with ConstraintLayout entirely by drag-and-dropping instead of editing the XML.

      ConstraintLayout 用简单的view来创造复杂和大型的布局场景,和RelativeLayout比较类似(即就是父控件以及子控件间的依赖关系,就不详细介绍了)但是ConstraintLayout比RelativeLayout更灵活好用,可以在可视化的工具栏来拖拽这个控件进行布局构建,在Android Studio 2.0往上默认使用的就是这个布局。

约束Constraint 的概述:

     Constraint ,定义视图在ConstraintLayout中的位置,必须给视图view添加一个或者多个水平和垂直约束,每个约束相当于这个视图在ConstraintLayout中沿着垂直方向或者水平方向的与其他视图之间的对齐等约束关系。

图一    这个图中,视图C只添加了水平约束,没有垂直约束。图中和视图A之间建立了约束关系,C的左边和右边位置分别和A对齐,但是没有垂直约束,所以显示在屏幕的顶部位置。

 

 

图二      这个图解决上述图中出现的问题,图C添加了一个垂直方向的约束,在A的底部,也实现了最终想要的视图效果。

 

 

二、ConstraintLayout 在项目中的应用

1、项目中的添加

 确认项目的build.gradle 文件中是否有maven.google.com 仓库,若是没有添加这个仓库:

repositories {
    google()
}

以依赖的形式把这个库添加到同一个build.gradle文件中:

dependencies {
    implementation 'com.android.support.constraint:constraint-layout:1.1.2'//示例版本,非最新版本
}

Sync Project with Gradle Files同步,就可以将这个库添加到项目中了。

2、布局转换

      以前开发的时候使用的是其他的布局,如果需要所有的项目布局都使用依赖布局,我们旧的布局不需要我们一一去更改,有更智能的转换方式:

旧布局:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_marginTop="38dp"
        android:orientation="horizontal">

        <Button
            android:id="@+id/thread_btn1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="线程一写入" />

        <Button
            android:id="@+id/thread_btn2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="线程二写入" />

        <Button
            android:id="@+id/Thread_query"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="查询所有" />

    </LinearLayout>


</RelativeLayout>

a/ 切换到Android Studio 布局中 Design ;

b/ 找到Component Tree 工具栏,在需要转换的视图(这里需要转换RelativeLayout)上右击选择Convert RelativeLayout to ConstraintLayout

           

3、添加或者删除约束

1)、添加约束

最简单的方式,可以在布局的Design视图窗口进行简单的拖拽来实现约束:

a/ 在Palwtte窗口拖拽合适控件view到视图编辑窗口;

b/ 在 ConstraintLayout 中看到这个控件view 可以看到一个边框,四个角可以拉动调整大小,四边中间有圆形的句柄可以拖动来添加约束关系;

c/ 点击圆形句柄然后拖拽可以添加不同的约束关系,具体可以参考下面两幅图,图一是给父布局添加约束,图二是两个子控件之间的约束。

图一:父布局约束
图二:子控件间的约束

   

@ 添加约束需要注意的点:

  • 每个view都必须有至少两个约束:一个水平方向和一个垂直方向的约束;
  • 添加约束仅仅在同一个水平方向的view 来添加,比如一个view的垂直方向只能和另一个view的垂直方向来添加约束;
  • 每一个约束句柄仅仅可以用在一个约束上,但是可以添加多个约束在同一个点。

2)、删除约束

删除约束很简单,需要删除哪个控件的约束,直接选中这个控件右下角显示 按钮,直接点击就可以删除这个控件的约束了。是不是很简单~

3)、约束图标学习

   Align:对齐,可以选择相对于布局对齐还是其他view对齐方式

  Edit Baseline:基线对齐,每个view的基线可以拖拽和其他view基线对齐

  Guidelines:可以选择添加水平基准线(Add Vertical Guideline)还是垂直(Add Horizontal Guideline)的,这线可以隐藏,可以拖动位置,可以给view添加相对于这条基准线的约束。

   约束的具体也可以在编辑视图的Properties窗口来进行调节。

    视图尺寸调节:使用这个最好宽高至少有一个的属性是match constraints (0dp);

    视图宽高模式:   Fixed ——  宽高设置具体 dp 值

                                 Wrap Content —— 宽高设置wrap_content

                                 Match Constraints  —— 宽高设置0dp

    ratio:宽高比, 要使用这个属性,宽高至少有一个设置为match constraints

 

Notes: 不能在ConstraintLayout中用match_parent ,替代是match constraints<0dp>。

4)双向约束链

一组视图view在同一条chain上,互相之间存在约束关系,一般有以下四种模式:

a/ Spread:默认情况,一组中的几个视图的均匀分布;

b/  Spread inside:一组视图中的第一个和最后一个视图分别在chain 的首端和末端,其他视图均匀分布;

c/ Weighted:类似以LinearLayout 中的weight  权重适配,在约束布局中使用 layout_constraintHorizontal_weight 和 layout_constraintVertical_weight 进行权重的分配。

d/   Packed:一组视图排列在一个链接上,彼此之间没有间隔。

   双向约束链的模式选择,即可以切换以上四种情况模式。

app:layout_constraintHorizontal_chainStyle="packed"

5)自动添加约束

 Autoconnect  自动添加约束,默认不开启,开启后控件在界面中会自动添加约束,但不一定是项目需要的约束;

 Infer Constraints  我们可以将控件拖拽到界面大体位置上,再点击会自动添加控件位置关系的约束

三、ConstraintLayout 使用

可视化操作使用可以参考郭霖大神的 《Android新特性介绍,ConstraintLayout完全解析》

* 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            // 尾部向尾部对齐

 

layout_constraintXXX_toYYYOf="CCC"  :  控件的 XXX边 和 控件CCC 的 YYY边 对齐。

1、居中

1)、屏幕中居中显示

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

    <Button
        android:id="@+id/btn1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="second"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="@android:color/holo_red_light"
        android:gravity="center"
        android:text="Center"
        android:textColor="@android:color/white"
        android:textSize="16sp"
        app:layout_constraintBottom_toTopOf="@id/btn1"
        app:layout_constraintLeft_toRightOf="@id/btn1"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

2)、控件的右上角空白区域居中显示

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

    <Button
        android:id="@+id/btn1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="second"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="@android:color/holo_red_light"
        android:gravity="center"
        android:text="Center"
        android:textColor="@android:color/white"
        android:textSize="16sp"
        app:layout_constraintBottom_toTopOf="@id/btn1"
        app:layout_constraintLeft_toRightOf="@id/btn1"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

 

2、偏移量

app:layout_constraintVertical_bias="0.6"  //在垂直方向向下的偏移量为 60%
app:layout_constraintHorizontal_bias="0.3"  //在水平方向向右的偏移量为 30%

 

3、宽高比 ratio

宽高比设置图

 

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

    <ImageView
        android:layout_width="60dp"
        android:layout_height="0dp"
        android:background="@android:color/holo_purple"
        app:layout_constraintDimensionRatio="2:1"
        app:layout_constraintTop_toTopOf="parent" />

    <ImageView
        android:id="@+id/iv1"
        android:layout_width="60dp"
        android:layout_height="0dp"
        android:background="@android:color/holo_purple"
        app:layout_constraintDimensionRatio="w,2:1"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <ImageView
        android:layout_width="60dp"
        android:layout_height="0dp"
        android:layout_marginTop="30dp"
        android:background="@android:color/holo_purple"
        app:layout_constraintDimensionRatio="h,2:1"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toBottomOf="@id/iv1" />

    <ImageView
        android:id="@+id/iv2"
        android:layout_width="0dp"
        android:layout_height="60dp"
        android:background="@android:color/holo_red_light"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintDimensionRatio="2:1"
        app:layout_constraintTop_toTopOf="parent" />

    <ImageView
        android:id="@+id/iv3"
        android:layout_width="0dp"
        android:layout_height="60dp"
        android:background="@android:color/holo_red_light"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintDimensionRatio="w,2:1"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <ImageView
        android:layout_width="0dp"
        android:layout_height="60dp"
        android:layout_marginTop="90dp"
        android:background="@android:color/holo_red_light"
        app:layout_constraintDimensionRatio="h,2:1"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toBottomOf="@id/iv2" />


    <ImageView
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@android:color/holo_orange_dark"
        app:layout_constraintBottom_toBottomOf="iv2"
        app:layout_constraintDimensionRatio="1:1"
        app:layout_constraintLeft_toRightOf="@id/iv2"
        app:layout_constraintRight_toLeftOf="@id/iv3"
        app:layout_constraintTop_toTopOf="@id/iv2" />

</android.support.constraint.ConstraintLayout>

使用 layout_constraintDimensionRatio 属性,至少需要设置宽度或者高度为 0dp,宽高的尺寸比例可以通过“float值”或者“W:H”的形式来设置。

分析: layout_width : 0dp   + layout_height : 60dp,设置 ratio : "2:1" 以及  "w,2:1" 效果是一样的,都是宽是高的二倍 ;

                                                                                    设置 ratio : "h,2:1"  则是以高作为基准,即高是宽的二倍。

          layout_width : 60dp + layout_height: 0dp,  设置 ratio : "2:1" 以及 "h,2:1" 效果是一样的,都是宽是高的二倍;

                                                                              设置 ratio : "w,2:1" 则是以宽作为基准,即高是宽的二倍。

使用 layout_constraintDimensionRatio 属性,宽度和高度都设置为 0dp, 会使用满足所有约束条件以及宽高比的最大值尺寸。

 

4、类似 LinearLayout  的权重 layout_weight 设置宽高占比

垂直方向比重设置
<?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">

    <TextView
        android:id="@+id/tv1"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@android:color/holo_red_light"
        android:gravity="center"
        android:text="first"
        app:layout_constraintBottom_toTopOf="@id/tv2"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_weight="1" />

    <TextView
        android:id="@+id/tv2"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@android:color/holo_orange_light"
        android:gravity="center"
        android:text="second"
        app:layout_constraintBottom_toTopOf="@id/tv3"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/tv1"
        app:layout_constraintVertical_weight="1.5" />

    <TextView
        android:id="@+id/tv3"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@android:color/holo_blue_bright"
        android:gravity="center"
        android:text="third"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/tv2"
        app:layout_constraintVertical_weight="1" />


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

    <TextView
        android:id="@+id/tv1"
        android:layout_width="0dp"
        android:layout_height="50dp"
        android:background="@android:color/holo_red_light"
        android:gravity="center"
        android:text="first"
        app:layout_constraintHorizontal_weight="0.5"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/tv2"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/tv2"
        android:layout_width="0dp"
        android:layout_height="50dp"
        android:background="@android:color/holo_orange_light"
        android:gravity="center"
        android:text="second"
        app:layout_constraintHorizontal_weight="1"
        app:layout_constraintLeft_toRightOf="@+id/tv1"
        app:layout_constraintRight_toLeftOf="@+id/tv3"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/tv3"
        android:layout_width="0dp"
        android:layout_height="50dp"
        android:background="@android:color/holo_blue_bright"
        android:gravity="center"
        android:text="third"
        app:layout_constraintHorizontal_weight="0.8"
        app:layout_constraintLeft_toRightOf="@+id/tv2"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

 

5、指示线Guideline  

     定位的时候也可以使用Guideline 来进行位置的定位,Guideline 是View的子类,使用方式和普通View相同,但是有以下优点:

  • 宽度和高度均是为0
  • 只是用来定位,但是是不可见的 View.Gone
用Guideline 实现控件的位置定位
<?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/guideline1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.5" />

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

    <TextView
        android:layout_width="100dp"
        android:layout_height="100dp"
        app:layout_constraintLeft_toRightOf="@id/guideline1"
        app:layout_constraintTop_toBottomOf="@id/guideline2"
        android:background="@android:color/holo_purple" />

</android.support.constraint.ConstraintLayout>

6、Chains 链

Chain 链比较难描述,它是一种特殊的约束,可以为多个通过 chain 链连接的 View 来分发剩余空间位置,类似于 LinearLayout 中的权重比 weight 属性,但 Chains 链要强大得多

如果几个View之间通过双向连接而互相约束对方的位置,那么将其视为链条,例如下面代码呈现的可以称之为链条。

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

    <TextView
        android:id="@+id/tv1"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:background="@android:color/holo_red_light"
        android:gravity="center"
        android:text="first"
        app:layout_constraintHorizontal_chainStyle="spread_inside"
        app:layout_constraintHorizontal_weight="0.5"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/tv2"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/tv2"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:background="@android:color/holo_orange_light"
        android:gravity="center"
        android:text="second"
        app:layout_constraintHorizontal_chainStyle="spread"
        app:layout_constraintHorizontal_weight="1"
        app:layout_constraintLeft_toRightOf="@+id/tv1"
        app:layout_constraintRight_toLeftOf="@+id/tv3"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/tv3"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:background="@android:color/holo_blue_bright"
        android:gravity="center"
        android:text="third"
        app:layout_constraintHorizontal_chainStyle="spread"
        app:layout_constraintHorizontal_weight="0.8"
        app:layout_constraintLeft_toRightOf="@+id/tv2"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

 app:layout_constraintHorizontal_chainStyle="XXX"  , 可以设置以下不同模式,实现不同的效果:

* spread - 元素将被展开(默认样式) 
* weighted 加权链 - 在spread 或者 spread_inside 模式下,如果某些小部件设置为MATCH_CONSTRAINT,设置水平或者垂直    方向的权重比例,则它们将拆分可用空间 
* spread_inside - 类似,但链的端点将不会扩展 
* packed - 链的元素将被打包在一起。 孩子的水平或垂直偏差属性将影响包装元素的定位

@margin  : 如果设置margin,整条链有这个边距效果。

 

四、小结

        系统看了官方文档再参考了相关博客算是把ConstraintLayout的相关知识点基本捋了一遍,相对于RelativeLayout 和 LinearLayout 来说更加好用高效,嵌套层级相对较少。ConstraintLayout 约束基本通过layout_constraintXXX_toYYYOf 属性来进行约束对齐,引入了Guideline 和 Chains  ,更好进行约束。

bug:

       在项目运行的时候,位置的依赖我一直使用的@id/XXX,但是我们也知道如果实在该控件下面的控件依赖会报错,找不到这个依赖资源,这次使用constraintlayout 的时候就犯了这个错误,但是把它改为@+id/XXX就行了,不存在找不到控件资源的错误。以前习惯了一直都是@+id/ 是给控件添加id , @id/是来处理位置依赖关系,现在看来@+id/也是可以处理依赖关系的。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值