Search code examples
androidkotlinandroid-viewandroid-constraintlayout

Create ConstraintLayout with 2 buttons and EditText fails programatically


I am trying to re-create a screen from XML to code for some reason. This is what I want my screen to look like:

enter image description here

So pretty simple:

  • Two buttons on each side (should actually be images but it's fine for now)
  • EditText in the middle
  • When the EditText grows to multiple lines, the buttons should 'stick' to the top of the EditText

With my code, my screen looks like this:

enter image description here

And I have no idea what that is the case. This is my code:

@Composable
fun ShowWrapped() {
    AndroidView(factory = { context ->
        createChat(context)
    })
}

fun createChat(context: Context): ConstraintLayout {
    val constraintLayout = ConstraintLayout(context).apply {
        id = View.generateViewId()
        layoutParams = ViewGroup.LayoutParams(
            MATCH_PARENT,
            MATCH_PARENT,
        )
    }
    val buttonA = ImageButton(context).apply {
        id = View.generateViewId()
        layoutParams = ViewGroup.LayoutParams(
            WRAP_CONTENT,
            WRAP_CONTENT,
        )
    }
    val buttonB = ImageButton(context).apply {
        id = View.generateViewId()
        layoutParams = ViewGroup.LayoutParams(
            WRAP_CONTENT,
            WRAP_CONTENT,
        )
    }
    val editText = EditText(context).apply {
        id = View.generateViewId()
        layoutParams = ViewGroup.LayoutParams(
            WRAP_CONTENT,
            WRAP_CONTENT,
        )
    }

    constraintLayout.addView(buttonA)
    constraintLayout.addView(buttonB)
    constraintLayout.addView(editText)

    buttonA.setImageResource(R.drawable.ic_launcher_foreground)
    buttonB.setImageResource(R.drawable.ic_launcher_foreground)

    val set = ConstraintSet()

    set.clone(constraintLayout)

    set.connect(buttonA.id, ConstraintSet.START, constraintLayout.id, ConstraintSet.START)
    set.connect(buttonB.id, ConstraintSet.END, constraintLayout.id, ConstraintSet.END)
    set.connect(editText.id, ConstraintSet.BOTTOM, constraintLayout.id, ConstraintSet.BOTTOM)
    set.connect(buttonA.id, ConstraintSet.TOP, editText.id, ConstraintSet.TOP)
    set.connect(buttonB.id, ConstraintSet.TOP, editText.id, ConstraintSet.TOP)
    set.connect(buttonA.id, ConstraintSet.END, editText.id, ConstraintSet.START)
    set.connect(buttonB.id, ConstraintSet.START, editText.id, ConstraintSet.END)

    set.applyTo(constraintLayout)

    return constraintLayout
}

Solution

  • The EditText is not constrained properly. You will need to add start and end constraints to center it in the layout. (This is the gist of Remc4's answer and the core of your issue.)

    set.connect(editText.id, ConstraintSet.BOTTOM,ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM)
    set.connect(editText.id, ConstraintSet.START,ConstraintSet.PARENT_ID, ConstraintSet.START)
    set.connect(editText.id, ConstraintSet.END,ConstraintSet.PARENT_ID, ConstraintSet.END)
    

    This will position your views in the right positions. You may have additional work such as introducing a horizontal chain to make sure everything stays aligned if the EditText grows enough to push the buttons off the screen.

    You did not post your working XML, so I can't comment on any differences between the XML and your code.