android-如何使用ConstraintLayout将多个视图集中在一起?

背景

Google宣布了一种称为“ ConstraintLayout”的新布局,该布局应该是最终布局,可以代替所有布局,同时保持平坦(无嵌套布局)并具有更好的性能。

问题

事实是,除了Google IO上展示的视频外,我几乎看不到任何可以帮助我解决此问题的教程。

考虑到我在另一个布局中有一个垂直居中的LinearLayout,我要尝试将它们都转换为一个ConstraintLayout。

毕竟,这就是这种新布局的目的。

我希望处理的布局如下所示:

enter image description here

请注意,中心的视图仅垂直居中,而两个textViews位于ImageView的右侧,ImageView也是垂直居中。

这一切都与RelativeLayout配合使用,后者具有2个TextViews的LinearLayout,但我想知道如何将它们转换为单个ConstraintLayout。

这是我显示的示例XML:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    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"
    android:minHeight="?attr/listPreferredItemHeightSmall">

    <ImageView
        android:id="@+id/appIconImageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_centerVertical="true"
        android:layout_marginEnd="4dp"
        android:layout_marginLeft="2dp"
        android:layout_marginRight="4dp"
        android:layout_marginStart="2dp"
        android:adjustViewBounds="true"
        android:src="@android:drawable/sym_def_app_icon"
        tools:ignore="ContentDescription"/>

    <LinearLayout
        android:id="@+id/appDetailsContainer"
        android:layout_width="0px"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_toEndOf="@+id/appIconImageView"
        android:layout_toLeftOf="@+id/overflowView"
        android:layout_toRightOf="@+id/appIconImageView"
        android:layout_toStartOf="@+id/overflowView"
        android:orientation="vertical">

        <TextView
            android:id="@+id/appLabelTextView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ellipsize="marquee"
            android:text="label"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:textDirection="locale"
            tools:ignore="HardcodedText,UnusedAttribute"/>

        <TextView
            android:id="@+id/appDescriptionTextView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ellipsize="marquee"
            android:minLines="3"
            android:text="description"
            android:textAppearance="?android:attr/textAppearanceSmall"
            android:textDirection="locale"
            tools:ignore="HardcodedText,UnusedAttribute"/>
    </LinearLayout>

    <ImageView
        android:id="@+id/overflowView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:adjustViewBounds="true"
        android:background="?attr/selectableItemBackground"
        android:clickable="true"
        android:padding="10dp"
        app:srcCompat="@drawable/ic_more_vert_black_24dp"

        tools:src="@drawable/ic_more_vert_black_24dp"
        tools:ignore="ContentDescription"/>

    <ImageView
        android:id="@+id/isSystemAppImageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignEnd="@+id/overflowView"
        android:layout_alignLeft="@+id/overflowView"
        android:layout_alignParentBottom="true"
        android:layout_alignRight="@+id/overflowView"
        android:layout_alignStart="@+id/overflowView"
        android:adjustViewBounds="true"
        android:scaleType="centerInside"
        app:srcCompat="@drawable/ic_warning_black_24dp"
        tools:ignore="ContentDescription"
        tools:src="@drawable/ic_warning_black_24dp"/>

</RelativeLayout>

我尝试了什么

