Layout

All standard Compose layout composables work in PDF rendering. Design your pages with Column, Row, Box, and the full set of layout modifiers.


Layout example Layout example — download PDF


Column

Stack content vertically:

Column(
    Modifier.fillMaxSize().padding(24.dp),
    verticalArrangement = Arrangement.spacedBy(8.dp),
) {
    Text("First item")
    Text("Second item")
    Text("Third item")
}

Row

Arrange content horizontally:

Row(
    Modifier.fillMaxWidth(),
    horizontalArrangement = Arrangement.SpaceBetween,
    verticalAlignment = Alignment.CenterVertically,
) {
    Text("Left")
    Text("Right")
}

Weights

Distribute space proportionally:

Row(Modifier.fillMaxWidth()) {
    Box(Modifier.weight(1f).background(Color.Blue).height(40.dp))
    Box(Modifier.weight(2f).background(Color.Green).height(40.dp))
    Box(Modifier.weight(1f).background(Color.Red).height(40.dp))
}
// Results in 25% / 50% / 25% width distribution

Box

Overlay content with alignment:

Box(
    Modifier.size(200.dp).background(Color.LightGray),
    contentAlignment = Alignment.Center,
) {
    Text("Centered in box")
}

Sizing modifiers

Modifier.fillMaxSize()              // Fill entire content area
Modifier.fillMaxWidth()             // Fill width, wrap height
Modifier.fillMaxHeight()            // Fill height, wrap width
Modifier.size(100.dp)               // Fixed 100x100
Modifier.size(200.dp, 100.dp)       // Fixed 200 wide x 100 tall
Modifier.width(150.dp)              // Fixed width, wrap height
Modifier.height(80.dp)              // Fixed height, wrap width

Padding and spacing

// Uniform padding
Modifier.padding(24.dp)

// Asymmetric padding
Modifier.padding(horizontal = 16.dp, vertical = 8.dp)

// Individual sides
Modifier.padding(start = 12.dp, top = 8.dp, end = 12.dp, bottom = 16.dp)

Use Spacer for explicit gaps:

Column {
    Text("Title")
    Spacer(Modifier.height(16.dp))
    Text("Body")
    Spacer(Modifier.weight(1f))  // Fills remaining space
    Text("Footer")               // Pushed to bottom
}

Dividers

Divider()                                    // Default thin gray line
Divider(color = Color.Black, thickness = 2.dp)  // Custom

Table pattern

Compose doesn’t have a built-in table, but you can build one with Row and Column:

Column(Modifier.fillMaxWidth()) {
    // Header row
    Row(
        Modifier
            .fillMaxWidth()
            .background(Color(0xFFE3F2FD))
            .padding(horizontal = 12.dp, vertical = 8.dp),
    ) {
        Text("Name", Modifier.weight(2f), fontWeight = FontWeight.Bold)
        Text("Qty", Modifier.weight(1f), fontWeight = FontWeight.Bold, textAlign = TextAlign.End)
        Text("Price", Modifier.weight(1f), fontWeight = FontWeight.Bold, textAlign = TextAlign.End)
    }

    // Data rows
    val items = listOf("Widget" to "$12.00", "Gadget" to "$24.50")
    for ((index, item) in items.withIndex()) {
        val bg = if (index % 2 == 0) Color.White else Color(0xFFFAFAFA)
        Row(
            Modifier
                .fillMaxWidth()
                .background(bg)
                .padding(horizontal = 12.dp, vertical = 6.dp),
        ) {
            Text(item.first, Modifier.weight(2f))
            Text("1", Modifier.weight(1f), textAlign = TextAlign.End)
            Text(item.second, Modifier.weight(1f), textAlign = TextAlign.End)
        }
    }
}

Use Modifier.weight() on column cells to create consistent column widths across rows. Alternating row backgrounds (Color.White / Color(0xFFFAFAFA)) improve readability.


See also