Pantrix UI

Carousel

Yan yana duran slaytlar, biri ekranda: resimler, kartlar, bir tanıtımın adımları. Kaydırmak onları çevirir. Altındakiler carousel'in nerede olduğunu söyler ve ekrana dokunamayan okuyucu için slaytları çevirir.

import com.pantrixui.components.data.carousel.PantrixCarousel

Örnekler

Öne çıkanlar: noktalarla

En yalın hâli: dört slayt ve altında noktalar. Slaydın sırası ekranın durumudur; carousel onu currentPage ile alır ve kaydırma bittiğinde onPageChange ile geri bildirir. Altındaki satır aynı durumu okur.

Yükseklik carousel'e verildi (180dp): slaytlar, noktalardan kalan yeri doldurur. Masaüstünde ve masadaki tarayıcıda iki yanda önceki ve sonraki düğmeleri de görünür; telefonda, tarayıcısında da, kaydırmak yeter.

var slide by rememberSaveable { mutableIntStateOf(0) }
PantrixCarousel(
    pageCount = TITLES.size,
    currentPage = slide,
    onPageChange = { slide = it },
    modifier = Modifier.height(180.dp),
    contentDescription = "Öne çıkanlar",
    tagKey = "featured"
) { index ->
    CarouselSlide(index, modifier = Modifier.fillMaxSize())
}
PantrixText(text = "Ekranda: ${TITLES[slide]}", color = PantrixTheme.colors.textSecondary)

@Composable
private fun CarouselSlide(
    index: Int,
    modifier: Modifier = Modifier
) {
    val role = roles()[index % ROLES]
    PantrixSurface(modifier = modifier, color = role.container, contentColor = role.onContainer) {
        Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
            PantrixText(text = TITLES[index % TITLES.size], style = PantrixTheme.typography.title)
        }
    }
}

@Composable
private fun roles(): List<PantrixColor> {
    val colors = PantrixTheme.colors
    return listOf(colors.info, colors.success, colors.warning, colors.danger)
}

private const val ROLES = 4

private val TITLES = listOf("Yeni gelenler", "Haftanın seçimi", "İndirimdekiler", "Son fırsat")

Komşuları görünen kartlar, sayaçla ve düğmelerle

peek = 24.dp ile slaytların iki yanında komşuları görünür: bir kaydırmayla gelecek olan şimdiden bellidir. indicator = CarouselIndicator.Count noktaların yerine bir sayaç yazar; controls = CarouselControls.Always düğmeleri telefonda da gösterir.

var slide by rememberSaveable { mutableIntStateOf(1) }
PantrixCarousel(
    pageCount = TITLES.size,
    currentPage = slide,
    onPageChange = { slide = it },
    contentDescription = "Teklifler",
    style = CarouselStyle(
        peek = 24.dp,
        indicator = CarouselIndicator.Count,
        controls = CarouselControls.Always
    ),
    tagKey = "offers"
) { index ->
    CarouselSlide(index, modifier = Modifier.fillMaxWidth().height(96.dp))
}

@Composable
private fun CarouselSlide(
    index: Int,
    modifier: Modifier = Modifier
) {
    val role = roles()[index % ROLES]
    PantrixSurface(modifier = modifier, color = role.container, contentColor = role.onContainer) {
        Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
            PantrixText(text = TITLES[index % TITLES.size], style = PantrixTheme.typography.title)
        }
    }
}

private val TITLES = listOf("Yeni gelenler", "Haftanın seçimi", "İndirimdekiler", "Son fırsat")

@Composable
private fun roles(): List<PantrixColor> {
    val colors = PantrixTheme.colors
    return listOf(colors.info, colors.success, colors.warning, colors.danger)
}

private const val ROLES = 4

Kendi düğmesiyle ilerleyen tanıtım

Kaydırılmayan bir tanıtım: swipeEnabled = false, gösterge ve düğmeler de kapalı. Adımlar yalnızca "Devam" ile ilerler. Hangi adımda olunduğu ekranın kendi durumudur; düğme onu bir artırır, carousel oraya döner.

