Search code examples
androidkotlinandroid-relativelayout

How set all attributes of RelativeLayout Programmatically in Kotlin?


I've created a basic layout in Android in my activity_main.xml for what will eventually be a custom view for a button. It is a relative view with three circles stacked on top of eachother inside it aligned in the centre. The circles change size when the user interacts with them.

I now want to replicate the whole thing purely in Kotlin code, as it will be loaded using data in a database.

I can't figure it out. Heres the manifest...

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <RelativeLayout
        android:id="@+id/myContainer"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <ImageView
            android:id="@+id/button3"
            android:layout_width="400dp"
            android:layout_height="400dp"
            android:layout_centerInParent="true"
            app:srcCompat="@drawable/circle"
            app:tint="#E60505" />

        <ImageView
            android:id="@+id/button2"
            android:layout_width="400dp"
            android:layout_height="400dp"
            android:layout_centerInParent="true"
            app:srcCompat="@drawable/circle"
            app:tint="#FFB700" />

        <ImageView
            android:id="@+id/button1"
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:layout_alignParentRight="false"
            android:layout_centerInParent="true"
            app:srcCompat="@drawable/circle" />
    </RelativeLayout>


</androidx.constraintlayout.widget.ConstraintLayout>

Then in Kotlin, all I can find about is LayoutParams for width and height, but where do I set all this stuff for the Relative Layout?

        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"

which I presume I want to do something like:

class MyContainer : RelativeLayout () {

var button1 = MyButtonClass(someArgs)
var button2 = MyButtonClass(someArgs)
var button3 = MyButtonClass(someArgs)

init {
/// can't find out how to do this bit in Kotlin... 
///something like....
this.layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT
this.layoutConstraintBottomToBottomOf = PARENT
this.layoutConstraintHorizontalBias = 0.5
///etc...

//then add the circle buttons 
this.addView(button3)
this.addView(button2)
this.addView(button1)
}

}

Am I even vagueley on the right track? Any pointers would be really appreciated.

EDIT: Following first answer, I can set layout attributes, but my app is just blank when i try to reproduce my original manifest tree in code. Have I applied this correctly?

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val appContainer = findViewById<ConstraintLayout>(R.id.appContainer)

        var buttonContainer = ButtonContainer(this.applicationContext)
        appContainer.addView(buttonContainer)
    }
}


class ButtonContainer (context: Context) : RelativeLayout(context) {

var button1 = CustomButton(context)

val buttonLayoutParams by lazy { ConstraintLayout.LayoutParams(ConstraintLayout.LayoutParams.WRAP_CONTENT, ConstraintLayout.LayoutParams.WRAP_CONTENT).apply {
    bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID
    startToStart = ConstraintLayout.LayoutParams.PARENT_ID
    topToTop = ConstraintLayout.LayoutParams.PARENT_ID
    endToEnd = ConstraintLayout.LayoutParams.PARENT_ID
    horizontalBias = 0.5F
}
}

override fun onFinishInflate() {
    super.onFinishInflate()
    this.layoutParams = buttonLayoutParams
    this.addView(button1)
}

}


class CustomButton(context: Context) : ImageView(context) {

val layoutParams by lazy { RelativeLayout.LayoutParams(60, 60).apply {
    addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE)
}
}


override fun onFinishInflate() {
    super.onFinishInflate()
    setLayoutParams(layoutParams)
    setBackgroundResource(squibcircle)
}

}


Solution

  • You need to cast LayoutParams as ConstraintLayout.LayoutParams to set those properties like below

    class ButtonContainer(context: Context) : RelativeLayout(context) {
    
        var button1 = CustomButton(context)
    
        val buttonLayoutParams by lazy { ConstraintLayout.LayoutParams(ConstraintLayout.LayoutParams.WRAP_CONTENT, ConstraintLayout.LayoutParams.WRAP_CONTENT).apply {
               bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID
               startToStart = ConstraintLayout.LayoutParams.PARENT_ID
               topToTop = ConstraintLayout.LayoutParams.PARENT_ID
               endToEnd = ConstraintLayout.LayoutParams.PARENT_ID
               horizontalBias = 0.5F
            }
        }
    
        override fun onFinishInflate() {
            this.layoutParams = buttonLayoutParams
            this.addView(button1)
        }
    }