Можно ли иметь одну Android ConstraintLayout настраиваемую горизонтальную или вертикальную ориентацию? - PullRequest
1 голос
/ 13 апреля 2020

Я хочу написать пользовательское представление многократного использования с ConstraintLayout и иметь только 1 файл макета (если это возможно). Я хочу довольно «простое» вертикальное или горизонтальное расположение из 3 кнопок, основанное на методе в пользовательском представлении, таком как «setVertical ()» с горизонтальным значением по умолчанию, et c.

Я мог бы сделать это с разными файлами макетов, но я бы предпочел более чистое решение для одного файла.

Возможно ли это, и если да, то как?

Будет ли это сделано через AttributeSet?

1 Ответ

1 голос
/ 13 апреля 2020

Как кто-то сказал в комментарии, вы не можете сделать это напрямую. Вы должны вручную изменить ограничения на свой ConstraintLayout, чтобы изменить ориентацию. Вот что мне удалось сделать:

Класс пользовательского представления:

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>

Это создает горизонтальное или вертикальное расширение цепь с 3 кнопками, используя ConstraintSet. Тем не менее, если вам нужны только три кнопки, вы можете достичь того же результата с LinearLayout, просто изменив его ориентацию.

...