var step by rememberSaveable { mutableIntStateOf(0) }
val last = STEPS.lastIndex
PantrixCarousel(
    pageCount = STEPS.size,
    currentPage = step,
    onPageChange = { step = it },
    swipeEnabled = false,
    contentDescription = "Tanıtım",
    style = CarouselStyle(indicator = CarouselIndicator.None, controls = CarouselControls.Never),
    tagKey = "introduction"
) { index ->
    PantrixSurface(modifier = Modifier.fillMaxWidth(), border = PantrixTheme.colors.divider) {
        PantrixText(text = STEPS[index], modifier = Modifier.padding(PantrixTheme.spacing.lg))
    }
}
Row(
    horizontalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.md),
    verticalAlignment = Alignment.CenterVertically
) {
    PantrixButton(
        text = if (step == last) "Baştan" else "Devam",
        onClick = { step = if (step == last) 0 else step + 1 },
        variant = ButtonVariant.Soft,
        size = ButtonSize.Small,
        tagKey = "introduction_next"
    )
    PantrixText(text = "Adım ${step + 1} / ${STEPS.size}", color = PantrixTheme.colors.textSecondary)
}

private val STEPS = listOf(
    "Pantrix'e hoş geldin. Bu tanıtım üç adım sürer.",
    "Bileşenler her platformda aynı tasarım dilini konuşur.",
    "Hazırsın: bileşen listesine dönüp birini açabilirsin."
)

Bir dolgunun üstünde

Temanın zemini olmayan bir dolgunun üstünde carousel. Renk verilmedi: dolgu, üstüne ne renkle yazıldığını söyler. Ekrandaki slaydın noktası ve düğmeler o renkte, öteki noktalar onun bir payındadır.

var slide by rememberSaveable { mutableIntStateOf(0) }
PantrixSurface(modifier = Modifier.fillMaxWidth(), color = PantrixTheme.colors.primary.color) {
    PantrixCarousel(
        pageCount = 3,
        currentPage = slide,
        onPageChange = { slide = it },
        modifier = Modifier.padding(PantrixTheme.spacing.md),
        contentDescription = "Dolgu üstünde",
        style = CarouselStyle(controls = CarouselControls.Always),
        tagKey = "filled"
    ) { index ->
        CarouselSlide(index, modifier = Modifier.fillMaxWidth().height(72.dp))
    }
}

@Composable
private fun CarouselSlide(
    index: Int,
    modifier: Modifier = Modifier
) {
    val role = roles()[index % ROLES]
    PantrixSurface(modifier = modifier, color = role.container, contentColor = role.onContainer) {
        Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
            PantrixText(text = TITLES[index % TITLES.size], style = PantrixTheme.typography.title)
        }
    }
}

@Composable
private fun roles(): List<PantrixColor> {
    val colors = PantrixTheme.colors
    return listOf(colors.info, colors.success, colors.warning, colors.danger)
}

private const val ROLES = 4

private val TITLES = listOf("Yeni gelenler", "Haftanın seçimi", "İndirimdekiler", "Son fırsat")

Kendiliğinden dönen galeri

Resim galerisi gibi: loop ile slaytlar döner, autoAdvanceMillis ile altı saniyede bir kendiliğinden ilerler. placement = CarouselPlacement.Overlaid düğmeleri ve noktaları slaydın üstüne, carousel'in kendi dolgusuna koyar (açık temada koyu, koyu temada açık); yer kaplamazlar.

Noktaların yanındaki düğme dönmeyi durdurur ve yeniden başlatır. Bir slaydı tutarken, fare üstündeyken ve klavye odağı içindeyken carousel kendiliğinden bekler.

var slide by rememberSaveable { mutableIntStateOf(0) }
PantrixCarousel(
    pageCount = TITLES.size,
    currentPage = slide,
    onPageChange = { slide = it },
    modifier = Modifier.height(200.dp),
    contentDescription = "Galeri",
    loop = true,
    autoAdvanceMillis = GALLERY_MILLIS,
    style = CarouselStyle(controls = CarouselControls.Always, placement = CarouselPlacement.Overlaid),
    tagKey = "gallery"
) { index ->
    CarouselSlide(index, modifier = Modifier.fillMaxSize())
}

@Composable
private fun CarouselSlide(
    index: Int,
    modifier: Modifier = Modifier
) {
    val role = roles()[index % ROLES]
    PantrixSurface(modifier = modifier, color = role.container, contentColor = role.onContainer) {
        Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
            PantrixText(text = TITLES[index % TITLES.size], style = PantrixTheme.typography.title)
        }
    }
}

