美文网首页Android 开发
Android约束布局ConstraintLayout由浅入深的

Android约束布局ConstraintLayout由浅入深的

作者: 948d307d6ecf | 来源:发表于2020-09-11 16:01 被阅读0次

    优缺点

    优点

    • 极大程度减少布局层级
    • 可以实现一些其他布局管理器不能实现的样式

    缺点

    • 每个被参考的控件都需要设置id

    ConstraintLayout性能分析

    以下所有描述都是针对ConstraintLayout下子控件的,通用的属性在此不在叙述,只针对ConstraintLayout独有属性进行探讨。

    基本用法

    一、定位

    1. 相对定位

    • 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:文字Baseline对齐
    • layout_constraintStart_toEndOf
    • layout_constraintStart_toStartOf
    • layout_constraintEnd_toStartOf
    • layout_constraintEnd_toEndOf

    以下代码表示tv2顶部与tv1顶部对齐

    <androidx.constraintlayout.widget.ConstraintLayout
        ...
        >
    
        <TextView
            android:id="@+id/tv1"
            ...
            />
    
        <TextView
            android:id="@+id/tv2"
            ...
            app:layout_constraintTop_toTopOf="@id/tv1" />
            
    </androidx.constraintlayout.widget.ConstraintLayout> 
    

    2. 圆形定位

    • layout_constraintCircle : 参考控件的id

    • layout_constraintCircleRadius : 本控件与参考控件中心点间距

    • layout_constraintCircleAngle : 角度0~360

      一图胜千言

    以下代码表示Textview中心位于id为targetId控件的中心距离30dp角度为30度的位置

    <androidx.constraintlayout.widget.ConstraintLayout
        ...
        >
    
        <TextView
            ...
            app:layout_constraintCircle="@id/targetId"
            app:layout_constraintCircleAngle="30"
            app:layout_constraintCircleRadius="30dp"/>
    </androidx.constraintlayout.widget.ConstraintLayout>    
    

    3. 百分比定位(bias)

    • layout_constraintHorizontal_bias
    • layout_constraintVertical_bias

    取值范围0~1,默认值0.5

    以下代码表示Textview中心位置位于ConstraintLayout宽度的30%处

    <androidx.constraintlayout.widget.ConstraintLayout
        ...
        >
    
        <TextView
            ...
            app:layout_constraintHorizontal_bias="0.3"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"/>
    </androidx.constraintlayout.widget.ConstraintLayout>    
    

    4. 居中对齐

    所有居中对其需要设置对应方向尺寸大小为wrap_content或固定值

    • 水平居中

    以下代码表示Textview相对于ConstraintLayout水平居中

    <androidx.constraintlayout.widget.ConstraintLayout
        ...
        >
    
        <TextView
            ...
            android:layout_width="60dp"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"/>
    </androidx.constraintlayout.widget.ConstraintLayout>   
    

    注意:

    1. 这里的left和right换成start和end也是可以的
    2. 这里的parent换成参考控件的id也是可以的
    • 垂直居中

    以下代码表示Textview相对于ConstraintLayout垂直居中

    <androidx.constraintlayout.widget.ConstraintLayout
        ...
        >
    
        <TextView
            ...
            android:layout_height="60dp"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"/>
    </androidx.constraintlayout.widget.ConstraintLayout>   
    

    注意:这里的parent换成参考控件的id也是可以的

    5. 单边对齐

    以下代码表示tv2和tv3与tv1顶部对齐

    <androidx.constraintlayout.widget.ConstraintLayout
        ...
        >
    
        <TextView
            android:id="@+id/tv1"
            ...
            />
    
        <TextView
            android:id="@+id/tv2"
            ...
            app:layout_constraintTop_toTopOf="@id/tv1" />
            
        <TextView
            android:id="@+id/tv3"
            ...
            app:layout_constraintTop_toTopOf="@id/tv1" />
    </androidx.constraintlayout.widget.ConstraintLayout>   
    

    注意:这里写法比较多样,以上展示的都是以统一的单个控件为参考点,也可以以相关控件为参考点,比如这里的tv3可以与tv2顶部对其,效果也是一样的。

    二、间距

    • layout_goneMarginStart
    • layout_goneMarginEnd
    • layout_goneMarginLeft
    • layout_goneMarginTop
    • layout_goneMarginRight
    • layout_goneMarginBottom

    表示当前控件参考的控件隐藏时对应的间距,如果参考控件未隐藏该设置不会生效。

    以下代码表示tv1正常显示多时候,tv2左边距离tv1 100dp,如果tv1隐藏了,tv2左边距为0

    <androidx.constraintlayout.widget.ConstraintLayout
        ...
        >
    
        <TextView
            android:id="@+id/tv1"
            ...
            />
    
        <TextView
            android:id="@+id/tv2"
            ...
            android:layout_marginStart="100dp"
            app:layout_goneMarginStart="0dp" 
            app:layout_constraintTop_toTopOf="@id/tv1" />
    </androidx.constraintlayout.widget.ConstraintLayout> 
    

    三、尺寸大小

    1. 权重比

    主要依赖于以下两个属性:

    • app:layout_constraintHorizontal_weight
    • app:layout_constraintVertical_weight

    默认情况下各控件的权重都是相等的,以下代码表示tv1、tv2和tv3三等分ConstraintLayout的宽度

    <androidx.constraintlayout.widget.ConstraintLayout
        ...
        >
    
        <TextView
            android:id="@+id/tv1"
            android:layout_width="0dp"
            ...
            app:layout_constraintEnd_toStartOf="@id/tv2"
            app:layout_constraintStart_toStartOf="parent"/>
            
        <TextView
            android:id="@+id/tv2"
            android:layout_width="0dp"
            ...
            app:layout_constraintEnd_toStartOf="@id/tv3"
            app:layout_constraintStart_toEndOf="@id/tv1"
            />
            
        <TextView
            android:id="@+id/tv3"
            android:layout_width="0dp"
            ...
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@id/tv2"/>
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    如果需要非等分,使用layout_constraintHorizontal_weight或者layout_constraintVertical_weight属性调整即可,以下代码表示tv1、tv2和tv3按照3:2:1的比例占满ConstraintLayout的宽度

    <androidx.constraintlayout.widget.ConstraintLayout
        ...
        >
    
        <TextView
            android:id="@+id/tv1"
            android:layout_width="0dp"
            ...
            app:layout_constraintEnd_toStartOf="@id/tv2"
            app:layout_constraintHorizontal_weight="3"
            app:layout_constraintStart_toStartOf="parent"/>
            
        <TextView
            android:id="@+id/tv2"
            android:layout_width="0dp"
            ...
            app:layout_constraintEnd_toStartOf="@id/tv3"
            app:layout_constraintHorizontal_weight="2"
            app:layout_constraintStart_toEndOf="@id/tv1"/>
            
        <TextView
            android:id="@+id/tv3"
            android:layout_width="0dp"
            ...
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_weight="1"
            app:layout_constraintStart_toEndOf="@id/tv2"/>
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    2. 百分比

    百分比需要满足下面三个条件:

    1. 宽或高设置成0dp
    2. 宽或高默认值设置成百分比
      • app:layout_constraintWidth_default="percent"
      • app:layout_constraintHeight_default="percent"
    3. 宽或高百分比的值(取值范围0~1)
      • app:layout_constraintWidth_percent
      • app:layout_constraintHeight_percent

    这里的百分比是指占父控件的百分比

    以下代码表示Textview宽度为ConstraintLayout宽度的50%

    <androidx.constraintlayout.widget.ConstraintLayout
        ...
        >
    
        <TextView
            ...
            android:layout_width="0dp"
            app:layout_constraintHeight_default="percent"
            app:layout_constraintWidth_percent="0.5"/>
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    3. 宽高比

    百分比需要满足下面两个条件:
    a. 宽或高至少有一个设置成0dp
    b. 通过app:layout_constraintDimensionRatio设置宽高比

    这里layout_constraintDimensionRatio宽高的取值有以下4种形式:

    • 16:9 表示宽高比为16:9
    • 0.2 表示宽高比为1:5
    • H,16:9 表示宽高比为9:16
    • W,16:9 表示宽高比为16:9

    以下代码表示Textview的宽高比为2:1

    <androidx.constraintlayout.widget.ConstraintLayout
        ...
        >
    
        <TextView
            ...
            android:layout_height="0dp"
            app:layout_constraintDimensionRatio="2:1"/>
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    高级用法

    一、强制约束

    1. 应用场景

    使用wrap_content,但仍要强制执行约束以限制结果尺寸,比如一个Textview的宽度是根据文字内容自适应的,文字内容可能很短也可能很长,当文字内容很长的时候可能会打破原先的约束,比如本来在在某个控件的左边,但是随着文字内容的增长会越界!

    2. 使用方式

    • layout_constrainedWidth="true|false"
    • layout_constrainedHeight="true|false"

    使用以上两个属性来强制控件的宽或高严格执行相应的约束条件

    3. 示例

    <androidx.constraintlayout.widget.ConstraintLayout
        ...
        >
    
        <TextView
            android:id="@+id/tv1"
            ...
            android:layout_width="wrap_content"
            app:layout_constraintRight_toLeftOf="@id/tv2"
            app:layout_constraintLeft_toLeftOf="parent" />
    
        <TextView
            android:id="@+id/tv2"
            ...
            android:layout_width="wrap_content"
            app:layout_constraintTop_toBottomOf="@id/tv1"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    以上代码实现的是tv1在tv2的左边,随着tv1内容不断增加,tv1的右边会越过tv2的左边,如果想限制不管tv1内容怎么增加都不会越过tv2的左边,则可增加layout_constrainedWidth="true"即可

    <androidx.constraintlayout.widget.ConstraintLayout
        ...
        >
    
        <TextView
            android:id="@+id/tv1"
            ...
            android:layout_width="wrap_content"
            app:layout_constrainedWidth="true"
            app:layout_constraintRight_toLeftOf="@id/tv2"
            app:layout_constraintLeft_toLeftOf="parent" />
    
        <TextView
            android:id="@+id/tv2"
            ...
            android:layout_width="wrap_content"
            app:layout_constraintTop_toBottomOf="@id/tv1"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    二、Barrier

    1. 应用场景

    当某个控件的约束想以一组控件为参考点,并且始终不越界

    2. 使用方式

    • app:barrierDirection="start|left|top|right|end|bottom"
    • app:constraint_referenced_ids="tv1,tv2"

    3. 示例

    以下代码表示以tv1和tv2的底部为一个屏障,tv3始终在tv1和tv2下面,即使tv1和tv2全部都消失

    <androidx.constraintlayout.widget.ConstraintLayout
        ...
        >
        <androidx.constraintlayout.widget.Barrier
            android:id="@+id/barrier"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:barrierAllowsGoneWidgets="true"
            app:barrierDirection="bottom"
            app:constraint_referenced_ids="tv1,tv2" />
            
        <TextView
            android:id="@+id/tv1"
            ...
            />
            
        <TextView
            android:id="@+id/tv2"
            ...
            />
            
        <TextView
            android:id="@+id/tv3"
            ...
            app:layout_constraintTop_toBottomOf="@id/barrier"/>
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    三、 Guideline

    1. 应用场景

    布局参考线可以作为其他控件布局约束的参考,但不会显示出来

    2. 使用方式

    参考线的方向,可分为水平和竖直两个方向:

    • android:orientation="vertical|horizontal"

    参考线的位置:

    • app:layout_constraintGuide_begin="100dp"
    • app:layout_constraintGuide_end="100dp"
    • app:layout_constraintGuide_percent="0.5"

    3. 示例

    以下代码表示以ConstraintLayout宽度的中心点为参考线,tv1与参考线左对齐

    <androidx.constraintlayout.widget.ConstraintLayout
        ...
        >
        
        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/guideline"
            android:orientation="vertical"
            app:layout_constraintGuide_percent="0.5"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
            
        <TextView
            android:id="@+id/tv1"
            ...
            app:layout_constraintLeft_toLeftOf="@id/guideline"
            />
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    四、Group

    1. 应用场景

    将某几个控件归为一组动态进行显示或隐藏控制

    2. 使用方式

    需要归为一组控件的ID

    • app:constraint_referenced_ids="tv1,tv2"

    3. 示例

    以下代码表示将tv1和tv2两个textview归为一组,并设置为隐藏

    <androidx.constraintlayout.widget.ConstraintLayout
        ...
        >
        
        <androidx.constraintlayout.widget.Group
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:visibility="gone"
            app:constraint_referenced_ids="tv1,tv2"/>
            
        <TextView
            android:id="@+id/tv1"
            ...
            />
        <TextView
            android:id="@+id/tv2"
            ...
            />
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    五、Chain

    Chain可以很容易达到其他布局管理器不容易实现,甚至无法实现的样式

    1. 应用场景

    某几个控件之间首位相接,排列方式有特殊要求

    2. 使用方式

    • layout_constraintHorizontal_chainStyle="spread|spread_inside|packed"
    • layout_constraintVertical_chainStyle="spread|spread_inside|packed"

    chainStyle取值:

    • spread: 控件均匀分布,即控件之间(包括边框)间距相同
    • spread_inside: 第一个和最后一个控件固定在链两端的约束边界上,其余控件均匀分布,即控件内部之间间距相同
    • packed: 控件打包在一起(在考虑外边距之后)。 然后,您可以通过更改链的头视图偏差调整整条链的偏差(左/右或上/下)。
    chainStyle取值

    3. 示例

    <androidx.constraintlayout.widget.ConstraintLayout
        ...
        >
        
        <TextView
            android:id="@+id/tv1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#00897B"
            android:gravity="center"
            android:paddingStart="20dp"
            android:paddingEnd="20dp"
            android:text="1111"
            android:textColor="#fff"
            android:textSize="20sp"
            app:layout_constraintHorizontal_chainStyle="spread_inside"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@id/tv2"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
        <TextView
            android:id="@+id/tv2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#3700B3"
            android:gravity="center"
            android:paddingStart="20dp"
            android:paddingEnd="20dp"
            android:text="2222"
            android:textColor="#fff"
            android:textSize="20sp"
            app:layout_constraintBaseline_toBaselineOf="@id/tv1"
            app:layout_constraintEnd_toStartOf="@id/tv3"
            app:layout_constraintStart_toEndOf="@id/tv1" />
    
        <TextView
            android:id="@+id/tv3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#FB8C00"
            android:gravity="center"
            android:paddingStart="20dp"
            android:paddingEnd="20dp"
            android:text="3333"
            android:textColor="#fff"
            android:textSize="20sp"
            app:layout_constraintBaseline_toBaselineOf="@id/tv1"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@id/tv2" />
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    综合实践

    使用ConstraintLayout实现以下布局,要求:

    1. 两个textview横向并排显示,即一左一右
    2. 两个textview的宽度均根据文字内容自适应
    3. 两个textview均左对齐
    4. 右边textview内容全展示(文字内容最多不会超过单行宽度)
    5. 显示不下时左边textview内容尾部显示省略号

    最终效果图

    tv1文字较少的时候 tv1文字较多的时候

    实现代码:

    <androidx.constraintlayout.widget.ConstraintLayout
        ...
        >
    
        <TextView
            android:id="@+id/tv1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#00897B"
            android:ellipsize="end"
            android:gravity="center"
            android:maxLines="1"
            android:paddingStart="20dp"
            android:paddingEnd="20dp"
            android:text="AAAAA"
            android:textColor="#fff"
            android:textSize="20sp"
            app:layout_constrainedWidth="true"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@id/tv2"
            app:layout_constraintHorizontal_bias="0"
            app:layout_constraintHorizontal_chainStyle="packed"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
        <TextView
            android:id="@+id/tv2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#FB8C00"
            android:ellipsize="end"
            android:gravity="center"
            android:paddingStart="20dp"
            android:paddingEnd="20dp"
            android:singleLine="true"
            android:text="BBBB"
            android:textColor="#fff"
            android:textSize="20sp"
            app:layout_constraintBaseline_toBaselineOf="@id/tv1"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@id/tv1" />
            
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    相关文章

      网友评论

        本文标题:Android约束布局ConstraintLayout由浅入深的

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