Bird
Raised Fist0
Android Kotlinmobile~5 mins

Custom layouts in Android Kotlin

Choose your learning style10 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.

Practice

(1/5)
1. What is the main purpose of creating a custom layout in Android using Kotlin?
easy
A. To control exactly how child views are measured and placed
B. To automatically generate UI from XML without coding
C. To replace the Android system UI completely
D. To create animations without using XML

Solution

  1. Step 1: Understand the role of custom layouts

    Custom layouts allow developers to define how child views are measured and positioned beyond standard layouts.
  2. Step 2: Compare with other options

    Options A, B, and C describe unrelated features like animations, automatic UI generation, or system UI replacement.
  3. Final Answer:

    To control exactly how child views are measured and placed -> Option A
  4. Quick Check:

    Custom layouts = precise child view control [OK]
Hint: Custom layouts control child view size and position [OK]
Common Mistakes:
  • Thinking custom layouts generate UI automatically
  • Confusing custom layouts with animations
  • Believing custom layouts replace system UI
2. Which method must you override to specify the size requirements of a custom layout in Android Kotlin?
easy
A. onDraw
B. onMeasure
C. onCreate
D. onLayout

Solution

  1. Step 1: Identify the method for measuring size

    The onMeasure method is used to determine the size requirements of the layout and its children.
  2. Step 2: Differentiate from other methods

    onLayout positions children, onDraw handles drawing, and onCreate is unrelated to layout measurement.
  3. Final Answer:

    onMeasure -> Option B
  4. Quick Check:

    Measure size = onMeasure [OK]
Hint: Measure size with onMeasure method override [OK]
Common Mistakes:
  • Confusing onLayout with onMeasure
  • Using onDraw for size calculation
  • Thinking onCreate handles layout measurement
3. Given this simplified custom layout code snippet, what will be the width of the first child view after layout?
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
  val child = getChildAt(0)
  child.measure(MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(50, MeasureSpec.EXACTLY))
  setMeasuredDimension(200, 100)
}

override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
  val child = getChildAt(0)
  child.layout(0, 0, child.measuredWidth, child.measuredHeight)
}
medium
A. 50 pixels
B. 200 pixels
C. 150 pixels
D. 100 pixels

Solution

  1. Step 1: Analyze onMeasure child measurement

    The child is measured with width 100 pixels exactly and height 50 pixels exactly.
  2. Step 2: Analyze onLayout child placement

    The child is laid out from (0,0) to (child.measuredWidth, child.measuredHeight), so width is 100 pixels.
  3. Final Answer:

    100 pixels -> Option D
  4. Quick Check:

    Child width = measured width = 100 [OK]
Hint: Child size = measured size in onMeasure [OK]
Common Mistakes:
  • Using parent width instead of child's measured width
  • Confusing layout size with measure specs
  • Assuming child's width equals parent's width
4. What is the main error in this custom layout code that causes child views not to appear?
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
  for (i in 0 until childCount) {
    val child = getChildAt(i)
    child.layout(0, 0, 0, 0)
  }
}
medium
A. Child views are laid out with zero width and height
B. The loop does not iterate over all children
C. onLayout should not be overridden
D. Missing call to super.onLayout

Solution

  1. Step 1: Examine child.layout parameters

    Each child is positioned with left=0, top=0, right=0, bottom=0, which means zero width and height.
  2. Step 2: Understand effect on visibility

    Zero size means children are not visible on screen.
  3. Final Answer:

    Child views are laid out with zero width and height -> Option A
  4. Quick Check:

    Zero size layout hides children [OK]
Hint: Check layout right and bottom > left and top [OK]
Common Mistakes:
  • Assuming loop skips children
  • Thinking super.onLayout is mandatory
  • Ignoring layout size parameters
5. You want to create a custom layout that arranges exactly two child views side by side, each taking half the parent's width and full height. Which approach correctly implements onLayout for this?
hard
A. Layout both children at (0,0) to (width, height) overlapping
B. Layout first child at (0,0) to (width, height), second child outside visible area
C. Layout first child from (0,0) to (width/2, height), second from (width/2,0) to (width, height)
D. Layout children vertically stacked with full width

Solution

  1. Step 1: Understand layout requirements

    Two children side by side means splitting parent's width equally, full height each.
  2. Step 2: Apply correct coordinates in onLayout

    First child from left=0 to right=width/2, second from left=width/2 to right=width, both top=0 bottom=height.
  3. Final Answer:

    Layout first child from (0,0) to (width/2, height), second from (width/2,0) to (width, height) -> Option C
  4. Quick Check:

    Side by side = split width in onLayout [OK]
Hint: Divide width, assign halves to children in onLayout [OK]
Common Mistakes:
  • Overlapping children by using full width for both
  • Placing second child outside visible bounds
  • Stacking children vertically instead of horizontally
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard