HorizontalCenteredHeroCarousel

Common

Component in Material 3 Compose

Material Design Carousel

A horizontal carousel that centers one large item between two small items.

Last updated:

Installation

dependencies {
   implementation("androidx.compose.material3:material3:1.4.0-alpha17")
}

Overloads

@ExperimentalMaterial3Api
@Composable
fun HorizontalCenteredHeroCarousel(
    state: CarouselState,
    modifier: Modifier = Modifier,
    maxItemWidth: Dp = Dp.Unspecified,
    itemSpacing: Dp = 0.dp,
    flingBehavior: TargetedFlingBehavior =
        CarouselDefaults.singleAdvanceFlingBehavior(state = state),
    userScrollEnabled: Boolean = true,
    minSmallItemWidth: Dp = CarouselDefaults.MinSmallItemSize,
    maxSmallItemWidth: Dp = CarouselDefaults.MaxSmallItemSize,
    contentPadding: PaddingValues = PaddingValues(0.dp),
    content: @Composable CarouselItemScope.(itemIndex: Int) -> Unit,
)

Parameters

namedescription
stateThe state object to be used to control the carousel's state
modifierA modifier instance to be applied to this carousel container
maxItemWidthThe max width a large item is allowed to be in dp. The default value of [Dp.Unspecified] allows one large item to grow to fill the entire viewport minus space for two surrounding small items. Values other than unspecified will add additional large items as space allows.
itemSpacingThe amount of space used to separate items in the carousel
flingBehaviorThe [TargetedFlingBehavior] to be used for post scroll gestures
userScrollEnabledwhether the scrolling via the user gestures or accessibility actions is allowed.
minSmallItemWidthThe minimum allowable width of small items in dp
maxSmallItemWidthThe maximum allowable width of small items in dp
contentPaddinga padding around the whole content. This will add padding for the content after it has been clipped. You can use it to add a padding before the first item or after the last one. Use [itemSpacing] to add spacing between the items.
contentThe carousel's content Composable

Code Example

HorizontalCenteredHeroCarouselSample

@OptIn(ExperimentalMaterial3Api::class)
@Preview
@Composable
fun HorizontalCenteredHeroCarouselSample() {

    data class CarouselItem(
        val id: Int,
        @DrawableRes val imageResId: Int,
        @StringRes val contentDescriptionResId: Int,
    )

    val items =
        listOf(
            CarouselItem(0, R.drawable.carousel_image_1, R.string.carousel_image_1_description),
            CarouselItem(1, R.drawable.carousel_image_2, R.string.carousel_image_2_description),
            CarouselItem(2, R.drawable.carousel_image_3, R.string.carousel_image_3_description),
            CarouselItem(3, R.drawable.carousel_image_4, R.string.carousel_image_4_description),
            CarouselItem(4, R.drawable.carousel_image_5, R.string.carousel_image_5_description),
        )
    val state = rememberCarouselState { items.count() }
    val animationScope = rememberCoroutineScope()
    HorizontalCenteredHeroCarousel(
        state = state,
        modifier = Modifier.fillMaxWidth().height(221.dp).padding(horizontal = 24.dp),
        itemSpacing = 8.dp,
        contentPadding = PaddingValues(horizontal = 16.dp),
    ) { i ->
        val item = items[i]
        Image(
            modifier =
                Modifier.fillMaxWidth()
                    .height(205.dp)
                    .maskClip(MaterialTheme.shapes.extraLarge)
                    .clickable(true, "Tap to focus", Role.Image) {
                        animationScope.launch { state.animateScrollToItem(i) }
                    },
            painter = painterResource(id = item.imageResId),
            contentDescription = stringResource(item.contentDescriptionResId),
            contentScale = ContentScale.Crop,
        )
    }
}