(约束布局)ConstraintLayout的辅助控件

相信大家对ConstraintLayout(约束布局)不陌生,这是google推出的一个强大控件,之所以强大其实主要归纳有两点:减少布局层次,能够轻松实现复杂布局。当然在我们实际使用过程中,是否真的减少了布局层次?其实这个问题从我开始用这个布局产生了疑问,看了下自己写的布局还是一层包一层。如果你也有这个问题,那么接下来文章中的内容能够帮助你解决.

1.约束布局基本使用:

 相信大家对于基本使用应该都没什么问题,这里就不做过多阐述,跟四大控件里面的相对布局思路类似。

2.约束布局辅助控件:

辅助控件就是今天的重点内容:今天重点说下GuideLine,Layer,Flow,group这四个辅助控件。我先贴下我demo布局

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/cons"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.constraintlayout.helper.widget.Layer
        android:id="@+id/layer"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#D16D6D"
        app:constraint_referenced_ids="textview1,textview2,src"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/textview1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:padding="10dp"
        android:text="这是一个constrainlayout自带的流式布局Flow"
        android:textColor="@color/white"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@id/guideline"
        app:layout_constraintTop_toTopOf="parent" />


    <TextView
        android:id="@+id/textview2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:padding="10dp"
        android:text="这是一个constraintlayout自带的Layer层布局"
        android:textColor="@color/white"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@id/guideline"
        app:layout_constraintTop_toBottomOf="@id/textview1" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.8" />

    <ImageView
        android:id="@+id/src"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:padding="10dp"
        android:src="@mipmap/ic_launcher"
        app:layout_constraintBottom_toBottomOf="@id/textview2"
        app:layout_constraintLeft_toRightOf="@id/guideline"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="@id/textview1" />

    <androidx.constraintlayout.helper.widget.Flow
        android:id="@+id/demo_flow"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:flow_firstHorizontalBias="0"
        app:flow_firstHorizontalStyle="packed"
        app:flow_horizontalBias="0"
        app:flow_horizontalGap="10dp"
        app:flow_horizontalStyle="spread_inside"
        app:flow_lastHorizontalBias="0"
        app:flow_lastHorizontalStyle="packed"
        app:flow_verticalGap="8dp"
        app:flow_wrapMode="chain"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/textview2" />

</androidx.constraintlayout.widget.ConstraintLayout>

2.1 GuideLine辅助线

首先看布局中的guideLine控件:这个控件是不显示在界面上的,也不占用任何空间,主要用于辅助线,它分水平和垂直辅助线,上面布局就是垂直辅助线,我们看看预览效果

可以看到预览效果中在屏幕0.8宽度上有一条垂直辅助线,他可以作为左右两边控件的约束条件.因此guideline可以简单理解为:不显示,不占空间的一条辅助约束其他控件的线。

2.2 Layer控件

说到这个控件我就不得不提一下:在不知道这个辅助控件之前,我的xml布局还是一层套一层,为什么呐?因为我要给某几个控件设置一个背景色。相当于要管理几个子view,果断只有选择在外面包裹一层cons。我也多次在网上找了下资料是在无从下手,group也不行。就在最近在研究flow时突然看到这个控件,omg突然发现新大陆。layer就是层布局,他的作用感觉可以理解为帧布局。

看下xml中这段布局

<androidx.constraintlayout.helper.widget.Layer
    android:id="@+id/layer"
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:background="#D16D6D"
    app:constraint_referenced_ids="textview1,textview2,src"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

<TextView
    android:id="@+id/textview1"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:padding="10dp"
    android:text="这是一个constrainlayout自带的流式布局Flow"
    android:textColor="@color/white"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toLeftOf="@id/guideline"
    app:layout_constraintTop_toTopOf="parent" />


<TextView
    android:id="@+id/textview2"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:padding="10dp"
    android:text="这是一个constraintlayout自带的Layer层布局"
    android:textColor="@color/white"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toLeftOf="@id/guideline"
    app:layout_constraintTop_toBottomOf="@id/textview1" />

