ConstraintLayout 以相同的宽度在内部展开视图
ConstraintLayout spread views inside with same width
我希望水平对齐四个按钮并满足这些条件:
- 他们的文字是 25%、50%、75%、100%(所以最后一个会更宽)
- 它们应该具有相同的宽度
- 他们应该把剩下的 space
是否可以使用 ConstraintLayout 实现此目的?
为了演示我到底想要什么,请查看我的布局的当前状态(没问题):
当前按钮的宽度设置为父按钮的 25%,它们之间有 static 边距(使用 LinearLayout 实现)。问题是什么?在小屏幕上,边距可能导致最后一个按钮被截断(如下图),或者在大屏幕上,按钮太大。
所以我希望 ConstraintLayout 的展开行为除了最后一个按钮的宽度为 wrap_content
并且其他按钮的宽度设置为等于最后一个按钮。
这就是我想出的:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">
<Button
android:id="@+id/tv_25"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginLeft="16dp"
android:text="25%"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/tv_50"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/tv_50"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginLeft="16dp"
android:text="50%"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintLeft_toRightOf="@id/tv_25"
app:layout_constraintRight_toLeftOf="@id/tv_75"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/tv_75"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginLeft="16dp"
android:text="75%"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintLeft_toRightOf="@id/tv_50"
app:layout_constraintRight_toLeftOf="@id/tv_100"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/tv_100"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:text="100%"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintLeft_toRightOf="@id/tv_75"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
解释:我用过app:layout_constraintHorizontal_chainStyle="spread"。使用链在均匀分布视图时考虑了边距。
Using chain style spread might be you got your expected layout.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">
<Button
android:id="@+id/btn_25"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/entercode_default"
android:text="25%"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/btn_50"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_50"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/entercode_default"
android:text="50%"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/btn_75"
app:layout_constraintStart_toEndOf="@+id/btn_25"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_75"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/entercode_default"
android:text="75%"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/btn_100"
app:layout_constraintStart_toEndOf="@+id/btn_50"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_100"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/entercode_default"
android:text="100%"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/btn_75"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
感谢@cheticamp 和他提供的答案 ,实现所需行为的最佳方法是编写一个简单的 ConstraintHelper
,将所有子项的宽度设置为其中的最大值。
class MaxWidthConstraint @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : ConstraintHelper(context, attrs, defStyleAttr) {
override fun updatePostMeasure(container: ConstraintLayout) {
val maxWidth =
referencedIds.asSequence().map { container.getViewById(it) }
.map { container.getViewWidget(it) }
.map { it.width }
.max() ?: 0
referencedIds.asSequence().map { container.getViewById(it) }
.map { container.getViewWidget(it) }
.forEach { it.width = maxWidth }
}
}
因此布局代码为:
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:ignore="HardcodedText">
<Button
android:id="@+id/btn_25"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="25%"
android:textAlignment="center"
app:layout_constraintEnd_toStartOf="@id/btn_50"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_50"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="50%"
app:layout_constraintEnd_toStartOf="@id/btn_75"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintStart_toEndOf="@id/btn_25"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_75"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="75%"
app:layout_constraintEnd_toStartOf="@id/btn_100"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintStart_toEndOf="@id/btn_50"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_100"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="100%"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintStart_toEndOf="@id/btn_75"
app:layout_constraintTop_toTopOf="parent" />
<com.myapplication.widgets.MaxWidthConstraint
android:layout_width="0dp"
android:layout_height="0dp"
app:constraint_referenced_ids="btn_25,btn_50,btn_75,btn_100"
tools:ignore="MissingConstraints" />
</androidx.constraintlayout.widget.ConstraintLayout>
我希望水平对齐四个按钮并满足这些条件:
- 他们的文字是 25%、50%、75%、100%(所以最后一个会更宽)
- 它们应该具有相同的宽度
- 他们应该把剩下的 space
是否可以使用 ConstraintLayout 实现此目的?
为了演示我到底想要什么,请查看我的布局的当前状态(没问题):
当前按钮的宽度设置为父按钮的 25%,它们之间有 static 边距(使用 LinearLayout 实现)。问题是什么?在小屏幕上,边距可能导致最后一个按钮被截断(如下图),或者在大屏幕上,按钮太大。
所以我希望 ConstraintLayout 的展开行为除了最后一个按钮的宽度为 wrap_content
并且其他按钮的宽度设置为等于最后一个按钮。
这就是我想出的:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">
<Button
android:id="@+id/tv_25"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginLeft="16dp"
android:text="25%"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/tv_50"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/tv_50"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginLeft="16dp"
android:text="50%"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintLeft_toRightOf="@id/tv_25"
app:layout_constraintRight_toLeftOf="@id/tv_75"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/tv_75"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginLeft="16dp"
android:text="75%"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintLeft_toRightOf="@id/tv_50"
app:layout_constraintRight_toLeftOf="@id/tv_100"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/tv_100"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:text="100%"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintLeft_toRightOf="@id/tv_75"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
解释:我用过app:layout_constraintHorizontal_chainStyle="spread"。使用链在均匀分布视图时考虑了边距。
Using chain style spread might be you got your expected layout.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">
<Button
android:id="@+id/btn_25"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/entercode_default"
android:text="25%"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/btn_50"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_50"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/entercode_default"
android:text="50%"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/btn_75"
app:layout_constraintStart_toEndOf="@+id/btn_25"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_75"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/entercode_default"
android:text="75%"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/btn_100"
app:layout_constraintStart_toEndOf="@+id/btn_50"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_100"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/entercode_default"
android:text="100%"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/btn_75"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
感谢@cheticamp 和他提供的答案 ConstraintHelper
,将所有子项的宽度设置为其中的最大值。
class MaxWidthConstraint @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : ConstraintHelper(context, attrs, defStyleAttr) {
override fun updatePostMeasure(container: ConstraintLayout) {
val maxWidth =
referencedIds.asSequence().map { container.getViewById(it) }
.map { container.getViewWidget(it) }
.map { it.width }
.max() ?: 0
referencedIds.asSequence().map { container.getViewById(it) }
.map { container.getViewWidget(it) }
.forEach { it.width = maxWidth }
}
}
因此布局代码为:
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:ignore="HardcodedText">
<Button
android:id="@+id/btn_25"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="25%"
android:textAlignment="center"
app:layout_constraintEnd_toStartOf="@id/btn_50"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_50"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="50%"
app:layout_constraintEnd_toStartOf="@id/btn_75"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintStart_toEndOf="@id/btn_25"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_75"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="75%"
app:layout_constraintEnd_toStartOf="@id/btn_100"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintStart_toEndOf="@id/btn_50"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_100"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="100%"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintStart_toEndOf="@id/btn_75"
app:layout_constraintTop_toTopOf="parent" />
<com.myapplication.widgets.MaxWidthConstraint
android:layout_width="0dp"
android:layout_height="0dp"
app:constraint_referenced_ids="btn_25,btn_50,btn_75,btn_100"
tools:ignore="MissingConstraints" />
</androidx.constraintlayout.widget.ConstraintLayout>