在 ConstraintLayout 中处理 GONE 视图拼图
Handling GONE views puzzle in ConstraintLayout
我有一个看起来足够简单的布局,但事实证明,仅使用 xml 即可实现相当棘手的行为,即仅使用 ConstraintLayout 的功能,而不必以编程方式执行任何操作。
我考虑过障碍和指导方针以及许多没有成功的场景和试验;所以这是我最后的希望,也许其他人知道我不知道的事情。
这是我的谜题:
- 如果 3 行可见 -> 图像应位于第 1 行和第 1 行之间
2
- 如果有 2 行可见 -> 图像应在第 1 行和第 1 行之间居中
第 2 行
- 如果 1 行可见 (label_text) -> 图像应在父级中居中,或者
居中对齐第 1 行 (label_text)
这里有一些图片来说明:
3 行 - 正确
2 行 - 正确
1 行不正确,但到目前为止我能得到的最好结果 [当只有标签可见时]
1 行按我希望的方式更正 [当只有标签可见时]
代码:
<androidx.constraintlayout.widget.ConstraintLayout
style="@style/V2.ItemList.Background"
android:minHeight="@dimen/item_minimum_height"
android:paddingVertical="@dimen/=margin_vertical">
<ImageView
android:id="@+id/icon"
app:layout_constraintBottom_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="parent"
tools:src="@drawable/ic_img"
tools:visibility="visible" />
<TextView
android:id="@+id/label_text"
app:layout_constraintBottom_toTopOf="@id/line1_text"
app:layout_constraintEnd_toStartOf="@id/right_content"
app:layout_constraintStart_toEndOf="@id/icon_start"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed"
tools:text="Label" />
<TextView
android:id="@+id/line1_text"
android:layout_marginTop="4dp"
app:layout_constraintBottom_toTopOf="@id/line2_text"
app:layout_constraintEnd_toStartOf="@id/right_content"
app:layout_constraintStart_toEndOf="@id/icon"
app:layout_constraintTop_toBottomOf="@id/label_text"
tools:text="Line 1"
tools:visibility="gone" />
<TextView
android:id="@+id/line2_text"
android:layout_marginTop="4dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/right_content"
app:layout_constraintStart_toEndOf="@id/icon"
app:layout_constraintTop_toBottomOf="@id/line1_text"
tools:text="Line 2"
tools:visibility="gone" />
</androidx.constraintlayout.widget.ConstraintLayout>
非常感谢任何帮助!
更新
请参阅下面的 Cheticamp 的回答,这是最好的解决方案,但如果它对其他人有用,如果我找不到 xml 唯一的解决方案,这就是我打算以编程方式进行的方式:
private fun adjustConstraints() {
if(binding.line1Text.isGone && binding.line1Text.isGone) {
ConstraintSet().apply {
clone(binding.itemListLayout)
// Adjust left/start content for single line
connect(
R.id.icon,
ConstraintSet.TOP,
R.id.item_list_layout,
ConstraintSet.TOP
)
connect(
R.id.icon,
ConstraintSet.BOTTOM,
R.id.item_list_layout,
ConstraintSet.BOTTOM
)
// Adjust right/end content for single line
connect(
R.id.right_content,
ConstraintSet.TOP,
R.id.item_list_layout,
ConstraintSet.TOP
)
connect(
R.id.right_content,
ConstraintSet.BOTTOM,
R.id.item_list_layout,
ConstraintSet.BOTTOM
)
}.also {
it.applyTo(binding.itemListLayout)
}
}
}
将 ImageView 约束到 label_text 的顶部和 [=20 的底部=].
<ImageView
android:id="@+id/icon"
app:layout_constraintTop_toTopOf="@id/label_text"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="@id/line1_text"
tools:src="@drawable/ic_img"
tools:visibility="visible" />
我有一个看起来足够简单的布局,但事实证明,仅使用 xml 即可实现相当棘手的行为,即仅使用 ConstraintLayout 的功能,而不必以编程方式执行任何操作。
我考虑过障碍和指导方针以及许多没有成功的场景和试验;所以这是我最后的希望,也许其他人知道我不知道的事情。
这是我的谜题:
- 如果 3 行可见 -> 图像应位于第 1 行和第 1 行之间 2
- 如果有 2 行可见 -> 图像应在第 1 行和第 1 行之间居中 第 2 行
- 如果 1 行可见 (label_text) -> 图像应在父级中居中,或者 居中对齐第 1 行 (label_text)
这里有一些图片来说明:
3 行 - 正确
2 行 - 正确
1 行不正确,但到目前为止我能得到的最好结果 [当只有标签可见时]
1 行按我希望的方式更正 [当只有标签可见时]
代码:
<androidx.constraintlayout.widget.ConstraintLayout
style="@style/V2.ItemList.Background"
android:minHeight="@dimen/item_minimum_height"
android:paddingVertical="@dimen/=margin_vertical">
<ImageView
android:id="@+id/icon"
app:layout_constraintBottom_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="parent"
tools:src="@drawable/ic_img"
tools:visibility="visible" />
<TextView
android:id="@+id/label_text"
app:layout_constraintBottom_toTopOf="@id/line1_text"
app:layout_constraintEnd_toStartOf="@id/right_content"
app:layout_constraintStart_toEndOf="@id/icon_start"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed"
tools:text="Label" />
<TextView
android:id="@+id/line1_text"
android:layout_marginTop="4dp"
app:layout_constraintBottom_toTopOf="@id/line2_text"
app:layout_constraintEnd_toStartOf="@id/right_content"
app:layout_constraintStart_toEndOf="@id/icon"
app:layout_constraintTop_toBottomOf="@id/label_text"
tools:text="Line 1"
tools:visibility="gone" />
<TextView
android:id="@+id/line2_text"
android:layout_marginTop="4dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/right_content"
app:layout_constraintStart_toEndOf="@id/icon"
app:layout_constraintTop_toBottomOf="@id/line1_text"
tools:text="Line 2"
tools:visibility="gone" />
</androidx.constraintlayout.widget.ConstraintLayout>
非常感谢任何帮助!
更新
请参阅下面的 Cheticamp 的回答,这是最好的解决方案,但如果它对其他人有用,如果我找不到 xml 唯一的解决方案,这就是我打算以编程方式进行的方式:
private fun adjustConstraints() {
if(binding.line1Text.isGone && binding.line1Text.isGone) {
ConstraintSet().apply {
clone(binding.itemListLayout)
// Adjust left/start content for single line
connect(
R.id.icon,
ConstraintSet.TOP,
R.id.item_list_layout,
ConstraintSet.TOP
)
connect(
R.id.icon,
ConstraintSet.BOTTOM,
R.id.item_list_layout,
ConstraintSet.BOTTOM
)
// Adjust right/end content for single line
connect(
R.id.right_content,
ConstraintSet.TOP,
R.id.item_list_layout,
ConstraintSet.TOP
)
connect(
R.id.right_content,
ConstraintSet.BOTTOM,
R.id.item_list_layout,
ConstraintSet.BOTTOM
)
}.also {
it.applyTo(binding.itemListLayout)
}
}
}
将 ImageView 约束到 label_text 的顶部和 [=20 的底部=].
<ImageView
android:id="@+id/icon"
app:layout_constraintTop_toTopOf="@id/label_text"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="@id/line1_text"
tools:src="@drawable/ic_img"
tools:visibility="visible" />