ConstraintLayout 构建自适应界面

QuibblerQuibbler 2020-02-26 约 29 分钟 2600 次阅读

ConstraintLayout 

从Android API 9以后Google推出了ConstraintLayout,而且从Android Studio 2.3 起,默认布局就是ConstraintLayout。 

1、ConstraintLayout

主要是为了解决布局嵌套过多的问题,以灵活的方式定位和调整小部件。RelativeLayout 也可以解决多层嵌套问题,但是ConstraintLayout更加灵活,性能更加出色。ConstraintLayout布局非常有利于可视化编程,各种拖拽操作。ConstraintLayout 的所有功能均可直接通过布局编辑器的可视化工具来使用,因为布局 API 和布局编辑器是专为彼此构建的。参考Google官方文档使用布局编辑器构建界面

要使用ConstraintLayout首先在build.gradle中添加依赖:

//2020年03月01日 最新版本1.1.3
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'

2、ConstraintLayout属性

了解一下基本属性。

2.1、相对位置约束

位置约束一共有13个。View如果仅用相对位置约束,那么需要同时约束Horizontal和Vertical两个方向,否则会提示错误。

        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

这些属性的取值reference或enum类型。其它View的id,或唯一的枚举类型parent。看看其中一个属性的定义如下,即可明白

<attr format="reference|enum" name="layout_constraintLeft_toLeftOf">
        <enum name="parent" value="0"/>
    </attr>

2.2、角度方位约束

用一个角度和一个距离来约束两个空间的中心。

layout_constraintCircle(reference)目标控件 ID

layout_constraintCircleAngle(integer)和目标控件的角度

layout_constraintCircleRadius(dimension)该控件中心 距离目标控件中心的距离。

只使用这三个属性就可以定位一个View的位置。虽然AndroidStudio还提示错误。

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <TextView
        android:id="@+id/text_view_1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView 1"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
        
    <TextView
        android:id="@+id/text_view_2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView 2"
        app:layout_constraintCircle="@id/text_view_1"
        app:layout_constraintCircleAngle="150"
        app:layout_constraintCircleRadius="200dp" />
</androidx.constraintlayout.widget.ConstraintLayout>

2.3、绝对位置 *

        在布局中写死控件所在的绝对位置

        layout_editor_absoluteX(dimension)

        layout_editor_absoluteY(dimension)

        这些属性在实际运行时并不生效,但是在写布局的时候AndroidStudio预览显示是正确的。

2.4、边距Margin约束

和之前写LinearLayout布局一样,边距margin边距仍然用这些属性控制。必须先约束该控件在ConstraintLayout里的相对位置,边距才能生效。且margin边距只能为正,不能为负。

        android:layout_marginStart

        android:layout_marginEnd

        android:layout_marginLeft

        android:layout_marginTop

        android:layout_marginRight

        android:layout_marginBottom

2.5、goneMargin边距

当用于约束的控件visibility被设置为gone的时候使用的margin值

        layout_goneMarginStart

        layout_goneMarginEnd

        layout_goneMarginLeft

        layout_goneMarginTop

        layout_goneMarginRight

        layout_goneMarginBottom

这是TextView1可见时,TextView2相对TextView1的约束,使用普通的layout_marginTop和layout_marginStart

当用来约束的View设置为gone不可见时,使用goneMargin属性设定的margin值。

2.6、居中

居中:

RelativeLayout中,把控件放在布局中间的方法是把layout_centerInParent设为true。在约束布局中添加上下左右四个对齐约束:

app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"

水平居中:

左右拉齐

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

垂直居中:

上下拉齐

app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintTop_toTopOf="parent"

2.7、尺寸约束

①固定dp值

②wrap_content

android:minWidth 最小的宽度

android:minHeight 最小的高度

android:maxWidth 最大的宽度

android:maxHeight 最大的高度

③match_content:官方不推荐在ConstraintLayout中使用match_parent

使用0dp和,再配合约束条件约束控件大小。

2.8、宽高比约束

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

        app:layout_constraintDimensionRatio

app:layout_constraintDimensionRatio="1:1"

设置宽高比的值的时候,还可以在前面加W或H,分别指定宽度或高度限制。

//高:宽=2:3
    app:layout_constraintDimensionRatio="H,2:3"
    //宽:高=2:3
    app:layout_constraintDimensionRatio="W,2:3"

2.9、链:chain

水平方向的控件从左到右:parent-view-... ... view-parent

垂直方向的约束从上到下:parent-view-... ...-view-parent

形成一种“无形的”链。

layout_constraintHorizontal_chainStyle来改变整条链的样式。chains提供了3种样式,分别是:

CHAIN_SPREAD —— 展开元素 (默认);

CHAIN_SPREAD_INSIDE —— 展开元素,但链的两端贴近parent;

CHAIN_PACKED —— 链的元素将被打包在一起。

2.10、权重weight

LinearLayout线性布局的时候常常用到weight权重,让控件按比例平分空间。水平方向按照权重分割空间,一定要把layout_width设置为0dp,不能设置为wrap_content,要不然不参与权重的计算瓜分剩余空间。

        app:layout_constraintVertical_weight

        app:layout_constraintHorizontal_weight

