ContraintLayout的基本属性与用法(一)

本文深入讲解ConstraintLayout的使用方法,通过实例对比传统布局,展示如何利用ConstraintLayout减少布局层级,提高性能。并介绍了ConstraintLayout的基本属性及其应用技巧。

前言

A ConstraintLayout is a ViewGroup which allows you to position and size widgets in a flexible way.
简言:ConstraintLayout是可以灵活设置其内控件位置和大小的ViewGroup。

支持API 9 (Gingerbread)及以上,官方后续仍将对其API和功能进行扩展。

添加
1、 Android Studio版本至少2.3,我用的是AS 3.1.3
2、 在build.gradle中添加依赖,如下:

dependencies {
compile ‘com.android.support.constraint:constraint-layout:1.1.3’
}

正题

开局一张图,博客全靠编:
在这里插入图片描述
该布局如果以传统布局方式来写的话是这样的(由于显示逻辑问题实际情况更复杂,demo略做精简)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/product_item"
    android:layout_width="match_parent"
    android:layout_height="140dp"
    android:layout_marginBottom="2dp"
    android:layout_marginLeft="7dp"
    android:layout_marginRight="7dp">

    <FrameLayout
        android:id="@+id/product_img_container"
        android:layout_width="117dp"
        android:layout_height="117dp"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true"
        android:layout_marginBottom="7dp"
        android:layout_marginLeft="10dp"
        android:layout_marginTop="7dp">
        <!-- 商品图片 -->
        <ImageView
            android:id="@+id/sku_img"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="centerCrop"
            tools:src="@drawable/ic_launcher_background" />

        <TextView
            android:id="@+id/sku_num"
            android:layout_width="wrap_content"
            android:layout_height="20dp"
            android:layout_gravity="end|right|bottom"
            android:paddingBottom="2dp"
            android:paddingLeft="6dp"
            android:paddingRight="6dp"
            android:paddingTop="2dp"
            android:textColor="#ffffff"
            android:textSize="11dp"
            tools:text="4件" />
    </FrameLayout>


    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_marginLeft="17dp"
        android:layout_marginRight="17dp"
        android:layout_marginTop="15dp"
        android:layout_toRightOf="@id/product_img_container"
        android:ellipsize="end"
        android:gravity="center_vertical"
        android:maxLines="2"
        android:textColor="#ff000000"
        android:textSize="16dp"
        android:textStyle="bold"
        tools:text="飞利浦干湿两a~须a abc def" />

    <!-- 商品介绍 -->
    <TextView
        android:id="@+id/desc"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@id/title"
        android:layout_below="@+id/title"
        android:layout_marginRight="17dp"
        android:layout_marginTop="9.5dp"
        android:ellipsize="end"
        android:gravity="center_vertical"
        android:lineSpacingMultiplier="1.1"
        android:maxLines="1"
        android:textColor="#818181"
        android:textSize="13dp"
        tools:text="西装作为职场必备 ITEM其修身线条,挺括的外观,舒适的穿着西装作为职场必备 ITEM其修身线条,挺括的外观" />

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@id/title"
        android:layout_marginBottom="12dp">

        <ImageView
            android:id="@+id/author_img"
            android:layout_width="20dp"
            android:layout_height="20dp"
            android:layout_alignBottom="@id/author_name"
            android:layout_marginBottom="2dp"
            tools:src="@drawable/ic_launcher_background" />

        <TextView
            android:id="@+id/author_name"
            android:layout_width="wrap_content"
            android:layout_height="25dp"
            android:layout_alignParentBottom="true"
            android:layout_marginLeft="5dp"
            android:layout_toRightOf="@+id/author_img"
            android:ellipsize="end"
            android:gravity="center_vertical"
            android:maxLength="6"
            android:textColor="#6A6A6A"
            android:textSize="11sp"
            tools:text="美丽教主" />

        <!--喜欢人数&点赞-->
        <TextView
            android:id="@+id/common_like_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="10dp"
            android:textSize="13dp"
            android:textColor="@color/colorAccent"
            android:layout_alignParentBottom="true"
            android:layout_alignParentRight="true"
            android:layout_marginRight="6dp"
            tools:text="300人喜欢"/>
    </RelativeLayout>
</RelativeLayout>

可以看到,这个简单的布局已经做了两层嵌套
在这里插入图片描述
如果我们用ContraintLayout,就一层布局足以,不用嵌套。之前写的布局我们可以以这种方式简单转化一下:在desin中右击
在这里插入图片描述
转化完成后,我们的布局会乱,因为会把我们所有的嵌套布局删掉,如Relativelayout,FrameLayout等。所以我们需要手动调整一下。
当然,你可以直接用contraintLayout布局编写,在gradle文件中添加依赖即可。

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