private val TITLES = listOf("Yeni gelenler", "Haftanın seçimi", "İndirimdekiler", "Son fırsat")

private const val GALLERY_MILLIS = 6_000

@Composable
private fun roles(): List<PantrixColor> {
    val colors = PantrixTheme.colors
    return listOf(colors.info, colors.success, colors.warning, colors.danger)
}

private const val ROLES = 4

Farklı yükseklikte slaytlar

Slaytların yüksekliği birbirinden farklı ve carousel'e yükseklik verilmemiş. Carousel ekrandaki slaydın yüksekliğindedir; bir slayttan ötekine geçerken yüksekliği de onunla birlikte, sıçramadan değişir. Altındaki satır bunu gösterir: slaytla birlikte aşağı ve yukarı kayar.

var slide by rememberSaveable { mutableIntStateOf(0) }
PantrixCarousel(
    pageCount = NOTES.size,
    currentPage = slide,
    onPageChange = { slide = it },
    contentDescription = "Notlar",
    loop = true,
    tagKey = "notes"
) { index ->
    PantrixSurface(modifier = Modifier.fillMaxWidth(), border = PantrixTheme.colors.divider) {
        PantrixText(text = NOTES[index], modifier = Modifier.padding(PantrixTheme.spacing.lg))
    }
}
PantrixText(
    text = "Bu satır, slaytların yüksekliğiyle birlikte yer değiştirir.",
    color = PantrixTheme.colors.textSecondary
)

private val NOTES = listOf(
    "Kısa bir not.",
    "Daha uzun bir not: birkaç satır sürer, çünkü anlatacak daha çok şeyi vardır. Carousel bu slayda gelirken " +
        "yüksekliği de yavaş yavaş artar; altındaki satır aşağı kayar.",
    "Orta boy bir not, iki satır kadar tutar ve öncekinden kısadır."
)

Kendi renkleriyle

Kendi renkleriyle: CarouselColors noktaları, noktaların izini, düğmeleri ve slaytın üstündeki örtüyü boyar. Burada noktalar markanın değil başarının rengindedir; verilmeyen her renk temanınkidir.

var slide by rememberSaveable { mutableIntStateOf(0) }
PantrixCarousel(
    pageCount = TITLES.size,
    currentPage = slide,
    onPageChange = { slide = it },
    modifier = Modifier.height(160.dp),
    colors = CarouselColors(
        indicator = PantrixTheme.colors.success.color,
        indicatorTrack = PantrixTheme.colors.success.container,
        control = PantrixTheme.colors.success.color
    ),
    contentDescription = "Öne çıkanlar",
    tagKey = "green"
) { index ->
    CarouselSlide(index, modifier = Modifier.fillMaxSize())
}

@Composable
private fun CarouselSlide(
    index: Int,
    modifier: Modifier = Modifier
) {
    val role = roles()[index % ROLES]
    PantrixSurface(modifier = modifier, color = role.container, contentColor = role.onContainer) {
        Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
            PantrixText(text = TITLES[index % TITLES.size], style = PantrixTheme.typography.title)
        }
    }
}

@Composable
private fun roles(): List<PantrixColor> {
    val colors = PantrixTheme.colors
    return listOf(colors.info, colors.success, colors.warning, colors.danger)
}

private const val ROLES = 4

private val TITLES = listOf("Yeni gelenler", "Haftanın seçimi", "İndirimdekiler", "Son fırsat")

API

pageCount

Yan yana duran slaytlar, biri ekranda: resimler, kartlar, bir tanıtımın adımları. Kaydırmak onları çevirir. Altındakiler carousel'in nerede olduğunu söyler ve ekrana dokunamayan okuyucu için slaytları çevirir.

