我有一个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,这也是约束布局测试版中的新功能,但是当孩子被标记为已经消失时,它不会调整。
答案 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);
这会以轻微的方式弄乱它,因为它会推动左侧屏幕更宽的视图。也许你可以解决这个问题,因为我现在还不能。