Skip to content

chethann/span-layout

Repository files navigation

A Compose multiplatform Layout that supports that provides a "Span Layout" where the available space is divided into N columns. Each child can provide how many columns it needs to span in Compact, Medium and expanded screen widths.

This is inspired by CSS Bootstrap library's grid system and CSS media query.

Sample usage:

@Composable
fun ResponsiveSpanLayout(windowWidthSizeClass: WindowWidthSizeClass) {
    Column(modifier = Modifier.verticalScroll(rememberScrollState())) {
        SpanLayout(
            windowWidthSizeClass = windowWidthSizeClass,
            modifier = Modifier.padding(horizontal = 4.dp),
            interRowSpacing = 16.dp
        ) {
            Box(
                modifier = Modifier.background(Color.Blue).height(100.dp)
                    .span(compactSpan = 12, mediumSpan = 6, expandedSpan = 4)
            )
            Box(
                modifier = Modifier.background(Color.Red).height(100.dp)
                    .span(compactSpan = 12, mediumSpan = 12, expandedSpan = 8)
            )

            Box(
                modifier = Modifier.background(Color.Red).height(100.dp)
                    .span(compactSpan = 12, mediumSpan = 12, expandedSpan = 8)
            )
            Box(
                modifier = Modifier.background(Color.Blue).height(100.dp)
                    .span(compactSpan = 12, mediumSpan = 6, expandedSpan = 4)
            )

            repeat(12) { index ->
                Box(
                    modifier = Modifier
                        .padding(horizontal = 4.dp)
                        .height(100.dp)
                        .background(Color.Red)
                        .span(
                            compactSpan = 6,
                            mediumSpan = 2,
                            expandedSpan = 1
                        ),
                    contentAlignment = Alignment.Center
                ) {
                    Text("Item $index", color = Color.White)
                }
            }
        }
    }
}

The above code will render differently on different window sizes based on

Compact

Compact

Medium

Medium

Expanded

Expanded

More real life example (A calendar view) with nested SpanLayouts

Compact

Compact

Medium

Medium

Expanded

Expanded

Code for the same. You can see that even for the Month view, SpanLayout with 7 spans is used

@Composable
fun Calender(windowWidthSizeClass: WindowWidthSizeClass) {
    val daysInMonth = remember { listOf(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) }
    val monthNames = remember { listOf("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December") }
    val dayOfTheWeekInitial = remember { listOf("S", "M", "T", "W", "T", "F", "S") }
    val daysAndMonthNames = daysInMonth.zip(monthNames)
    var skips = 0

    Column(modifier = Modifier.verticalScroll(rememberScrollState())) {
        SpanLayout(
            windowWidthSizeClass = windowWidthSizeClass,
            interRowSpacing = 8.dp,
            gutterSpace = 8.dp,
            stretchToFillRow = true
        ) {
            daysAndMonthNames.forEachIndexed { index, daysAndMonthName ->
                Column(modifier = Modifier
                    .background(Color.Gray)
                    .span(
                        compactSpan = 12,
                        mediumSpan = 6,
                        expandedSpan = 4
                    )
                ) {

                    Text(daysAndMonthName.second, fontWeight = FontWeight.Bold)

                    Spacer(modifier = Modifier.height(8.dp))

                    SpanLayout(
                        windowWidthSizeClass = windowWidthSizeClass,
                        interRowSpacing = 4.dp,
                        gutterSpace = 4.dp,
                        totalSpans = 7
                    ) {

                        dayOfTheWeekInitial.forEach {
                            Text(
                                it,
                                fontWeight = FontWeight.Bold,
                                modifier = Modifier
                                    .span(
                                        compactSpan = 1,
                                        mediumSpan = 1,
                                        expandedSpan = 1
                                    )
                            )
                        }

                        repeat(skips) {
                            Box(modifier = Modifier
                                .span(
                                    compactSpan = 1,
                                    mediumSpan = 1,
                                    expandedSpan = 1
                                ))
                        }

                        skips = (skips + daysAndMonthName.first) % 7

                        repeat(daysAndMonthName.first) { index ->
                            Text(
                                (index + 1).toString(),
                                modifier = Modifier
                                    .span(
                                    compactSpan = 1,
                                    mediumSpan = 1,
                                    expandedSpan = 1
                                )
                            )
                        }
                    }
                }
            }
        }
    }
}

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published