是否可以使用单个 Android ConstraintLayout 可配置的水平或垂直方向?
Is it possible to have single Android ConstraintLayout configurable Horizontal or Vertical Orientation?
我想用 ConstraintLayout 编写一个可重用的自定义视图,并且只有 1 个布局文件(如果可能)。我想要一个 "simple" 基于自定义视图上的方法的 3 个按钮的垂直或水平排列,例如 "setVertical()" 默认为水平等
我显然可以使用不同的布局文件来执行此操作,但我更喜欢更简洁的单文件解决方案。
这可能吗?如果可能,怎么做?
这会通过 AttributeSet 完成吗?
正如有人在评论中所说,你不能直接这样做。您必须手动更改 ConstraintLayout 上的约束才能更改方向。这是我设法做到的:
自定义视图class:
class CustomView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0)
: ConstraintLayout(context, attrs, defStyleAttr) {
var orientation = -1
set(value) {
if (field == value) return
field = value
val constraints = ConstraintSet()
constraints.clone(this)
when (orientation) {
HORIZONTAL -> {
constraints.createHorizontalChainRtl(ConstraintSet.PARENT_ID, ConstraintSet.START, ConstraintSet.PARENT_ID,
ConstraintSet.END, CHAIN_IDS, null, ConstraintSet.CHAIN_SPREAD)
for (id in CHAIN_IDS) {
constraints.centerVertically(id, ConstraintSet.PARENT_ID)
}
}
VERTICAL -> {
constraints.createVerticalChain(ConstraintSet.PARENT_ID, ConstraintSet.TOP, ConstraintSet.PARENT_ID,
ConstraintSet.BOTTOM, CHAIN_IDS, null, ConstraintSet.CHAIN_SPREAD)
for (id in CHAIN_IDS) {
constraints.centerHorizontallyRtl(id, ConstraintSet.PARENT_ID)
}
}
else -> error("Invalid orientation")
}
constraints.applyTo(this)
}
init {
View.inflate(context, R.layout.custom_view, this)
orientation = HORIZONTAL
}
companion object {
const val HORIZONTAL = 0
const val VERTICAL = 1
val CHAIN_IDS = intArrayOf(R.id.btn1, R.id.btn2, R.id.btn3)
}
}
R.layout.custom_view
文件:
<merge xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent">
<Button android:id="@+id/btn1" android:layout_width="48dp" android:layout_height="48dp"/>
<Button android:id="@+id/btn2" android:layout_width="48dp" android:layout_height="48dp"/>
<Button android:id="@+id/btn3" android:layout_width="48dp" android:layout_height="48dp"/>
</merge>
这会使用 ConstraintSet
创建一个带有 3 个按钮的水平或垂直展开链。也就是说,如果您只需要三个按钮,则只需更改 LinearLayout
的方向即可获得相同的结果。
我想用 ConstraintLayout 编写一个可重用的自定义视图,并且只有 1 个布局文件(如果可能)。我想要一个 "simple" 基于自定义视图上的方法的 3 个按钮的垂直或水平排列,例如 "setVertical()" 默认为水平等
我显然可以使用不同的布局文件来执行此操作,但我更喜欢更简洁的单文件解决方案。
这可能吗?如果可能,怎么做?
这会通过 AttributeSet 完成吗?
正如有人在评论中所说,你不能直接这样做。您必须手动更改 ConstraintLayout 上的约束才能更改方向。这是我设法做到的:
自定义视图class:
class CustomView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0)
: ConstraintLayout(context, attrs, defStyleAttr) {
var orientation = -1
set(value) {
if (field == value) return
field = value
val constraints = ConstraintSet()
constraints.clone(this)
when (orientation) {
HORIZONTAL -> {
constraints.createHorizontalChainRtl(ConstraintSet.PARENT_ID, ConstraintSet.START, ConstraintSet.PARENT_ID,
ConstraintSet.END, CHAIN_IDS, null, ConstraintSet.CHAIN_SPREAD)
for (id in CHAIN_IDS) {
constraints.centerVertically(id, ConstraintSet.PARENT_ID)
}
}
VERTICAL -> {
constraints.createVerticalChain(ConstraintSet.PARENT_ID, ConstraintSet.TOP, ConstraintSet.PARENT_ID,
ConstraintSet.BOTTOM, CHAIN_IDS, null, ConstraintSet.CHAIN_SPREAD)
for (id in CHAIN_IDS) {
constraints.centerHorizontallyRtl(id, ConstraintSet.PARENT_ID)
}
}
else -> error("Invalid orientation")
}
constraints.applyTo(this)
}
init {
View.inflate(context, R.layout.custom_view, this)
orientation = HORIZONTAL
}
companion object {
const val HORIZONTAL = 0
const val VERTICAL = 1
val CHAIN_IDS = intArrayOf(R.id.btn1, R.id.btn2, R.id.btn3)
}
}
R.layout.custom_view
文件:
<merge xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent">
<Button android:id="@+id/btn1" android:layout_width="48dp" android:layout_height="48dp"/>
<Button android:id="@+id/btn2" android:layout_width="48dp" android:layout_height="48dp"/>
<Button android:id="@+id/btn3" android:layout_width="48dp" android:layout_height="48dp"/>
</merge>
这会使用 ConstraintSet
创建一个带有 3 个按钮的水平或垂直展开链。也就是说,如果您只需要三个按钮,则只需更改 LinearLayout
的方向即可获得相同的结果。