ParametreTürVarsayılanNe olduğu
pageCountIntKaç slayt olduğu.
currentPageIntEkrandaki slayt, bir sayfalayıcınınki gibi sıfırdan sayılır. Uçlardan birinin ötesindeki değer en yakın slayt sayılır. PantrixPagination sayfalarını, yazdığı gibi, birden sayar: onun sayfası bunun bir fazlasıdır.
onPageChange(page: Int) -> UnitBir kaydırmanın bittiği slayt ve bir düğmenin, bir noktanın, bir tuşun ya da kendiliğinden ilerlerken carousel'in istediği slayt bildirilir.
modifierModifierModifierCarousel'e uygulanır: slaytlara ve altındakilere.
contentDescriptionString?nullEkran okuyucu için carousel'in içinde ne olduğu: "Öne çıkan ürünler".
swipeEnabledBooleantrueKaydırmanın slaytları çevirip çevirmediği. Kendi düğmesiyle ilerleyen bir tanıtım bunu kapatır.
loopBooleanfalseSlaytların dönüp dönmediği: sonuncudan ilkine geçilir. Tek slaytlı bir carousel'in gidecek yeri yoktur.
autoAdvanceMillisInt0Carousel'in kendiliğinden sonrakine geçmeden önce bir slaytta ne kadar kaldığı. Yalnızca okuyucusunun çevirdiği bir carousel için sıfırdır. Bir slaydı okumaya yetecek kadar uzun verilir: beş saniye ya da daha fazla.
styleCarouselStyle?nullBu çağrının kendi stili: çevresindeki her stili ezer, yoğunluk ona da uygulanır. Yalnızca verdiği alanlar değişir ve her platformda değişir.
colorsCarouselColors?nullBu çağrının, slaytların altındakiler için kendi renkleri. Yalnızca verdiği renkler değişir.
tagKeyString?nullOtomasyon için dilden bağımsız bir anahtar: carousel'in etiketi Carousel_<tagKey> olur ve parçaları onun içinde adlandırılır: klavye odağını alan Carousel_<tagKey>.Slides_view, .Page_<index>, .Control_previous, .Control_next, .Control_pause ve .Indicator_position. Slaytların döndüğü ve komşu slaytların göründüğü yerde iki slaytlı bir carousel'de aynı slayt iki yanda birden durur: aynı etiketle iki kez.
page@Composable (index: Int) -> UnitSırasına göre bir slayt.

CarouselStyle

PantrixCarousel'in geometrisi ve slaytlarının altında ne gösterdiği. Her platformda aynıdır: düğmeler platforma göre değil, okuyucunun parmakla mı fareyle mi kullandığına göre gelir ve gider. Boşluklar yoğunlukla ölçeklenir, nokta ölçeklenmez.

ParametreTürVarsayılanNe olduğu
pageSpacingDpDp.Unspecifiedİki slaydın arasındaki boşluk. Bir slayt yerini sonrakine bırakırken ve komşuları peek ile görünen bir slaydın yanında görünür.
peekDpDp.UnspecifiedEkrandaki slaydın iki yanında bırakılan yer: komşuları bu yerde görünür.
indicatorSizeDpDp.UnspecifiedGöstergenin bir noktası.
indicatorGapDpDp.Unspecifiedİki noktanın arası.
indicatorSpacingDpDp.UnspecifiedSlaytlarla altındakilerin arası. Altındakiler slaytların üstünde duruyorsa onlarla slaytların kenarlarının arası.
indicatorCarouselIndicator?nullCarousel'in nerede olduğunu neyin söylediği.
controlsCarouselControls?nullİki düğmenin nerede gösterildiği.
placementCarouselPlacement?nullBunların slaytların altında mı, üstünde mi durduğu.

CarouselColors

Temanın renklerini almayan bir carousel için PantrixCarousel'in slaytlarının altında neyle boyandığı: verilen renk kullanılır, verilmeyen temanınki olarak kalır. Slaytlar çağıranın kendisinindir.

ParametreTürVarsayılanNe olduğu
indicatorColorColor.UnspecifiedEkrandaki slaydın noktası. primary rolünün color'ı.
indicatorTrackColorColor.UnspecifiedÖteki slaytların noktaları. Temanın borderStrong'u: bir kontrolün kendi işareti gibi zeminden ayırt edilir.
controlColorColor.UnspecifiedDüğmeler. Temanın onSurface'ı, bir ikonun rengi.
overlayColorColor.UnspecifiedSlaytların üstünde durduklarında noktaların ve her düğmenin arkasındaki dolgu. Temanın onSurface'ı: temanın zeminlerinin ters tonu, slayt arkasından görünsün diye saydamlaştırılmış. Buraya temanın rol renklerinden biri verilirse, üstüne yazılanlar için temanın onunla eşleştirdiği renk de gelir.

Erişilebilirlik