0
0
Android Kotlinmobile~5 mins

Custom layouts in Android Kotlin

Choose your learning style9 modes available
Introduction

Custom layouts let you arrange app elements exactly how you want. They help make your app look unique and fit your design needs.

When you want to place buttons and text in a special pattern not covered by standard layouts.
When you need to create a unique screen design for your app's home page.
When default layouts like LinearLayout or RelativeLayout can't arrange views the way you want.
When you want to control exactly how child views measure and position themselves.
When building a reusable component that arranges its children in a custom way.
Syntax
Android Kotlin
class MyCustomLayout(context: Context, attrs: AttributeSet?) : ViewGroup(context, attrs) {
    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        // Measure children and set measured dimensions
        val widthSize = MeasureSpec.getSize(widthMeasureSpec)
        val heightSize = MeasureSpec.getSize(heightMeasureSpec)
        setMeasuredDimension(widthSize, heightSize)
    }

    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        // Position children inside this layout
    }
}

You must override onMeasure to tell Android how big your layout and its children should be.

You must override onLayout to place each child view inside your layout.

Examples
This custom layout stacks children vertically, one below another.
Android Kotlin
class SimpleCustomLayout(context: Context) : ViewGroup(context) {
    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        val count = childCount
        var maxWidth = 0
        var totalHeight = 0
        for (i in 0 until count) {
            val child = getChildAt(i)
            measureChild(child, widthMeasureSpec, heightMeasureSpec)
            maxWidth = maxOf(maxWidth, child.measuredWidth)
            totalHeight += child.measuredHeight
        }
        val width = resolveSize(maxWidth, widthMeasureSpec)
        val height = resolveSize(totalHeight, heightMeasureSpec)
        setMeasuredDimension(width, height)
    }

    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        var currentTop = 0
        for (i in 0 until childCount) {
            val child = getChildAt(i)
            child.layout(0, currentTop, child.measuredWidth, currentTop + child.measuredHeight)
            currentTop += child.measuredHeight
        }
    }
}
This layout centers a single child view inside itself.
Android Kotlin
class CenterCustomLayout(context: Context) : ViewGroup(context) {
    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        val child = getChildAt(0)
        measureChild(child, widthMeasureSpec, heightMeasureSpec)
        setMeasuredDimension(
            MeasureSpec.getSize(widthMeasureSpec),
            MeasureSpec.getSize(heightMeasureSpec)
        )
    }

    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        val child = getChildAt(0)
        val left = (width - child.measuredWidth) / 2
        val top = (height - child.measuredHeight) / 2
        child.layout(left, top, left + child.measuredWidth, top + child.measuredHeight)
    }
}
Sample App

This custom layout stacks buttons vertically. Each button appears below the previous one. It measures all children to find the widest width and total height, then arranges them top to bottom.

Android Kotlin
class VerticalStackLayout(context: Context) : ViewGroup(context) {
    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        var maxWidth = 0
        var totalHeight = 0
        for (i in 0 until childCount) {
            val child = getChildAt(i)
            measureChild(child, widthMeasureSpec, heightMeasureSpec)
            maxWidth = maxOf(maxWidth, child.measuredWidth)
            totalHeight += child.measuredHeight
        }
        val width = resolveSize(maxWidth, widthMeasureSpec)
        val height = resolveSize(totalHeight, heightMeasureSpec)
        setMeasuredDimension(width, height)
    }

    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        var currentTop = 0
        for (i in 0 until childCount) {
            val child = getChildAt(i)
            child.layout(0, currentTop, child.measuredWidth, currentTop + child.measuredHeight)
            currentTop += child.measuredHeight
        }
    }
}

// Usage in an Activity or Fragment:
// val layout = VerticalStackLayout(context)
// layout.addView(Button(context).apply { setText("Button 1") })
// layout.addView(Button(context).apply { setText("Button 2") })
// setContentView(layout)
OutputSuccess
Important Notes

Always call measureChild or measureChildWithMargins inside onMeasure to measure children properly.

Use setMeasuredDimension to tell Android your layout's size after measuring.

In onLayout, use child.layout(left, top, right, bottom) to position each child view.

Summary

Custom layouts let you control exactly how child views are measured and placed.

You must override onMeasure and onLayout methods.

Custom layouts help create unique and flexible UI designs beyond standard layouts.