<androidx.constraintlayout.widget.Guideline
    android:id="@+id/guideline"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    app:layout_constraintGuide_percent="0.8" />

<ImageView
    android:id="@+id/src"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:padding="10dp"
    android:src="@mipmap/ic_launcher"
    app:layout_constraintBottom_toBottomOf="@id/textview2"
    app:layout_constraintLeft_toRightOf="@id/guideline"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="@id/textview1" />

需要给管理的子控件id设置上使用app:constraint_referenced_ids,使用相当简单,另外建议把layer写在管理的子布局前面不然设置的背景可能无效,至于为什么你可以理解为帧布局,layer写在后面就会把子view覆盖无法正常显示.这样就解决了给多个子控件设置背景又套一层。不过这个控件我还没用到项目上,只是有写demo实例。

2.3 flow控件

这个控件就是我们说的流式布局,在以往我们现实这种效果需要自定义管理器,view或者第三方框架。目前google在cons中已经开源了flow控件。使用也相对简单:

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"

    >


    <androidx.constraintlayout.helper.widget.Layer
        android:layout_width="match_parent"
        android:layout_height="match_parent"


        app:constraint_referenced_ids="tv_device_name,tv_online_state,tv_switch_state2"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/tv_device_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:ellipsize="end"
        android:maxLines="1"
        android:padding="5dp"
        android:text="测试测试"
        android:textColor="@color/purple_200"
        android:textStyle="bold"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/tv_org_name"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:text="研发部dadfad打发士大夫打发范德萨"
        android:textColor="@color/purple_700"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@id/guideline"
        app:layout_constraintTop_toBottomOf="@id/tv_device_name" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.3" />

    <!--        //chain或者aligned,chain:链形式,依次挨着排,aligned会两端对齐-->
    <!--        flow_firstHorizontalStyle首行的对齐方式,packed:靠最左侧挨着排,水平间隔:horizontalGap生-->

    <!--        app:flow_horizontalBias="0" 全局水平bias,为0时,每行都贴左边,可解决中间行单独占一行时,不贴最左侧的问题-->
    <!--        flow_horizontalGap  控件水平方向上的间隔-->
    <androidx.constraintlayout.helper.widget.Flow
        android:id="@+id/flow"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="5dp"
        android:layout_marginEnd="5dp"

        app:constraint_referenced_ids="tv_type,tv_online_state,tv_switch_state,tv_switch_state2,tv_switch_state3,tv_switch_state4,tv_switch_state5"
        app:flow_firstHorizontalBias="0"
        app:flow_firstHorizontalStyle="packed"

        app:flow_horizontalGap="10dp"
        app:flow_horizontalStyle="spread_inside"
        app:flow_lastHorizontalBias="0"
        app:flow_lastHorizontalStyle="packed"
        app:flow_verticalGap="8dp"

        app:flow_wrapMode="chain"
        app:layout_constraintLeft_toRightOf="@id/guideline"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="@id/tv_org_name" />

    <TextView
        android:id="@+id/tv_type"
        android:layout_width="0dp"
        android:layout_height="wrap_content"


        android:text="自动采集看接口接gfgg"
        android:textColor="@color/black"
        app:layout_constraintWidth_default="wrap"

        />

    <TextView
        android:id="@+id/tv_online_state"
        android:layout_width="0dp"
        android:layout_height="wrap_content"

        android:text="在线"
        android:textColor="@color/black"
        app:layout_constraintWidth_default="wrap"

        />

    <TextView
        android:id="@+id/tv_switch_state"
        android:layout_width="0dp"
        android:layout_height="wrap_content"

        android:text="合位"
        android:textColor="@color/black"
        app:layout_constraintWidth_default="wrap" />

    <TextView
        android:id="@+id/tv_switch_state2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"

        android:text="的反馈进度"

        android:textColor="@color/black"
        app:layout_constraintWidth_default="wrap" />


    <TextView
        android:id="@+id/tv_switch_state3"
        android:layout_width="0dp"
        android:layout_height="wrap_content"


        android:text="的反馈进"
        android:textColor="@color/black"
        app:layout_constraintWidth_default="wrap" />

    <TextView
        android:id="@+id/tv_switch_state4"
        android:layout_width="0dp"
        android:layout_height="wrap_content"


        android:text="的反馈进度接口"
        android:textColor="@color/black"
        app:layout_constraintWidth_default="wrap" />

    <TextView
        android:id="@+id/tv_switch_state5"
        android:layout_width="0dp"
        android:layout_height="wrap_content"


        android:text="的反馈进度接口"
        android:textColor="@color/black"
        app:layout_constraintWidth_default="wrap" />
