美文网首页Android开发经验谈Android技术知识Android开发
ConstraintLayout 约束布局例子讲解 (持续更新)

ConstraintLayout 约束布局例子讲解 (持续更新)

作者: zhongjh | 来源:发表于2018-04-03 00:25 被阅读697次

    2016年google就已经公布了这个约束布局ConstraintLayout。

    但是时至现在2018年,还是很多人在使用普遍的LinearLayout或者RelativeLayout。有的可能会用到百分比布局,但是还是很少很少用到。我觉得非常有必要普及这方面的内容,并且这个对于提高性能,是有作用的

    唯一副作用是学习成本高、相对于其他普通布局完成的速度可能也会慢

    我最近也开始涉及学习这方面,发现确实如果不通过好好的例子来写的,确实很难上手。
    所以出了以下内容,让大家更快更容易了解!

    首先先跟大家共享我搜到的文章:
    https://blog.csdn.net/lmj623565791/article/details/78011599?utm_source=tuicool&utm_medium=referral
    https://blog.csdn.net/guolin_blog/article/details/53122387
    https://segmentfault.com/a/1190000009536640?utm_source=tuicool&utm_medium=referral

    再列出我觉得有参考性的demo,github上找的
    https://github.com/googlesamples/android-ConstraintLayoutExamples
    https://github.com/vtthach/20170704_Sample_ConstraintLayout

    属性作用:

    以前RelativeLayout的约束有两种:

    • 1 子控件和子控件之间的约束(如android:layout_below="@id/title")
    • 2 子控件和父控件的约束(如 android:layout_alignParentTop="true")
    • 3 子控件和Guideline(参考线)的约束。下面会讲解参考线的作用。

    参数取值是 ID(@id/button1)代表约束1、3, 或者 字符串"parent" 代表约束2:

    RelativeLayout 对应父类 RelativeLayout 对应其他view ConstraintLayout
    android:layout_alignParentLeft="true" android:layout_alignLeft app:layout_constraintLeft_toLeftOf 与指定View的左边界一致
    android:layout_alignParentStart="true" android:layout_alignStart app:layout_constraintStart_toStartOf
    android:layout_alignParentTop="true" android:layout_alignTop app:layout_constraintTop_toTopOf 与指定View的上边界一致
    android:layout_alignParentRight="true" android:layout_alignRight app:layout_constraintRight_toRightOf
    android:layout_alignParentEnd="true" android:layout_alignEnd app:layout_constraintEnd_toEndOf
    android:layout_alignParentBottom="true" android:layout_alignBottom app:layout_constraintBottom_toBottomOf 与指定View的下边界一致
    android:layout_centerHorizontal="true" app:layout_constraintStart_toStartOf="parent" 和 app:layout_constraintEnd_toEndOf="parent"
    android:layout_centerVertical="true" app:layout_constraintTop_toTopOf="parent" 和 app:layout_constraintBottom_toBottomOf="parent"
    android:layout_centerInParent="true" app:layout_constraintStart_toStartOf="parent", app:layout_constraintTop_toTopOf="parent", app:layout_constraintEnd_toEndOf="parent", 和 app:layout_constraintBottom_toBottomOf="parent"
    android:layout_below app:layout_constraintTop_toBottomOf 在指定View的下方
    android:layout_toEndOf app:layout_constraintStart_toEndOf 在指定View的右边
    android:layout_toRightOf app:layout_constraintLeft_toRightOf 在指定View的右边
    android:layout_above app:layout_constraintBottom_toTopOf 在指定View的上方
    android:layout_toStartOf app:layout_constraintEnd_toStartOf 在指定View的左边
    android:layout_toLeftOf app:layout_constraintRight_toLeftOf 在指定View的左边
    android:layout_alignBaseline app:layout_constraintBaseline_toBaselineOf
    组合属性作用:
    ConstraintLayout 组合属性 解释
    app:layout_constraintEnd_toStartOf="@+id/vLine", app:layout_constraintTop_toTopOf="@+id/vLine", app:layout_constraintBottom_toBottomOf="@+id/vLine" 这个是基于vLine控件的左边,并且完全的中心对齐
    app:layout_constraintBottom_toBottomOf="@+id/vLine" app:layout_constraintStart_toEndOf="@+id/vLine" app:layout_constraintTop_toTopOf="@+id/vLine" 同上,这次是在右边并且中心对齐
    1.首先完成顶部第一个图片:
    image.png

    添加以下两个属性

    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    

    即可完成居中,因为左边约束了,右边也约束了。可以通俗的理解为左边和右边用相同的力道(我这样说是因为下面会介绍可以控制哪边用的力道大小)都相扯约束,自然居中了。
    如果第一个图片不添加

    app:layout_constraintTop_toTopOf="parent"
    

    则这个相距属性android:layout_marginTop="16dp"是不会触发的。

    所以总结第一个图片:

    <ImageView
            android:id="@+id/imgIcon"
            android:layout_width="48dp"
            android:layout_height="48dp"
            android:layout_marginTop="16dp"
            android:src="@drawable/ic_security_lock"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            tools:ignore="ContentDescription" />
    
    2.接着完成顶部第二个控件:
    image.png

    首先直奔主题,关键的一个属性:

    layout_constraintTop_toBottomOf 
    

    按照我的理解则是约束上面并且位于该约束控件的下面
    同时为了居中,也是添加约束父布局的左边和右边,所以最终是

    <TextView
            android:id="@+id/txtMessage"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="32dp"
            android:text="@string/please_enter_your_4_bit_password"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/imgIcon" />
    
    3.接着是比较困难的第三个控件布局
    image.png

    首先我们按照上面所了解的,先分别添加4个控件


    image.png

    第一个控件,居左并且在第二个控件的下面。第二个控件在第一个控件和第三个控件的中间,第三个控件一样,只有最后一个第四个控件在最右边。

    <ImageView
            android:id="@+id/imgOne"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_marginTop="24dp"
            android:src="@drawable/pin_code_round_empty"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/txtMessage"
            tools:ignore="ContentDescription" />
    
    <ImageView
            android:id="@+id/imgTwo"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_marginTop="24dp"
            android:src="@drawable/pin_code_round_empty"
            app:layout_constraintLeft_toRightOf="@+id/imgThree"
            app:layout_constraintRight_toLeftOf="@+id/imgOne"
            app:layout_constraintTop_toBottomOf="@+id/txtMessage"
            tools:ignore="ContentDescription" />
    
        <ImageView
            android:id="@+id/imgThree"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_marginTop="24dp"
            android:src="@drawable/pin_code_round_empty"
            app:layout_constraintLeft_toRightOf="@+id/imgTwo"
            app:layout_constraintRight_toLeftOf="@+id/imgFour"
            app:layout_constraintTop_toBottomOf="@+id/txtMessage"
            tools:ignore="ContentDescription" />
    
        <ImageView
            android:id="@+id/imgFour"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_marginTop="24dp"
            android:src="@drawable/pin_code_round_empty"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/txtMessage"
            tools:ignore="ContentDescription" />
    

    那么剩下一个问题如何让他们居中呢?很简单,第一个控件添加

    app:layout_constraintRight_toLeftOf="@+id/imgFour"
    

    大意是居左,跟右边的第四个控件约束,变成这样


    image.png

    然后第四个控件添加该属性

    app:layout_constraintLeft_toRightOf="@+id/imgOne"
    

    最终便可以居中了

    4.接着是下面的百分比布局

    首先完成百分比布局之前,我们需要先明确大体布局。如上面的布局,横布局需要分成三等份,竖布局需要分成四等份。然后就开始创建参考线了。

    4.1首先为了铺满这个百分比,要先创建多一个ConstraintLayout布局,基于txtForget控件的下面。
    <android.support.constraint.ConstraintLayout
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_marginTop="8dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/txtForget">
    
    4.2开始创建参考线。
    Preview创建Guideline

    创建竖线3条

    <android.support.constraint.Guideline
                android:id="@+id/guidelineV33"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                app:layout_constraintGuide_percent="0.33333333" />
    
            <android.support.constraint.Guideline
                android:id="@+id/guidelineV66"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                app:layout_constraintGuide_percent="0.66666666" />
    
            <android.support.constraint.Guideline
                android:id="@+id/guidelineV100"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                app:layout_constraintGuide_percent="1" />
    

    创建横线4条

    <android.support.constraint.Guideline
                android:id="@+id/guideline1H25"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                app:layout_constraintGuide_percent="0.25" />
    
            <android.support.constraint.Guideline
                android:id="@+id/guideline1H50"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                app:layout_constraintGuide_percent="0.50" />
    
            <android.support.constraint.Guideline
                android:id="@+id/guideline1H75"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                app:layout_constraintGuide_percent="0.75" />
    
            <android.support.constraint.Guideline
                android:id="@+id/guideline1H100"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                app:layout_constraintGuide_percent="1" />
    

    创建完所需要的参考线之后如图所示:

    image.png
    4.3接下来我们只要负责把需要放的控件放进参考线里面居中即可

    让我们看看最重要的4个属性

    app:layout_constraintBottom_toTopOf="@+id/guideline1H25"
                app:layout_constraintEnd_toStartOf="@+id/guidelineV33"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent"
    

    app:layout_constraintStart_toStartOf:表示与指定View的左边界一致,如果是parent则是父控件最左边
    app:layout_constraintEnd_toStartOf:在指定View的左边
    app:layout_constraintBottom_toTopOf:在指定View的上方
    app:layout_constraintTop_toTopOf:与指定View的上边界一致,如果是parent则是父控件的最上边

    那么把每个控件都放进去,最终百分比的代码:

    <android.support.constraint.ConstraintLayout
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_marginTop="8dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/txtForget">
    
            <TextView
                android:id="@+id/txtOne"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_gravity="center"
                android:layout_margin="8dp"
                android:layout_marginBottom="8dp"
                android:layout_marginEnd="8dp"
                android:layout_marginStart="8dp"
                android:layout_marginTop="8dp"
                android:gravity="center"
                android:tag="1"
                android:text="1"
                android:textSize="32sp"
                app:layout_constraintBottom_toTopOf="@+id/guideline1H25"
                app:layout_constraintEnd_toStartOf="@+id/guidelineV33"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                tools:ignore="HardcodedText" />
    
            <TextView
                android:id="@+id/txtTwo"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_gravity="center"
                android:layout_margin="8dp"
                android:layout_marginBottom="8dp"
                android:layout_marginEnd="8dp"
                android:layout_marginStart="8dp"
                android:layout_marginTop="8dp"
                android:gravity="center"
                android:tag="2"
                android:text="2"
                android:textSize="32sp"
                app:layout_constraintBottom_toTopOf="@+id/guideline1H25"
                app:layout_constraintEnd_toStartOf="@+id/guidelineV66"
                app:layout_constraintStart_toEndOf="@+id/txtOne"
                app:layout_constraintTop_toTopOf="parent"
                tools:ignore="HardcodedText" />
    
            <TextView
                android:id="@+id/txtThree"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_gravity="center"
                android:layout_margin="8dp"
                android:layout_marginBottom="8dp"
                android:layout_marginEnd="8dp"
                android:layout_marginStart="8dp"
                android:layout_marginTop="8dp"
                android:gravity="center"
                android:tag="3"
                android:text="3"
                android:textSize="32sp"
                app:layout_constraintBottom_toTopOf="@+id/guideline1H25"
                app:layout_constraintEnd_toStartOf="@+id/guidelineV100"
                app:layout_constraintStart_toStartOf="@+id/guidelineV66"
                app:layout_constraintTop_toTopOf="parent"
                tools:ignore="HardcodedText" />
    
            <TextView
                android:id="@+id/txtFour"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_gravity="center"
                android:layout_margin="8dp"
                android:layout_marginBottom="8dp"
                android:layout_marginEnd="8dp"
                android:layout_marginStart="8dp"
                android:layout_marginTop="8dp"
                android:gravity="center"
                android:tag="4"
                android:text="4"
                android:textSize="32sp"
                app:layout_constraintBottom_toTopOf="@+id/guideline1H50"
                app:layout_constraintEnd_toStartOf="@+id/guidelineV33"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="@+id/guideline1H25"
                tools:ignore="HardcodedText" />
    
            <android.support.constraint.Guideline
                android:id="@+id/guidelineV33"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                app:layout_constraintGuide_percent="0.33333333" />
    
            <android.support.constraint.Guideline
                android:id="@+id/guidelineV66"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                app:layout_constraintGuide_percent="0.66666666" />
    
            <android.support.constraint.Guideline
                android:id="@+id/guidelineV100"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                app:layout_constraintGuide_percent="1" />
    
            <android.support.constraint.Guideline
                android:id="@+id/guideline1H25"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                app:layout_constraintGuide_percent="0.25" />
    
            <android.support.constraint.Guideline
                android:id="@+id/guideline1H50"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                app:layout_constraintGuide_percent="0.50" />
    
            <android.support.constraint.Guideline
                android:id="@+id/guideline1H75"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                app:layout_constraintGuide_percent="0.75" />
    
            <android.support.constraint.Guideline
                android:id="@+id/guideline1H100"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                app:layout_constraintGuide_percent="1" />
    
        </android.support.constraint.ConstraintLayout>
    
    image.png

    请注意,app:layout_constraintStart_toStartOf和app:layout_constraintLeft_toLeftOf有区别的,具体可以在改演示中的百分比修改就知道具体区别了。

    5、利用Barrier完美实现“多对象约束”

    例子布局

    类似这样的布局,中间这条线是在左边两个文本框以及右边两个文本框的中间。广州黄埔的文字或者江苏南京的文字如果过长,中间的一条线都会往下移动,例如这样:


    image.png

    或者这样:


    image.png
    那么如何把这两个TextView对象当成一个对象来看待呢,很简单,如下代码:
            <android.support.constraint.Barrier
                android:id="@+id/barrier7"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:barrierDirection="bottom"
                app:constraint_referenced_ids="tvDeparture,tvDestination" />
    

    最后把这个Barrier当成一个对象对待即可

    app:layout_constraintTop_toBottomOf="@+id/barrier7"
    

    6、待编辑的其他属性

    • Barrier
      Barrier是一个虚拟的辅助控件,它可以阻止一个或者多个控件越过自己,就像一个屏障一样。当某个控件要越过自己的时候,Barrier会自动移动,避免自己被覆盖。

    • Group
      Group帮助你对一组控件进行设置。最常见的情况是控制一组控件的visibility。你只需把控件的id添加到Group,就能同时对里面的所有控件进行操作(比如批量隐藏,删除等等)。

    <android.support.constraint.ConstraintLayout ...>
      <TextView
        android:id="@+id/text1" ... />
      <TextView
        android:id="@+id/text2" ... />
     <android.support.constraint.Group
                android:id="@+id/group"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
        app:constraint_referenced_ids=”text1,text2" />
    </android.support.constraint.ConstraintLayout>
    
    • Circular positioning
      可以相对另一个控件,以角度和距离定义当前控件的位置,即提供了在圆上定义控件位置的能力。如图所示:

    [图片上传失败...(image-e0b4d2-1523179128704)]

    • Placeholder
      Placeholder顾名思义,就是用来一个占位的东西,它可以把自己的内容设置为ConstraintLayout内的其它view。因此它用来写布局的模版,也可以用来动态修改UI的内容。

    总而言之,约束布局的能力正在变得越来越强大。

    相关文章

      网友评论

        本文标题:ConstraintLayout 约束布局例子讲解 (持续更新)

        本文链接:https://www.haomeiwen.com/subject/khqxhftx.html