在编写XML文件之前,我们需要了解一下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

通常情况下,这些属性足够让我们编译一套复杂的布局。其实这些属性很简单,你完全可以当做加强版本的RelativeLayout来使用,Left_toLeftOf的意思就是我的左边跟xxid的左边相邻,其他意思类推。
例如假设你的textview要在imageView的右边,那么代码就这么写 在textView控件中 app:layout_constraintLeft_toRightOf="@图片控件的id"
所以改变完后的代码如下:

<?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:id="@+id/product_item"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginBottom="2dp"
    android:layout_marginLeft="7dp"
    android:layout_marginRight="7dp">

    <!-- 商品图片 -->
    <ImageView
        android:id="@+id/sku_img"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:scaleType="centerCrop"
        tools:src="@drawable/ic_launcher_background" />

    <TextView
        android:id="@+id/sku_num"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingBottom="2dp"
        android:paddingLeft="6dp"
        android:paddingRight="6dp"
        android:paddingTop="2dp"
        android:textColor="#ffffff"
        android:textSize="13dp"
        app:layout_constraintBottom_toBottomOf="@id/sku_img"
        app:layout_constraintRight_toRightOf="@id/sku_img"
        tools:text="4件" />


    <TextView
        android:id="@+id/title"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginLeft="16dp"
        android:ellipsize="end"
        android:gravity="center_vertical"
        android:maxLines="2"
        android:textColor="#ff000000"
        android:textSize="16dp"
        android:textStyle="bold"
        app:layout_constraintLeft_toRightOf="@id/sku_img"
        app:layout_constraintRight_toRightOf="parent"
        tools:text="飞利浦干湿两a~须a abc def飞利浦干湿两a~须a abc def飞利浦干湿两a~须a abc de" />

    <!-- 商品介绍 -->
    <TextView
        android:id="@+id/desc"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:ellipsize="end"
        android:lineSpacingMultiplier="1.1"
        android:maxLines="1"
        android:textColor="#818181"
        android:textSize="13dp"
        app:layout_constraintLeft_toLeftOf="@id/title"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/title"
        tools:text="西装作为职场必备 ITEM其修身线条,挺括的外观,舒适的穿着西装作为职场必备 ITEM其修身线条,挺括的外观" />


    <ImageView
        android:id="@+id/author_img"
        android:layout_width="30dp"
        android:layout_height="30dp"
        app:layout_constraintBottom_toBottomOf="@id/sku_img"
        app:layout_constraintLeft_toLeftOf="@id/title"
        tools:src="@drawable/ic_launcher_background" />

    <TextView
        android:id="@+id/author_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:ellipsize="end"
        android:gravity="center_vertical"
        android:maxLength="6"
        android:textColor="#6A6A6A"
        android:textSize="11sp"
        app:layout_constraintBottom_toBottomOf="@id/author_img"
        app:layout_constraintLeft_toRightOf="@id/author_img"
        tools:text="美丽教主" />

    <!--喜欢人数&点赞-->
    <TextView
        android:id="@+id/common_like_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="13dp"
        app:layout_constraintBottom_toBottomOf="@id/sku_img"
        app:layout_constraintRight_toRightOf="parent"
        tools:text="300人喜欢" />

</android.support.constraint.ConstraintLayout>


布局截图如下:
在这里插入图片描述
可以看到,我们不用嵌套任何一个布局即可完成该布局的编码工作,所以在性能上,尤其是更加复杂的布局,岂不是很爽。
当然,有可能你在布局的过程中会遇到以下几种情况:

1. 两个控件之间怎么居中对齐?
2. 我设置了android:ellipsize="end"为什么没生效
3. 在某些逻辑下我要隐藏很多控件,为了方便,我在传统布局里可以将这些控件设置在一个ViewGroup里,就可以达到隐藏ViewGroup来简化单独的控件隐藏逻辑,现在新布局不让用布局嵌套了,我难道要一个个控件单独隐藏?
4. 我所依赖的一个控件在某些逻辑下setVisibiltyGone后,自身的位置发生了重大偏差,怎么办?

这些问题,我们都可以解决,篇幅问题,我们下期会依依解决这些问题,同时引出更多的高级用法,高级属性。

<think>嗯,用户这次问的是Android开发中设置并排按钮间距的问题。从对话历史看,用户应该是个开发者,可能在布局时遇到了按钮间距的细节调整需求。用户引用了站内两段资料,但明确表示这些只是参考,实际需要的是具体间距设置方法。看来用户已经尝试过搜索,但需要更聚焦的解决方案。考虑到Android布局的多样性,我需要提供多种主流方案供选择。先梳理核心痛点:横向排列的按钮需要自定义间距。这涉及到三个关键点:消除默认间距、精确控制距离、适应不同屏幕。需要从ViewGroup容器和View属性两个层面解决。第种用LinearLayout加margin是最直观的,适合简单场景。但要注意dip和dp单位的区别,得提醒用户用dp保证致性。第二种ConstraintChain的方案虽然代码稍复杂,但能完美处理响应式布局,特别是当按钮尺寸动态变化时最稳定。用户没提MaterialDesign的要求,但ChainStyle的示例还是推荐了packed模式,这是MD规范推荐的按钮组排列方式。xml示例需要强调android:textAllCaps="false"这个细节,因为很多开发者会忽略系统默认的全大写转换。最后补充的Space方案可能最有意思,虽然代码行数最多,但解决了margin法在RTL布局的兼容问题。阿拉伯语等从右到左语言场景下,使用marginEnd会失效,而Space视图能自动适配。考虑到用户可能后续会遇到异形按钮间距问题,提前在“其他方式”里准备了Shape方案。当按钮有复杂背景时,这个方案其实是最高效的,不过drawable的创建步骤需要额外说明。性能方面要重点提示:所有方案中,带有weight属性的LinearLayout在嵌套时可能引起性能问题,这点在adapter里特别明显。如果用户之后追问列表优化,还可以展开说使用ContraintLayout减少层级。</think> 在Android中设置两个**横向排列按钮之间的间距**,以下是几种主流方案及具体操作步骤: --- ### 📌 方案:使用 `LinearLayout` + `layout_margin`(推荐) ```xml <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="center"> <Button android:id="@+id/btn1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="按钮1" android:layout_marginEnd="16dp" /> <!-- 右侧间距 --> <Button android:id="@+id/btn2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="按钮2" /> </LinearLayout> ``` **关键点**: 1. `layout_marginEnd="16dp"`:为第个按钮右侧添加间距(适配RTL布局) 2. 或使用 `android:layout_marginRight`(旧项目兼容) --- ### 📌 方案二:`ConstraintLayout` 的 **Chain** 模式 ```xml <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <Button android:id="@+id/btn1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="按钮1" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toStartOf="@id/btn2" app:layout_constraintHorizontal_chainStyle="spread" /> <!-- 关键链式布局 --> <Button android:id="@+id/btn2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="按钮2" app:layout_constraintStart_toEndOf="@id/btn1" app:layout_constraintEnd_toEndOf="parent" android:layout_marginStart="16dp" /> <!-- 左侧间距 --> </androidx.constraintlayout.widget.ConstraintLayout> ``` **优势**:响应式布局,自动处理屏幕尺寸适配 --- ### 📌 方案三:插入透明间距视图 ```xml <LinearLayout android:orientation="horizontal" ...> <Button android:text="按钮1" /> <!-- 间距控件 --> <Space android:layout_width="16dp" android:layout_height="1dp" /> <Button android:text="按钮2" /> </LinearLayout> ``` **适用场景**:需严格像素级控制间距时 --- ### 🔧 解决默认间隔问题 若系统自带间隔影响布局,添加以下属性: ```xml <LinearLayout ... android:divider="@null" <!-- 移除分隔线 --> android:showDividers="none"> <!-- 隐藏分隔符 --> ``` --- ### ⚡ 其他方式 1. **权重分配**(适合等分间距): ```xml <Button ... android:layout_weight="1" /> <Button ... android:layout_weight="1" /> ``` 2. **通过 Shape Drawable**: ```xml <Button android:background="@drawable/btn_with_margin" /> ``` `btn_with_margin.xml`: ```xml <layer-list> <item android:right="16dp"> <!-- 右侧内边距 --> <shape android:shape="rectangle"> <solid android:color="@color/button_color"/> </shape> </item> </layer-list> ``` --- ### 💎 最佳实践建议 1. **单位选择**:优先使用 `dp`(独立像素)保证不同屏幕致性 2. **间距值推荐**: - 小间距:`8dp` - 标准间距:`16dp` - 大间距:`24dp` 3. **ConstraintLayout** 在复杂布局中性能更优[^2] 通过以上方法,可灵活控制任意按钮间距,满足Material Design规范要求。 --- ### 🔍相关问题 1. 如何动态修改Android按钮间距? 2. ConstraintLayout的ChainStyle有哪些区别? 3. 如何适配RTL布局的边距设置? 4. Material Design对按钮间距的具体规范是什么? 5. 不同屏幕密度下如何保证间距致性?
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值