</androidx.constraintlayout.widget.ConstraintLayout>

效果图

这个控件属性较多,理解起来不难,主要是应用场景:1.列表 2.历史搜索

列表里面比较简单直接在item里面对需要自动换行的控件设置id,类似上面的布局。

第二种历史搜索我们模拟一个list<String>的集合,控件进行动态生成(flow部分):

<androidx.constraintlayout.helper.widget.Flow
    android:id="@+id/demo_flow"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    app:flow_firstHorizontalBias="0"
    app:flow_firstHorizontalStyle="packed"
    app:flow_horizontalBias="0"
    app:flow_horizontalGap="10dp"
    app:flow_horizontalStyle="spread_inside"
    app:flow_lastHorizontalBias="0"
    app:flow_lastHorizontalStyle="packed"
    app:flow_verticalGap="8dp"
    app:flow_wrapMode="chain"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toBottomOf="@id/textview2" />

可以看到在flow布局中并没有设置ids,因此在我们页面中需要动态添加才能生效,下面给出java代码:

stringList.add("哈哈哈大打瞌睡");
stringList.add("阿萨第三方收费");
stringList.add("收到反馈的弗兰克");
stringList.add("世界杯加到快及点击");
stringList.add("大幅度发");
stringList.add("反反复复的付过付过滚滚滚");
stringList.add("哦单开反馈几点开奖辅助");
stringList.add("电饭锅热豆浆大富科技的");
stringList.add("如反馈及风科技风科技的”");
stringList.add("放入局大富科技风科技局非共和国和");
        int ids[] = new int[stringList.size()];
        int localis[] = new int[]{R.id.tvUserCode, R.id.tvUserName, R.id.tvTestDate, R.id.tvHumidity, R.id.tvPercent, R.id.tvCircle, R.id.tvTestSkin, R.id.tvHirstory, R.id.tva, R.id.tvb, R.id.tvc
                , R.id.tvd
                , R.id.tve, R.id.tvf};
        for (int index = 0; index < stringList.size(); index++) {
            TextView textView = new TextView(this);
            ConstraintLayout.LayoutParams layoutParams = new ConstraintLayout.LayoutParams(ConstraintLayout.LayoutParams.WRAP_CONTENT, ConstraintLayout.LayoutParams.WRAP_CONTENT);
           layoutParams.matchConstraintDefaultWidth=ConstraintLayout.LayoutParams.WRAP_CONTENT;
            textView.setLayoutParams(layoutParams);
            textView.setId(localis[index]);
//            textView.setGravity(Gravity.START);
//            textView.setTextSize(16.0f);
            textView.setTextColor(getResources().getColor(R.color.black));
            textView.setText(stringList.get(index));
            cons.addView(textView);
            ids[index] = localis[index];
            textView.setOnClickListener(v -> {
                Log.e("您点击了", textView.getText().toString());
                Toast.makeText(MainActivity.this, "您点击了" + textView.getText(), Toast.LENGTH_SHORT).show();
            });
        }
flow.setReferencedIds(ids);

这里面重点就是setReferencedIds设置控件的id,需要传一个int[].这样我们就可以动态实现自动换行了,跟记录历史搜索功能类似,搜索内容进行自动换行。看下效果图

重点是中间部分,他实现了自动换行功能。因此在项目中我们需要自动换行时可以选择此控件实现,不需要接住第三方或者自定义。

2.4 group控件

这个辅助控件目前个人觉得功能比较单一就是分组管理,同样需要设置控件id对其进行统一管理,他与flow不同的是不能设置背景,一般是用于对其控件gone visiable的。这里就不单独贴出布局了。

