New Compose Multiplatform components arrived on Composables UICheck it out →

ContextualFlowColumn

[ContextualFlowColumn] is a specialized version of the [FlowColumn] layout. It is designed to enable users to make contextual decisions during the construction of [FlowColumn] layouts.

This component is particularly advantageous when dealing with a large collection of items, allowing for efficient management and display. Unlike traditional [FlowColumn] that composes all items regardless of their visibility, ContextualFlowColumn smartly limits composition to only those items that are visible within its constraints, such as [maxLines] or maxWidth. This approach ensures optimal performance and resource utilization by composing fewer items than the total number available, based on the current context and display parameters.

While maintaining the core functionality of the standard [FlowColumn], [ContextualFlowColumn] operates on an index-based system and composes items sequentially, one after another. This approach provides a perfect way to make contextual decisions and can be an easier way to handle problems such as dynamic see more buttons such as (N+ buttons).

Last updated:

Installation

dependencies {
   implementation("androidx.compose.foundation:foundation-layout:1.7.0-beta03")
}

Overloads

@ExperimentalLayoutApi
@Composable
fun ContextualFlowColumn(
    itemCount: Int,
    modifier: Modifier = Modifier,
    verticalArrangement: Arrangement.Vertical = Arrangement.Top,
    horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
    maxItemsInEachColumn: Int = Int.MAX_VALUE,
    maxLines: Int = Int.MAX_VALUE,
    overflow: ContextualFlowColumnOverflow = ContextualFlowColumnOverflow.Clip,
    content: @Composable ContextualFlowColumnScope.(index: Int) -> Unit,
)

Parameters

namedescription
modifierThe modifier to be applied to the Row.
horizontalArrangementThe horizontal arrangement of the layout's children.
verticalArrangementThe vertical arrangement of the layout's virtual column.
maxItemsInEachColumnThe maximum number of items per column
maxLinesThe maximum number of columns
overflowThe strategy to handle overflowing items
itemCountThe total number of item composable
contentThe indexed-based content of [ContextualFlowColumnScope]

Code Example

ContextualFlowColMaxLineDynamicSeeMore

@Composable
@Sampled
@OptIn(ExperimentalLayoutApi::class
fun ContextualFlowColMaxLineDynamicSeeMore() {
    val totalCount = 300
    var maxLines by remember {
        mutableStateOf(2)
    }

    Text(
        modifier = Modifier
            .fillMaxWidth(1f)
            .padding(20.dp),
        text = "ContextualFlowColumn (based on Subcompose)" +
            " is great for Large Items & +N dynamic labels",
        fontWeight = FontWeight.Bold
    )

    val moreOrCollapseIndicator = @Composable { scope: ContextualFlowColumnOverflowScope ->
        val remainingItems = totalCount - scope.shownItemCount
        DynamicSeeMore(
            isHorizontal = true,
            remainingItems = remainingItems
        ) {
            if (remainingItems == 0) {
                maxLines = 2
            } else {
                maxLines += 2
            }
        }
    }
    ContextualFlowColumn(
        modifier = Modifier
            .fillMaxWidth(1f)
            .horizontalScroll(rememberScrollState())
            .padding(20.dp)
            .height(200.dp)
            .wrapContentHeight(align = Alignment.Top),
        verticalArrangement = Arrangement.spacedBy(10.dp),
        horizontalArrangement = Arrangement.spacedBy(20.dp),
        maxLines = maxLines,
        overflow = ContextualFlowColumnOverflow.expandOrCollapseIndicator(
            minColumnsToShowCollapse = 4,
            expandIndicator = moreOrCollapseIndicator,
            collapseIndicator = moreOrCollapseIndicator
        ),
        itemCount = totalCount
    ) { index ->
        Box(
            modifier = Modifier
                .align(Alignment.CenterHorizontally)
                .height(50.dp)
                .width(50.dp)
                .background(Color.Green)
        ) {
            Text(text = index.toString(), fontSize = 18.sp, modifier =
            Modifier
                .padding(3.dp)
                .align(Alignment.Center))
        }
    }
}