我试图阅读一些文章并观看一些Google视频:

  • [https://codelabs.developers.google.com/codelabs/constraint-layout/index.html#0]
  • [https://www.youtube.com/watch?v=sO9aX87hq9c]
  • [https://youtu.be/csaXml4xtN8?t=1693]

那没有帮助,所以我尝试使用它,希望自己能找到使用方法。但是我不知道该怎么做。 我尝试使用该功能转换布局,但这会使视图变得一团糟,并增加了我不想拥有的额外边距。

问题

如何将2个布局转换为单个ConstraintLayout?

5个解决方案
61 votes

在这里看看我的答案。

app:layout_constraintHorizontal_chainStyle="packed"包含一项功能-app:layout_constraintHorizontal_chainStyle="packed"-该功能可实现您所要求的内容:

链在单个轴上(水平或垂直)提供类组行为   垂直)。

如果一组小部件通过链接在一起,则被视为链   双向连接

创建链后,有两种可能性:

  • 将元素散布在可用空间中
  • 链也可以“打包”,在这种情况下,元素可以组合在一起

对于您的情况,您必须打包app:layout_constraintHorizontal_chainStyle="packed"app:layout_constraintVertical_chainPacked="true" TextView,并将其垂直居中放置在父级中:

(确保您使用支持链的app:layout_constraintHorizontal_chainStyle="packed"版本)

<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="16dp"
        android:text="TextView"
        app:layout_constraintBottom_toTopOf="@+id/button"
        app:layout_constraintLeft_toRightOf="@+id/imageView2"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintHorizontal_chainStyle="packed"/>

    <TextView
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="16dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:text="Button\nMkay"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toRightOf="@+id/imageView2"
        app:layout_constraintTop_toBottomOf="@+id/textView"/>

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="16dp"
        android:layout_marginTop="16dp"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@mipmap/ic_launcher"/>

    <ImageView
        android:id="@+id/imageView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="16dp"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@mipmap/ic_launcher"/>

    <ImageView
        android:id="@+id/imageView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="16dp"
        android:layout_marginEnd="16dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:srcCompat="@mipmap/ic_launcher"/>
</android.support.constraint.ConstraintLayout>

更新25-06-2019(@Saeid Z):

现在在约束布局1.1.3中,我们必须使用app:layout_constraintHorizontal_chainStyle="packed"而不是app:layout_constraintVertical_chainPacked="true"

Yury Fedorov answered 2020-02-13T22:49:10Z
10 votes

要使某些内容垂直或水平居中,请在布局上设置相反的约束。

垂直居中

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

水平居中

    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
Kevin answered 2020-02-13T22:49:39Z
5 votes

app:layout_constraintVertical_bias="0.5"设置为需要垂直居中的视图,bias属性仅在您指定边界约束时才有效(例如,顶部和底部为垂直偏移,左侧和右侧为水平偏移)

一个例子:

<android.support.constraint.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/constraintLayout">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="@id/constraintLayout"
        app:layout_constraintBottom_toBottomOf="@id/constraintLayout"
        app:layout_constraintVertical_bias="0.5" />

</android.support.constraint.ConstraintLayout>

在我的布局中可以使用它:[https://github.com/hidroh/tldroid/blob/master/app/src/main/res/layout/activity_main.xml,]非常相似的布局,尽管我将其放置在 屏幕高度的1/3。

enter image description here

hidro answered 2020-02-13T22:50:08Z
5 votes

编辑:在链可用之前就已经写了这个答案。 请现在使用链条,请参见上面的答案:[https://stackoverflow.com/a/40102296/1402641]


现在,我相信您唯一的选择是将两个文本视图包装在另一个布局中-可能线性布局最适合这种情况。

但是约束布局背后的团队表示,他们想引入“虚拟容器”,正是这种虚拟容器适用于这种用例:将两个或多个视图组合在一起,并在容器上设置约束(例如垂直居中)。 这个想法是,它不是约束布局内部的完全嵌套布局,而只是约束布局用来定位其子元素的东西-因此,它应该比嵌套提供更好的性能。

他们在I / O谈话中提到了这一点(链接到确切的时间)。 所以我想保持关注。

Marcin Koziński answered 2020-02-13T22:50:42Z
2 votes

看一下我的示例(ConstraintLayout中的中心组件)

现在,您可以将“图像”居中(约束左上-底部),将“标签”顶部约束到“图像”顶部,将“描述”顶部约束到“标签”底部。在下面的示例中,我将按钮高度与右侧的两个textview匹配(这是您的情况)。 其他文本视图受上述链接的约束。

enter image description here

更新:在下面回答您的评论:

我已经安装了您的应用,这是我目前唯一能想到的。 由于它是ViewHolder布局,因此可以将layout_height设置为wrap_content,也可以根据需要对其进行修复。 如果您愿意,我可以向您发送xml,我不想泛滥答案。

顶部TextView的左约束被限制为ImageView的右约束。 另外,top TextView-> top约束被限制在容器的顶部,所以是正确的。 底部TextView被限制在容器的底部。 中间的TextView被约束为匹配顶部TextView的宽度,并且与ImageView没有任何关系。

enter image description here

bajicdusko answered 2020-02-13T22:51:21Z
translate from https://stackoverflow.com:/questions/37507057/how-to-center-multiple-views-together-using-constraintlayout