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

and*_*per 49 android android-layout android-constraintlayout

背景

谷歌已经宣布了一种名为" ConstraintLayout " 的新布局,它应该是最终布局,可以在保持平坦(没有嵌套布局)的同时取代所有布局,并且具有更好的性能.

问题

事情是,我几乎没有看到任何可以帮助我解决这个问题的教程,除了在Google IO上展示的视频.

我想要做的是,假设我在另一个布局中有一个垂直居中的LinearLayout - 将它们转换为单个ConstraintLayout.

毕竟,这是这个新布局的目的......

我想要处理的布局如下:

在此输入图像描述

请注意,中心的视图仅垂直居中,并且2个textView位于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>
Run Code Online (Sandbox Code Playgroud)

我尝试了什么

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

这没有帮助,所以我尝试使用它,希望我自己能找到如何使用它.但我无法找到如何做到这一点.我尝试使用该功能来转换布局,但这会使视图变得非常混乱,并且会增加我不希望拥有的额外边距.

这个问题

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

Yur*_*rov 64

看看我的答案在这里.

ContraintLayout包含一个功能 - Chains这使您可以实现您的要求:

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

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

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

  • 在可用空间中传播元素
  • 链也可以"打包",在这种情况下,元素被组合在一起

至于你的情况,你必须打包你的labeldescriptionTextViews并将它们垂直居中在你的父级:

(确保使用ConstraintLayout支持链的版本)

<?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>
Run Code Online (Sandbox Code Playgroud)

  • 它如何将视图组合在一起? (2认同)
  • 我不知道实现细节。我所知道的是,在约束中相互引用的视图构成了一个链,其行为由其第一个成员定义。 (2认同)
  • @Yury Fedorov谢谢。现在在约束布局1.1.3中,我们必须使用app:layout_constraintHorizo​​ntal_chainStyle =“ packed”而不是app:layout_constraintVertical_chainPacked =“ true” (2认同)

小智 9

要垂直或水平居中,请在布局上设置相反的约束.

垂直居中

    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
Run Code Online (Sandbox Code Playgroud)

水平居中

    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
Run Code Online (Sandbox Code Playgroud)

  • 这个唯一的中心单一视图 (8认同)
  • 请先看这个[how-to-answer](https://stackoverflow.com/help/how-to-answer) 这个问题之前已经回答过,显然,你可以在这里添加你的答案。但在回答之前您需要了解一些要点。首先,不要添加之前使用相同代码或建议添加的答案。其次,如果用户非常具体地询问了问题以及他需要什么来解决这个问题,则不要添加过于复杂的答案。第三,如果您想对答案或问题提出任何建议,您可以添加评论。 (2认同)

hid*_*dro 5

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

一个例子:

<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>
Run Code Online (Sandbox Code Playgroud)

得到它在我的布局工作:https://github.com/hidroh/tldroid/blob/master/app/src/main/res/layout/activity_main.xml,几乎相似的布局,虽然我把事情定位在1 /屏幕高度的第3位.

在此输入图像描述


Mar*_*ski 5

编辑:这个答案是在链条可用之前编写的.请立即使用链,请参阅上面的答案:https://stackoverflow.com/a/40102296/1402641


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

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

他们在他们的I/O谈话中提到它(与确切的时间相关联).所以我想请继续关注.