将ConstraintLayout项目对齐到两个项目的末尾

时间:2017-06-11 19:14:21

标签: android android-layout android-constraintlayout

我有一个ConstraintLayout,它有两个垂直堆叠的视图A和B.我有第三个视图C,它需要水平地到达A和B的末尾。在任何给定点,A可以比B宽,反之亦然,因此约束不仅可以基于一个视图。有没有办法通过视图C来定义这个约束?

目前,我可以定义A和B以便

app:layout_constraintEnd_toStartOf="C"

这确实有效,但由于C中没有开始约束,设计预览将无法正确绘制其他属性,例如

app:layout_constraintHorizontal_bias="1.0"

另一种选择可能是以某种方式将A组和B组分组。大多数关于分组的问题都是关于链的问题,我认为这些问题无法解决这个问题。添加另一个视图来包装这两个也似乎打败了ConstraintLayout的目的,它旨在消除嵌套的子节点。

编辑:我在下面附上了一个例子:

<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="wrap_content">

    <TextView
        android:id="@+id/view_c"
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        android:layout_marginStart="16dp"
        android:text="View C"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.5" />

    <TextView
        android:id="@+id/view_a"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:text="View A"
        app:layout_constraintBottom_toTopOf="@id/view_b"
        app:layout_constraintEnd_toStartOf="@id/view_c"
        app:layout_constraintHorizontal_bias="0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_goneMarginBottom="16dp" />

    <TextView
        android:id="@+id/view_b"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="16dp"
        android:text="View B"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@id/view_c"
        app:layout_constraintHorizontal_bias="0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/view_a" />

</android.support.constraint.ConstraintLayout>

在这种情况下,预览应显示&#34;查看C&#34;因为它的偏差是0.5,所以在中间的某个地方。但是,它不知道它的起始界限,因为它们在view_a和view_b中定义,因此坚持正确。

解决方案:

以下是我的最终布局

<?xml version="1.0" encoding="utf-8"?>

<!--due to animations, we need a wrapper viewgroup so our changes will stick-->

<LinearLayout 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:background="?android:attr/selectableItemBackground"
    android:baselineAligned="false"
    android:clipToPadding="false"
    android:minHeight="?android:attr/listPreferredItemHeightSmall"
    android:orientation="horizontal"
    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
    android:paddingStart="?android:attr/listPreferredItemPaddingStart">

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

        <!--As per Android N, icons (24dp) are aligned to the left rather than centered-->

        <ImageView
            android:id="@+id/kau_pref_icon"
            android:layout_width="56dp"
            android:layout_height="56dp"
            android:layout_marginBottom="4dp"
            android:layout_marginTop="4dp"
            android:contentDescription="@string/kau_pref_icon"
            android:paddingEnd="32dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.5"
            tools:layout_editor_absoluteX="0dp" />

        <TextView
            android:id="@+id/kau_pref_title"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:ellipsize="marquee"
            android:textAppearance="?android:attr/textAppearanceListItem"
            android:textColor="?android:attr/textColorPrimary"
            app:layout_constraintBottom_toTopOf="@+id/kau_pref_desc"
            app:layout_constraintEnd_toStartOf="@+id/kau_pref_inner_frame"
            app:layout_constraintHorizontal_bias="0"
            app:layout_constraintStart_toEndOf="@id/kau_pref_icon"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_goneMarginBottom="16dp"
            tools:layout_editor_absoluteX="-175dp" />

        <TextView
            android:id="@id/kau_pref_desc"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginBottom="16dp"
            android:ellipsize="end"
            android:maxLines="10"
            android:textAppearance="?android:attr/textAppearanceListItemSecondary"
            android:textColor="?android:attr/textColorSecondary"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@id/kau_pref_inner_frame"
            app:layout_constraintHorizontal_bias="0"
            app:layout_constraintStart_toEndOf="@id/kau_pref_icon"
            app:layout_constraintTop_toBottomOf="@id/kau_pref_title"
            tools:layout_editor_absoluteX="-175dp" />

        <android.support.constraint.Barrier
            android:id="@+id/kau_pref_barrier"
            android:layout_width="1dp"
            android:layout_height="wrap_content"
            app:constraint_referenced_ids="kau_pref_title,kau_pref_desc"
            app:barrierDirection="end"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent" />

        <LinearLayout
            android:id="@id/kau_pref_inner_frame"
            android:layout_width="wrap_content"
            android:layout_height="0dp"
            android:gravity="center_vertical|end"
            android:orientation="horizontal"
            android:paddingStart="16dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="1.0"
            app:layout_constraintStart_toEndOf="@id/kau_pref_barrier"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.5"
            tools:layout_editor_absoluteX="1dp" />

    </android.support.constraint.ConstraintLayout>

</LinearLayout>

有标题和描述,内部内容必须在两个视图的末尾。我也尝试过Group,这也是约束布局测试版中的新功能,但是当孩子被标记为已经消失时,它不会调整。

Resulting layout

2 个答案:

答案 0 :(得分:7)

使用新的Barriers功能可以轻松实现这一点。

<?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="wrap_content">

    <TextView
        android:id="@+id/view_c"
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        android:text="View C"
        app:layout_constraintLeft_toRightOf="@+id/barrier1"
        app:layout_constraintTop_toTopOf="parent" />

    <android.support.constraint.Barrier
        android:id="@+id/barrier1"
        android:layout_width="1dp"
        android:layout_height="wrap_content"
        app:barrierDirection="right"
        app:constraint_referenced_ids="view_a, view_b"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/view_a"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:text="View A"
        app:layout_constraintBottom_toTopOf="@id/view_b"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_goneMarginBottom="16dp" />

    <TextView
        android:id="@+id/view_b"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:layout_marginBottom="16dp"
        android:text="View B"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/view_a" />

</android.support.constraint.ConstraintLayout>

如何使用障碍?

障碍就像建立一个“保护”constraint_referenced_ids中提到的观点的HUUUUGE WALL。所以,你必须提到它“应该禁止”的方向,在我们的例子中是正确的(view_c)。只需使用barrierDirection属性即可。
最后,不要忘记确保view_c位于禁区(layout_constraintLeft_toRightOf="@+id/barrier1")。

由于此功能仅在ConstraintLayout的1.1.0 beta1版本中可用,因此不要忘记将此行添加到build.gradle文件中。

compile 'com.android.support.constraint:constraint-layout:1.1.0-beta1'


希望这有帮助!

答案 1 :(得分:0)

我在我的IDE中尝试了这个,我想出了一些在运行时动态执行的代码

TextView viewa = (TextView) findViewById(R.id.view_a);
TextView viewb = (TextView) findViewById(R.id.view_b);

ConstraintLayout cl = (ConstraintLayout) findViewById(R.id.constraintLayout);
ConstraintSet cs = new ConstraintSet();
cs.clone(cl);
cs.connect(viewb.getWidth() > viewa.getWidth() ? R.id.view_b : R.id.view_a, ConstraintSet.RIGHT, R.id.view_c, ConstraintSet.LEFT);
cs.applyTo(cl);

这会以轻微的方式弄乱它,因为它会推动左侧屏幕更宽的视图。也许你可以解决这个问题,因为我现在还不能。