Search code examples
androidandroid-layoutviewandroid-jetpack-composecomposable

Card carousel in Android with Jetpack Compose


I want to create composable function which can show elements(cards) like in the picture below. Is there any way to do it with LazyList or LazyColumn

I’ve tried VerticalPager from Google accompanist but I don’t know how to set them like on the pictureenter image description here


Solution

  • I was also looking to make a carousel in Compose but I couldn't find, so I did it. The result is not perfect (height problem if too tall), but it can give an example.

    I made an infinite LazyColumn and I change scale and zIndex for the content to make the carousel effect.

    Here my function :

    @Composable
    fun Carousel(
      count: Int,
      parentModifier: Modifier = Modifier.fillMaxWidth().height(540.dp),
      contentWidth: Dp,
      contentHeight: Dp,
      content: @Composable (modifier: Modifier, index: Int) -> Unit
    ) {
    val listState = rememberLazyListState(Int.MAX_VALUE / 2)
    
    BoxWithConstraints(
        modifier = parentModifier
    ) {
        val halfRowWidth = constraints.maxWidth / 2
    
        LazyColumn(
            state = listState,
            modifier = Modifier.fillMaxSize(),
            contentPadding = PaddingValues(top = 10.dp),
            verticalArrangement = Arrangement.spacedBy(-contentHeight / 2),
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            items(
                count = Int.MAX_VALUE,
                itemContent = { globalIndex ->
                    val scale by remember {
                        derivedStateOf {
                            val currentItem = listState.layoutInfo.visibleItemsInfo.firstOrNull { it.index == globalIndex } ?: return@derivedStateOf 0.85f
    
                            (1f - minOf(1f, abs(currentItem.offset + (currentItem.size / 2) - halfRowWidth).toFloat() / halfRowWidth) * 0.25f)
                        }
                    }
    
                    content(
                        index = globalIndex % count,
                        modifier = Modifier
                            .width(contentWidth)
                            .height(contentHeight)
                            .scale(scale)
                            .zIndex(scale * 10)
                    )
                }
            )
        }
      }
    }
    

    And I call the function like this :

    Carousel(
       count = list.size,
       contentWidth = maxWidth,
       contentHeight = 200.dp,
       content = { modifier, index ->
            MyComposableContent(
                item = list[index],
                modifier = modifier
            )
       }
    )
    

    Carousel compose result