CPS251 Android Development by Scott Shaper

Combining LazyColumn and LazyRow

In this section we will combine LazyColumn and LazyRow to create a more complex layout. We will use a LazyColumn to display a list of categories and a LazyRow to display a list of items for each category.

Note: In order for the images to work you will need to add the following dependencies and permissions.

This will go in your libs.versions.toml file

[versions]
... 
coil = "2.4.0" // Add this line for Coil version

[libraries]
...
coil-compose = { module = "io.coil-kt:coil-compose", version.ref = "coil" } // Add this line for Coil Compose make sure it is in the libraries section.

This will go in your build.gradle file

dependencies {
    ...
    implementation(libs.coil.compose) // Add this line for Coil Compose
}

You will need to add this code to your manifest file to allow internet access. It is found in apps→manifests→AndroidManifest.xml.

<uses-permission android:name="android.permission.INTERNET" />
@Composable
    fun CategoryList() {
        // Create sample data
        val categories = List(7) { categoryIndex ->
            Category(
                id = categoryIndex,
                name = "Category ${categoryIndex + 1}",
                items = List(10) { itemIndex ->
                    CategoryItem(
                        id = itemIndex,
                        title = "Title ${itemIndex + 1}",
                        // Using placeholder images from picsum.photos
                        imageUrl = "https://picsum.photos/200/300?random=${categoryIndex * 10 + itemIndex}"
                    )
                }
            )
        }
    
        LazyColumn(
            modifier = Modifier
                .fillMaxSize()
                .padding(top=50.dp),
            verticalArrangement = Arrangement.spacedBy(16.dp),
            contentPadding = PaddingValues(16.dp)
        ) {
            items(categories) { category ->
                // Within the LazyColumn we have a CategorySection composable which contains a LazyRow
                CategorySection(category)
            }
        }
    }
    
    @Composable
    fun CategorySection(category: Category) {
        Column {
            // Category title
            Text(
                text = category.name,
                style = MaterialTheme.typography.titleLarge,
                modifier = Modifier.padding(bottom = 8.dp)
            )
    
            // Horizontal scrolling list of items
            LazyRow(
                horizontalArrangement = Arrangement.spacedBy(8.dp)
            ) {
                items(category.items) { item ->
                    CategoryItemCard(item)
                }
            }
        }
    }

    @Composable
fun CategoryItemCard(item: CategoryItem) {
    Card(
        modifier = Modifier
            .width(160.dp)    // Fixed width for consistent card size
            .height(200.dp),  // Fixed height for consistent card size
        elevation = CardDefaults.cardElevation(defaultElevation = 4.dp)  // Card shadow
    ) {
        Column {
            
            AsyncImage(
                model = item.imageUrl,
                contentDescription = item.title,
                modifier = Modifier
                    .fillMaxWidth()
                    .height(120.dp),
                contentScale = ContentScale.Crop  // Crop image to fill the space
            )

            
            Text(
                text = item.title,
                style = MaterialTheme.typography.titleMedium,
                maxLines = 2,  // Limit to 2 lines
                overflow = TextOverflow.Ellipsis,  // Show ellipsis for overflow
                modifier = Modifier.padding(8.dp)
            )
        }
    }
}

   

What This Example Is Doing

CategoryList builds sample data: seven categories, each with ten items that have titles and image URLs (from picsum.photos). A LazyColumn scrolls vertically through categories; for each category, CategorySection shows the category name and a LazyRow of item cards. So you get a vertical list of sections, and each section has a horizontal row of cards. CategoryItemCard displays each item in a fixed-size card: AsyncImage loads the image from the URL (Coil + INTERNET permission required), and the title appears below. The dependency snippets above add the Coil library and INTERNET permission so images can load from the web.

Above Code Explained

The CategoryList composable creates a vertically scrolling list of categories using LazyColumn. Each category contains:

The CategorySection composable handles the display of each category by:

The CategoryItemCard composable displays individual items as cards, each containing:

How this example renders

The screenshot shows the combined layout on screen: a vertically scrolling list of category sections (e.g., “Category 1”, “Category 2”). Each section has a title at the top and a horizontally scrolling row of cards below it. Each card shows an image and a title. You scroll down to see more categories and scroll left/right within a section to see more items. The full project is on my GitHub page—open the chapter8 combined.kt file to run it.

Combined LazyColumn and LazyRow: vertical list of categories, each with a horizontal row of image cards