2.11、辅助属性

         这些属性是 UI 编辑器用来辅助拖拽布局的,在实际使用过程中可以不用关心它们。布局中使用并不生效,只在布局预览的时候有效。

        layout_optimizationLevel

        layout_editor_absoluteX

        layout_editor_absoluteY

        layout_constraintBaseline_creator

        layout_constraintTop_creator

        layout_constraintRight_creator

        layout_constraintLeft_creator

        layout_constraintBottom_creator

3、约束工具

3.1、参照线 Guideline

类似盖房子的锤线,作为其它空间的参照。可以设置多个,而不用整个ConstraintLayout都参考第一个View或者只参考Parent。

android:orientation 参照线方向,可以水平horizontal、垂直vertical

app:layout_constraintGuide_begin 垂直距左,水平距上,起始距离

app:layout_constraintGuide_end    垂直距下,水平距右,起始距离

app:layout_constraintGuide_percent  垂直距左,水平距上,距离按比例比例

三者的优先级:percent > begin > end,如果都设置,前者覆盖后者。

举个例子:

<?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout 
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        
        <androidx.constraintlayout.widget.Guideline
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="horizontal"
            app:layout_constraintGuide_end="100dp" />
            
        <androidx.constraintlayout.widget.Guideline
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="horizontal"
            app:layout_constraintGuide_begin="100dp" />
            
        <androidx.constraintlayout.widget.Guideline
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            app:layout_constraintGuide_percent="0.1" />
            
        <androidx.constraintlayout.widget.Guideline
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            app:layout_constraintGuide_end="100dp" />
            
    </androidx.constraintlayout.widget.ConstraintLayout>

3.2、屏障 Barrier 组件

Barrier直译为障碍、屏障。在约束布局中,可以使用属性constraint_referenced_ids属性来引用多个带约束的组件,从而将它们看作一个整体,Barrier 的介入可以完成很多其他布局不能完成的功能。

空间将用Barrier屏障来约束,Barrier屏障中的控件就任由变形。

举个例子:

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="10dp">
        
        <androidx.constraintlayout.widget.Barrier
            android:id="@+id/barrier"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:barrierDirection="right"
            app:constraint_referenced_ids="text_view1,text_view2"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
            
        <TextView
            android:id="@+id/text_view1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="TextView 1"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
        <TextView
            android:id="@+id/text_view2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="50dp"
            android:text="TextView 2"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toBottomOf="@id/text_view1" />
         
        <EditText
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:layout_constraintLeft_toRightOf="@+id/barrier"
            app:layout_constraintRight_toRightOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>

将TextView1和TextView2“放在”Barrier中,用屏障分割左右,希望在右侧的EditText只需要以屏障为约束即可。

3.3、Group 组件

Group可以把多个控件归为一组,方便隐藏或显示一组控件。打打方便的控制界面View的可见性,不需要一个一个去设置。

3.4、占位符 Placeholder

Placeholder中可设置另一个控件的id,使这个控件移动到占位符的位置。

app:content="@+id/id"

还可以在代码中给Placeholder动态设置content内容,将指定View移到Placeholder位置,感觉大有可为!

//将TextView移到placeHolder位置
    placeHolder.setContentId(R.id.text_view);

举个例子:

<androidx.constraintlayout.widget.ConstraintLayout 
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        
        <androidx.constraintlayout.widget.Placeholder
            android:id="@+id/place_holder"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:content="@+id/text_view"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
        
        <!--TextView不会再这里显示,而是显示在Placeholder的位置-->
        <TextView
            android:id="@+id/text_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="TextView"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>

参考资料:

        Android 开发者>Android Studio>用户指南>ConstraintLayout

        ConstraintLayout 详解

        约束布局ConstraintLayout看这一篇就够了

        使用ConstraintLayout遇到的些许问题

相关推荐

精选
ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager
Android

ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager

ViewPager1、ViewPagerandroidx.viewpager.widget.ViewPager,Android中使用非常广泛的控件,可以说是APP必备:首次打开引导页、页面Banner广告等。常用方法:setAdapter() 设置适配器setOffscreenPageLimit() 设置缓存的页面个数,默认是 1setCurrentItem() 跳转到特定的页面setOnPage

1.1k
获取Android内置WebView内核版本
Android

获取Android内置WebView内核版本

获取Android内置WebView内核版本竟然能遇到这样奇葩的事情,网页用的技术过于新颖,以至于只支持高版本Chromium内核的,低版本安卓系统中内置的内核版本较低,无法加载前端页面。1、设置查看在系统设置里 > 应用 > 应用管理 > 显示系统应用,查看WebView组件:2、页面查看通过WebView发起的网络请求,都会带上浏览器的UA,通常页面都可以通过UA判断浏览器的内核版本。这里有两

1.1w
Android 14适配总结
Android

Android 14适配总结

Android 14适配总结毕业工作至今已经适配了三个Android大版本,从Android 11到Android 12、再到Android 13。2023年,Google即将推出的Android 14,上半年已经开始第一批适配。现在,第四个Android版本已经适配完,总结记录一下。1、Android 14计划Google一般会在2月份对外发布预告,同时放出开发者预览版。“拉通”各大平台、厂商以

1.1w