MATCH_CONSTRAINTS не работает в динамически генерируемой взвешенной цепочке

#android-constraintlayout

#android-constraintlayout

Вопрос:

Я написал следующий метод. Он динамически создает 16 красных полей просмотра, а затем добавляет их в цепочку компоновки ограничений, чтобы распределить их по горизонтали по родительскому макету. Это работает, но только если я задаю представлениям определенное значение ширины и хочу, чтобы они заполняли доступное пространство. Если я установлю ширину каждого представления ConstraintSet.MATCH_CONSTRAINT , ни один из них не появится вообще.

Что я делаю не так? Я думал, что если бы была установлена ширина MATCH_CONSTRAINT , каждое представление заполняло бы отведенное ему пространство по его значению веса. Вместо этого они вообще не отображаются, и они отображаются только в том случае, если я задаю им определенную ширину, но тогда они не будут увеличиваться или уменьшаться, чтобы соответствовать представлению. Это как если бы их установка MATCH_CONSTRAINT была такой же, как установка ширины буквально равной нулю.

 private fun createDropTargets(parentView: ConstraintLayout) {
        parentView.setOnDragListener(StaffDragListener())
        val set = ConstraintSet()

        val ids = arrayListOf<Int>()
        val weights = arrayListOf<Float>()
        for (i in 0..15) {
            val drop = View(activity)
            drop.setBackgroundColor(Color.RED)

            // THE NEXT LINE IS WHERE I SET THE WIDTH VALUE. IF I SET TO A NUMBER > 0 THE VIEWS SHOW UP, BUT DO NOT DYNAMICALLY FILL THE SPACE
            
            val params = ConstraintLayout.LayoutParams(ConstraintSet.MATCH_CONSTRAINT, 0)
            params.setMargins(5, 0, 5, 0)
            drop.layoutParams = params
            drop.id = View.generateViewId()
            parentView.addView(drop)
            ids.add(drop.id)
            weights.add(1f)
        }
        set.clone(parentView)
        var previousId: Int? = null
        for ((index, id) in ids.withIndex()) {
            if (previousId == null) {
                set.connect(id, ConstraintSet.LEFT, ConstraintSet.PARENT_ID, ConstraintSet.LEFT)
            } else {
                set.connect(id, ConstraintSet.LEFT, previousId, ConstraintSet.RIGHT)
                if (index == ids.size - 1) {
                    set.connect(id, ConstraintSet.RIGHT, ConstraintSet.PARENT_ID, ConstraintSet.RIGHT)
                }
            }
            previousId = id
        }
        set.createHorizontalChain(ConstraintSet.PARENT_ID, ConstraintSet.LEFT, ConstraintSet.PARENT_ID, ConstraintSet.RIGHT, ids.toIntArray(), weights.toFloatArray(), ConstraintSet.CHAIN_SPREAD_INSIDE)
        set.applyTo(parentView)
    }
 

Ответ №1:

MATCH_CONSTRAINT устанавливает ширину / высоту равными нулю, поскольку она определена следующим образом в ConstraintSet:

 public static final int MATCH_CONSTRAINT = 0;
 

Это говорит о том, что ограничения будут определять размер. Отсутствие ограничений или неправильных ограничений просто приведет к нулевой ширине / высоте.

Ваш код правильный, за исключением того, что для высоты установлено значение MATCH_CONSTRAINT (помните 0 == MATCH_CONSTRAINT ), но вы не применяете ограничения к высоте, поэтому представления просто исчезают (ширина, но нет высоты.) Если вы зададите заданную высоту для представлений, они появятся. Следующий код покажет представления высотой 100 пикселей:

 private fun createDropTargets(parentView: ConstraintLayout) {
    parentView.setOnDragListener(StaffDragListener())
    val set = ConstraintSet()

    val ids = arrayListOf<Int>()
    val weights = arrayListOf<Float>()
    for (i in 0..15) {
        val drop = View(activity)
        drop.setBackgroundColor(Color.RED)
        val params = ConstraintLayout.LayoutParams(ConstraintSet.MATCH_CONSTRAINT, 100)
        params.setMargins(5, 0, 5, 0)
        drop.layoutParams = params
        drop.id = View.generateViewId()
        parentView.addView(drop)
        ids.add(drop.id)
        weights.add(1f)
    }
    set.clone(parentView)
    set.createHorizontalChain(ConstraintSet.PARENT_ID, ConstraintSet.LEFT, ConstraintSet.PARENT_ID, ConstraintSet.RIGHT, ids.toIntArray(), weights.toFloatArray(), ConstraintSet.CHAIN_SPREAD_INSIDE)
    set.applyTo(parentView)
}
 

Кстати, второй цикл является избыточным. Вся эта работа выполняется с созданием цепочки.

Вам нужно будет решить, хотите ли вы определенную высоту или позволите установить высоту с помощью соответствующих ограничений, применяемых в вертикальном направлении.