将 ConstraintLayout 项目对齐到两个项目的末尾
Align ConstraintLayout item to be at the end of two items
我有一个 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 的目的,它旨在消除嵌套 children.
编辑:我在下面附上了一个示例:
<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>
在这种情况下,预览应该在中间某处显示 "View C",因为它的偏差为 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,它在约束布局测试版中也是新的,但是当 children 被标记为消失时它不会调整。
我在我的 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);
这最终会稍微弄乱它,因为它会将更宽的视图推出左侧屏幕。也许你可以解决这个问题,因为我目前无法解决。
这可以使用新的 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>
如何使用障碍?
障碍就像建造一堵 "protects" constraint_referenced_ids
中提到的观点的 HUUUUGE WALL。所以,你必须指出它是 "supposed to keep out" 的方向,在我们的例子中是正确的 (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'
希望这对您有所帮助!
我有一个 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 的目的,它旨在消除嵌套 children.
编辑:我在下面附上了一个示例:
<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>
在这种情况下,预览应该在中间某处显示 "View C",因为它的偏差为 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,它在约束布局测试版中也是新的,但是当 children 被标记为消失时它不会调整。
我在我的 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);
这最终会稍微弄乱它,因为它会将更宽的视图推出左侧屏幕。也许你可以解决这个问题,因为我目前无法解决。
这可以使用新的 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>
如何使用障碍?
障碍就像建造一堵 "protects" constraint_referenced_ids
中提到的观点的 HUUUUGE WALL。所以,你必须指出它是 "supposed to keep out" 的方向,在我们的例子中是正确的 (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'
希望这对您有所帮助!