总结:约束布局的其他辅助控件就不列出了,总之功能比较强大的,我们平时在项目中可能使用得不多,导致我们忽略了这个控件的优势,因此这些辅助控件还是值得大家学习,特别是layer能够统一设置控件背景。可以减少避免不必要的布局层次。

 

  

<think>好的,我现在需要帮助用户在AndroidConstraintLayout中实现子控件的居中。根据用户的问题,他们可能是指水平居中、垂直居中,或者同时水平和垂直居中。我需要先回忆ConstraintLayout的基本用法,然后结合用户提供的引用内容,特别是引用[1]中的例子,来构造正确的布局方法。首先,用户提到的引用[1]里有一个ConstraintLayout的例子,其中Button使用了app:layout_constraintLeft_toLeftOf和app:layout_constraintRight_toRightOf属性,并且设置了Horizontal_bias为0.3。这说明在ConstraintLayout中,通过将控件的左右两侧约束到父容器的左右两侧,可以实现水平方向上的居中,而bias属性可以调整位置的比例。如果用户想要居中,可能需要将bias设为0.5,或者不设置,因为默认情况下居中。不过,用户的问题是如何居中,所以可能需要同时约束左右和上下,或者根据具体方向进行调整。接下来,我需要确认在ConstraintLayout中实现居中的几种常见方法。例如,水平居中通常需要将start和end约束到父容器的start和end;垂直居中则需要将top和bottom约束到父容器的top和bottom。同时,如果需要在父容器中完全居中,可能需要四个约束:左右上下都约束到父容器,这样控件就会居中。此外,还可以使用chain的方式或者guideline来辅助布局,但用户的问题可能更倾向于基本方法。然后,我需要检查是否有其他属性或方法可以实现居中。例如,使用layout_constraintCircle属性或者百分比布局,但可能这些方法较为复杂,而用户可能需要的是最直接的解决方案。根据引用[1]中的例子,使用左右约束到父容器,并且可能调整bias,这应该是最直接的方式。另外,用户可能希望看到代码示例,所以需要给出一个具体的XML布局例子,展示如何将TextView或Button居中。同时,可能需要解释每个属性的作用,比如约束到父容器、设置bias等。此外,还要注意是否需要设置控件的宽度和高度,例如使用wrap_content或0dp(match_constraint)。最后,需要确保回答结构清晰,分步骤说明水平和垂直居中的方法,并提供代码示例。同时,根据用户之前的提问历史,可能还需要生成相关问题,如如何处理多个控件的居中、如何动态调整位置等。</think>### 在 ConstraintLayout 中将子控件居中的方法 #### 一、水平居中 通过将控件的**左右边界**同时约束到父容器的左右边界实现水平居中: ```xml <Button android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" /> ``` - `layout_constraintLeft_toLeftOf="parent"`:左边界对齐父容器左边界 - `layout_constraintRight_toRightOf="parent"`:右边界对齐父容器右边界 - 控件宽度建议设为 `wrap_content` 或 `0dp`(即 `match_constraint`)[^1] #### 二、垂直居中 通过将控件的**上下边界**同时约束到父容器的上下边界实现垂直居中: ```xml <Button android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" /> ``` #### 三、完全居中(水平 + 垂直) 同时约束四个方向: ```xml <Button android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" /> ``` #### 四、使用 Bias 调整偏移比例 若需微调位置,可添加 `layout_constraintHorizontal_bias` 或 `layout_constraintVertical_bias`: ```xml <Button ... app:layout_constraintHorizontal_bias="0.3" <!-- 水平偏移比例 0.0~1.0 --> app:layout_constraintVertical_bias="0.8" /> <!-- 垂直偏移比例 --> ``` #### 五、动态调整示例(结合代码) 若需通过代码动态居中,可修改约束参数: ```kotlin val constraintSet = ConstraintSet() constraintSet.clone(parentLayout) constraintSet.centerHorizontally(childView.id, ConstraintSet.PARENT_ID) constraintSet.applyTo(parentLayout) ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值