Popover
Bir öğenin yanında duran ve o öğe hakkında, öğenin kendisinin gösterebileceğinden fazlasını taşıyan katman: bir durumun ne anlama geldiği, bir alanın ne beklediği, bir satır için birkaç kontrol.
import com.pantrixui.components.overlay.popover.PantrixPopover
- Başlık.
titlepopover'ın başında durur ve içerik kayarken yerinde kalır. Bir satırdan uzun her popover'a verilir. - İçerik.
contentbaşlığın altında bir sütundur: bir metin, bir bağlantı, birkaç düğme. - Yön ve hiza.
sidepopover'ın çapanın hangi yanında açılacağını,alignmento yan boyunca nasıl hizalanacağını söyler: söylenmezse altta açılır ve çapaya ortalanır. İstenen yanda yer yoksa karşı yana geçer. - Pencerenin içinde. Pencerenin kenarlarına, sistem çubuklarına ve klavyeye stilin
margin'inden fazla yaklaşmaz ve o yerden büyük olmaz: içeriği satır atlar, sığmayan başlığın altında kayar. - Kapatılamayan popover.
dismissible = falseile dışına basmak, geri tuşu ve Escape kapanmasını istemez: yalnızca içindeki bir şeyin kapattığı popover için. - Dokunma ve fare. Dokunarak ya da tıklayarak açılınca odak olduğu yerde kalır; klavye devreye girince popover odağı alır. Açıkken altındaki sayfa odak göstermez.
- Renkler ve stil.
colors(PopoverColors) dolguyu, başlığın ve kenar çizgisinin rengini;style(PopoverStyle) köşeleri, genişlikleri, en çok yüksekliği, gölgeyi ve çapaya uzaklığı verir. Yalnızca verilen alanlar değişir, gerisi temanın kalır. - Platformlar. Popover her platformda aynı görünür; fark stildedir. En geniş hâli Android'de ve iOS'ta 320, masaüstünde ve web'de 360 dp'dir; köşeleri Android'de ve iOS'ta temanın orta, masaüstünde ve web'de küçük köşesidir.
Örnekler
Bilgi
En yalın hâli: bir satırın yanındaki bilgi düğmesi popover'ı açar; içinde satır hakkında daha fazlası ve bir bağlantı var. Popover'ın açık olup olmadığı ekranın durumudur (visible). Popover kendini kapatmaz: kapanmak istediğinde onDismissRequest'i çağırır, visible'ı false yapan bu koddur. İçindeki bir kontrole basmak kapanmasını istemez: bağlantı popover'ı kendi onClick'inde kapatır.
Dışına basmak, geri tuşu ve Escape kapatır. Klavyeyle açılınca odak bağlantıdadır; kapanınca düğmeye döner. Kartın "Son olay" satırı en son ne olduğunu söyler.
var open by rememberSaveable { mutableStateOf(false) }
val report = LocalExampleEvents.current
Row(verticalAlignment = Alignment.CenterVertically) {
PantrixText(text = "Teslimat: Salı")
PantrixPopover(
visible = open,
onDismissRequest = {
open = false
report("Teslimat popover'ı kapatıldı")
},
anchor = {
PantrixIconButton(
imageVector = PantrixIcons.Info,
contentDescription = "Teslimat ayrıntıları",
onClick = { open = true },
tagKey = "open_delivery"
)
},
title = "Teslimat",
tagKey = "delivery"
) {
PantrixText(text = "Salı günü 09.00 ile 12.00 arasında gelir. Kurye on dakika önce arar.")
PantrixLink(
text = "Kargoyu izle",
onClick = {
open = false
report("Kargo izleme açıldı")
},
tagKey = "track"
)
}
}
Yön ve hiza
side popover'ın çapanın hangi yanında açılacağını, alignment o yan boyunca nasıl hizalanacağını söyler. Söylenmezse popover altta açılır ve çapaya ortalanır: PopoverSide.Bottom ve PopoverAlignment.Center.
Baş ve Son yazı yönüne göre değişir: soldan sağa bir düzende Baş soldur. Popover çapanın yanındayken (Baş ya da Son) hiza dikeydir: Baş üst kenarları, Son alt kenarları buluşturur.
İstenen yanda yer yoksa popover karşı yana geçer: Üst'ü seç ve düğme pencerenin üst kenarına yakınken aç. İki yanda da yer yoksa popover istenen yanda kalır ve pencerenin içine, çapanın üstüne kayar.
var open by rememberSaveable { mutableStateOf(false) }
var side by rememberSaveable { mutableStateOf(PopoverSide.Bottom) }
var alignment by rememberSaveable { mutableStateOf(PopoverAlignment.Center) }
val report = LocalExampleEvents.current
PantrixSegmentButton(options = SIDES, selected = side, onSelect = { side = it }, tagKey = "side")
PantrixSegmentButton(
options = ALIGNMENTS,
selected = alignment,
onSelect = { alignment = it },
tagKey = "alignment"
)
Box(modifier = Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) {
PantrixPopover(
visible = open,
onDismissRequest = {
open = false
report("Popover kapatıldı")
},
anchor = {
PantrixButton(
text = "Aç",
onClick = { open = true },
variant = ButtonVariant.Outline,
tagKey = "open_placed"
)
},
side = side,
alignment = alignment,
tagKey = "placed"
) {
PantrixText(text = "side = ${side.name}, alignment = ${alignment.name}")
}
}
private val SIDES = listOf(
SegmentOption(value = PopoverSide.Top, label = "Üst", tagKey = "top"),
SegmentOption(value = PopoverSide.Bottom, label = "Alt", tagKey = "bottom"),
SegmentOption(value = PopoverSide.Start, label = "Baş", tagKey = "start"),
SegmentOption(value = PopoverSide.End, label = "Son", tagKey = "end")
)
private val ALIGNMENTS = listOf(
SegmentOption(value = PopoverAlignment.Start, label = "Baş", tagKey = "start"),
SegmentOption(value = PopoverAlignment.Center, label = "Orta", tagKey = "center"),
SegmentOption(value = PopoverAlignment.End, label = "Son", tagKey = "end")
)
Kenarda
Pencerenin bitiş kenarına yakın bir çapa. Popover çapasına ortalanır; çapa kenara yakınken ortalanan popover pencereden taşardı. Taşmaz: kenardan stilin margin'i kadar içeride kalacak şekilde kayar.
Dar bir pencerede dene: daraltılacak olan, uygulamanın kendi penceresidir. Popover yerini gerçek pencereye göre seçer, bir kartın pencere seçicisinin örneğine verdiği pencereye göre değil; bu kartta o seçici bu yüzden yoktur. Yeterince geniş bir pencerede kartın yanında popover'a yer kalır; orada popover kaymaz, düğmeye ortalanır.
var open by rememberSaveable { mutableStateOf(false) }
val report = LocalExampleEvents.current
Box(modifier = Modifier.fillMaxWidth(), contentAlignment = Alignment.CenterEnd) {
PantrixPopover(
visible = open,
onDismissRequest = {
open = false
report("Kenardaki popover kapatıldı")
},
anchor = {
PantrixIconButton(
imageVector = PantrixIcons.MoreHorizontal,
contentDescription = "Paylaşım ayrıntıları",
onClick = { open = true },
tagKey = "open_shared"
)
},
title = "Paylaşım",
tagKey = "shared"
) {
PantrixText(text = "Bu klasörü üç kişi görebiliyor: Ada, Deniz ve Umut.")
}
}
Alanın yanında
Bir alanın ne beklediğini söyleyen popover. Çapa alanın tamamıdır: popover alanın altında, alignment = PopoverAlignment.End ile sonuna hizalı açılır. Açan, alanın sonundaki bilgi düğmesidir.
Popover açıkken altındaki sayfa odak göstermez: alana yazarken açarsan, popover açıkken alan durgun çizilir. Kapanınca odak yine çapadadır.
var open by rememberSaveable { mutableStateOf(false) }
val report = LocalExampleEvents.current
val iban = rememberTextFieldState()
PantrixPopover(
visible = open,
onDismissRequest = {
open = false
report("IBAN yardımı kapatıldı")
},
anchor = {
PantrixTextField(
state = iban,
modifier = Modifier.fillMaxWidth(),
label = "IBAN",
placeholder = "TR00 0000 0000 0000 0000 0000 00",
trailingIcon = {
PantrixIconButton(
imageVector = PantrixIcons.Info,
contentDescription = "IBAN nedir?",
onClick = { open = true },
size = ButtonSize.Small,
tagKey = "open_iban_help"
)
},
tagKey = "iban"
)
},
alignment = PopoverAlignment.End,
title = "IBAN",
tagKey = "iban_help"
) {
PantrixText(text = "TR ile başlayan 26 haneli hesap numarası. Banka uygulamanda hesap ayrıntılarında yazar.")
}
Onay
Küçük bir onay: geniş bir pencerede bir dialog yerine, işin başladığı düğmenin yanında. İçinde bir cümle ve iki düğme var; her düğme popover'ı kendi onClick'inde kapatır.
Güvenli seçenek önce gelir: klavyeyle açılınca odak ilk kontrolde, "Vazgeç"tedir. alignment = PopoverAlignment.Start popover'ı düğmenin başına hizalar.
var open by rememberSaveable { mutableStateOf(false) }
val report = LocalExampleEvents.current
PantrixPopover(
visible = open,
onDismissRequest = {
open = false
report("Silme onayı kapatıldı")
},
anchor = {
PantrixButton(
text = "Dosyayı sil…",
onClick = { open = true },
variant = ButtonVariant.Outline,
tagKey = "open_confirm"
)
},
alignment = PopoverAlignment.Start,
title = "Dosya silinsin mi?",
tagKey = "delete_file"
) {
PantrixText(text = "Rapor.pdf her cihazdan kaldırılır.")
Row(horizontalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.sm)) {
PantrixButton(
text = "Vazgeç",
onClick = {
open = false
report("Silmekten vazgeçildi")
},
variant = ButtonVariant.Text,
tagKey = "cancel_delete"
)
PantrixButton(
text = "Sil",
onClick = {
open = false
report("Dosya silindi")
},
variant = ButtonVariant.Destructive,
tagKey = "confirm_delete"
)
}
}
Seçmek zorunlu
dismissible = false: dışına basmak, geri tuşu ve Escape bir şey yapmaz, ekran okuyucunun kapatma eylemi de yoktur. Kapatması gereken şey içindedir: çıkış iki düğmedir. dismissible yalnızca böyle, içindeki bir şeyin kapattığı bir popover için false yapılır.
onDismissRequest boş bırakıldı: bu popover'da hiç çağrılmaz.
var open by rememberSaveable { mutableStateOf(false) }
val report = LocalExampleEvents.current
PantrixPopover(
visible = open,
onDismissRequest = {},
anchor = {
PantrixButton(
text = "Çerez tercihi",
onClick = { open = true },
variant = ButtonVariant.Outline,
tagKey = "open_cookies"
)
},
alignment = PopoverAlignment.Start,
title = "Çerezler",
dismissible = false,
tagKey = "cookies"
) {
PantrixText(text = "Ölçüm çerezlerine izin veriyor musun?")
Row(horizontalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.sm)) {
PantrixButton(
text = "Yalnız gerekli",
onClick = {
open = false
report("Yalnız gerekli çerezler")
},
variant = ButtonVariant.Text,
tagKey = "cookies_needed"
)
PantrixButton(
text = "İzin ver",
onClick = {
open = false
report("Çerezlere izin verildi")
},
tagKey = "cookies_all"
)
}
}
Uzun içerik
Otuz satır stilin en çok yüksekliğine (PopoverStyle.maxHeight) sığmaz: popover o yükseklikte kalır, başlık yerinde durur ve içerik altında kayar.
İçinde odaklanacak bir kontrol yoktur. Bu yüzden klavyede odağı popover'ın kendisi alır ve kaydıran tuşlar içeriği kaydırır: ok tuşları, Page Up ve Page Down, boşluk, Home ve End.
var open by rememberSaveable { mutableStateOf(false) }
val report = LocalExampleEvents.current
PantrixPopover(
visible = open,
onDismissRequest = {
open = false
report("Sürüm notları kapatıldı")
},
anchor = {
PantrixButton(
text = "Sürüm notları",
onClick = { open = true },
variant = ButtonVariant.Outline,
tagKey = "open_notes"
)
},
alignment = PopoverAlignment.Start,
title = "Sürüm notları",
tagKey = "notes"
) {
(1..30).forEach { number -> PantrixText(text = "$number. değişiklik: küçük bir düzeltme.") }
}
Kendi stili
style yalnızca bu popover'ın geometrisini değiştirir: PopoverStyle'ın verilen alanları değişir, gerisi temanın ve platformun stilinden gelir. Burada popover en çok 220dp genişliğindedir ve metin o genişlikte satır atlar; köşeleri temanın büyük köşesidir (ShapeRole.Large) ve çapasından 16dp uzakta durur.
Çapaya uzaklık (gap) temanın yoğunluğuyla ölçeklenir; en çok genişlik ve köşeler ölçeklenmez.
var open by rememberSaveable { mutableStateOf(false) }
PantrixPopover(
visible = open,
onDismissRequest = { open = false },
anchor = {
PantrixButton(
text = "Kısayollar",
onClick = { open = true },
variant = ButtonVariant.Outline,
tagKey = "open_shortcuts"
)
},
alignment = PopoverAlignment.Start,
title = "Kısayollar",
style = PopoverStyle(shape = ShapeRole.Large, maxWidth = 220.dp, gap = 16.dp),
tagKey = "shortcuts"
) {
PantrixText(text = "Ctrl+F arar, F5 yeniler. Del seçili dosyayı siler; geri almak için Ctrl+Z.")
}
Kendi renkleri
colors popover'a temanın değil, verilen renkleri verir: burada temanın hiçbir rolünde olmayan, uygulamanın kendi moru. PopoverColors'ın yalnızca verilen alanları değişir, gerisi temanın kalır.
PopoverColors dolguyu, başlığı ve kenar çizgisini boyar; içeriğin rengi onda yoktur. Rolü olmayan bir dolguda içeriğin rengini içeriği yazan verir: buradaki metin color = own.onContainer ile yazıldı. Dolgu temanın bir rolünün rengiyse, PantrixTheme.colors.info.container gibi, başlık ve içerik kendiliğinden o rolün eş rengini alır.
var open by rememberSaveable { mutableStateOf(false) }
val report = LocalExampleEvents.current
val own = ownColors()
PantrixPopover(
visible = open,
onDismissRequest = {
open = false
report("Pro popover'ı kapatıldı")
},
anchor = {
PantrixButton(
text = "Pro nedir?",
onClick = { open = true },
variant = ButtonVariant.Outline,
tagKey = "open_pro"
)
},
alignment = PopoverAlignment.Start,
title = "Pro",
colors = PopoverColors(container = own.container, title = own.onContainer, border = own.color),
tagKey = "pro"
) {
PantrixText(text = "Sınırsız proje, paylaşılan klasörler ve öncelikli destek.", color = own.onContainer)
}
Başka temadaki bir bölümde
Sayfanın tersi renkte bir bölüm ve içinden açılan bir popover. Bölüm ikinci bir temadır (PantrixTheme(darkTheme = …)): açık sayfada koyu, koyu sayfada açık. Popover o temanın içinde çağrıldığı için onun renklerindedir: katmanı pencerenin kökünde kurulsa da çağrıldığı yerin temasını taşır.
var open by rememberSaveable { mutableStateOf(false) }
val report = LocalExampleEvents.current
val pageIsDark = PantrixTheme.colors.background.luminance() < 0.5f
PantrixTheme(darkTheme = !pageIsDark) {
PantrixSurface(modifier = Modifier.fillMaxWidth()) {
Column(modifier = Modifier.padding(PantrixTheme.spacing.md)) {
PantrixPopover(
visible = open,
onDismissRequest = {
open = false
report("Bölümün popover'ı kapatıldı")
},
anchor = {
PantrixButton(text = "Bu bölümden aç", onClick = { open = true }, tagKey = "open_in_part")
},
alignment = PopoverAlignment.Start,
title = "Bu bölüm",
tagKey = "in_part"
) {
PantrixText(text = "Bölümün temasında açıldı.")
}
}
}
}
Dar pencerede sheet
presentation = OverlayPresentation.Adaptive: dar bir pencerede popover alttan bir sheet olur, başlığı sheet'in başlığı, içeriği altında; daha geniş pencerede düğmenin yanında bir popover. Karttaki pencere seçicisinden "Dar" ile "Geniş" arasında geç. Popover'ın varsayılanı her pencerede Popover'dır: bir bilgi kutusu çoğu zaman yanında kalmalıdır.
var open by rememberSaveable { mutableStateOf(false) }
// Kartın penceresi örnek kadar uzundur: dar bir pencerede açılan sheet'e yer kalsın diye örnek uzun tutulur.
Column(Modifier.fillMaxWidth().height(280.dp)) {
PantrixPopover(
visible = open,
onDismissRequest = { open = false },
anchor = { PantrixButton(text = "Teslimat", onClick = { open = true }, tagKey = "open_adaptive_popover") },
title = "Teslimat",
tagKey = "adaptive_popover",
presentation = OverlayPresentation.Adaptive
) {
PantrixText("Salı günü dokuz ile on iki arasında gelir; kurye on dakika önce arar.")
PantrixButton(text = "Kargoyu izle", onClick = { open = false }, tagKey = "adaptive_track")
}
}
API
visible
Bir öğenin yanında duran ve o öğe hakkında, öğenin kendisinin gösterebileceğinden fazlasını taşıyan katman: bir durumun ne anlama geldiği, bir alanın ne beklediği, bir satır için birkaç kontrol.
| Parametre | Tür | Varsayılan | Ne olduğu |
|---|---|---|---|
visible | Boolean | Popover'ın görünüp görünmediği. Temanın hareketiyle girer ve çıkar. | |
onDismissRequest | () -> Unit | dismissible açıkken dışına basılınca, Escape'e ya da geri tuşuna basılınca çağrılır. Popover, visible false olana kadar kalır. | |
anchor | @Composable () -> Unit | Popover'ın yanında durduğu şey: onu açan kontrol. Bu kontrol, popover'ın çağrıldığı yerde ve o yerin istediği gibi yerleşir. Popover onun yerleşim kutusuna göre konumlanır, dokunma hedefinin kapladığı yer de bu kutunun içindedir. | |
modifier | Modifier | Modifier | Popover'ın kendisine, katmanının içinde uygulanır. Çapaya uygulanmaz. |
side | PopoverSide | PopoverSide.Bottom | Popover'ın çapanın hangi yanını tercih ettiği. PopoverSide.Start ve PopoverSide.End yazı yönünü izler. |
alignment | PopoverAlignment | PopoverAlignment.Center | Popover'ın o yan boyunca çapayla nasıl hizalanacağı. |
title | String? | null | Popover'ın en üstündeki başlık. Altındakiler kayarken görünür kalır ve popover açılırken ekran okuyucu onu duyurur. Bir satırdan uzun her popover'a verilir. |
dismissible | Boolean | true | Dışına basmanın, Escape'in, geri tuşunun ve ekran okuyucunun kapatma eyleminin kapanmasını isteyip istemediği. Yalnızca content'teki bir şeyin kapattığı bir popover için false yapılır. |
style | PopoverStyle? | null | Bu ç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. |
colors | PopoverColors? | null | Bu çağrının kendi renkleri. Yalnızca verdikleri değişir, gerisi temanınki kalır. |
tagKey | String? | null | otomasyon için yerele bağlı olmayan bir anahtar: popover'ın etiketi Popover_<tagKey>'dir, çizildiği hâliyle popover'ın üstünde, sheet olarak gösterildiğinde de sheet'in üstünde. |
presentation | OverlayPresentation | OverlayPresentation.Popover | popover'ın nasıl gösterildiği: varsayılan çapanının yanında; pencerenin altından bir sheet olarak, başlığı title, altında content, yanlarında popover'ın kendi boşluğuyla; ya da dar bir pencerede biri, daha geniş pencerede öteki. Açılırken seçilir, kapanana kadar kalır. |
content | @Composable ColumnScope.() -> Unit | Popover'ın içindekiler, başlığın altında bir sütun hâlinde. |
PopoverStyle
PantrixPopover'ın geometrisi: ne kadar genişleyip yükseldiği, çapasından ne kadar uzakta durduğu ve pencerenin kenarlarına ne kadar yaklaştığı.
| Parametre | Tür | Varsayılan | Ne olduğu |
|---|---|---|---|
shape | ShapeSpec | ShapeSpec.Unspecified | Popover'ın köşeleri: Android'de ve iOS'ta temanın orta, masaüstünde ve web'de küçük köşesidir. |
minWidth | Dp | Dp.Unspecified | Popover'ın en az genişliği: içinde ne kadar az şey olursa olsun bundan dar olmaz. |
maxWidth | Dp | Dp.Unspecified | Popover'ın en çok genişliği: daha uzun metin satır atlar. |
maxHeight | Dp | Dp.Unspecified | Popover'ın en çok yüksekliği: bunu aşan içerik başlığın altında kayar. |
elevation | Dp | Dp.Unspecified | Popover'ın uygulamanın üstünde ne kadar yüksekte durduğu, yani gölgesinin ne kadar büyük olduğu. |
gap | Dp | Dp.Unspecified | Çapa ile popover'ın arası. |
margin | Dp | Dp.Unspecified | Popover ile pencerenin kenarları arasında, bir de pencereyi orada örten şeylerle arasında boş bırakılan yer: bir sistem çubuğu, bir ekran çentiği, klavye. |
PopoverColors
Temanın renklerini almayan bir çağrı için PantrixPopover'ın boyandığı renkler: verilen renk kullanılır, verilmeyen temanın kalır.
| Parametre | Tür | Varsayılan | Ne olduğu |
|---|---|---|---|
container | Color | Color.Unspecified | Popover'ın dolgusu. Temanın surface'ı. |
title | Color | Color.Unspecified | Başlık. Temanın textPrimary'si. |
border | Color | Color.Unspecified | Popover'ın çevresindeki ince çizgi: popover'ı, altında duran kendi rengindeki bir yüzeyden ayırır, gölgenin az göründüğü koyu temada olduğu gibi. Temanın kendi zeminlerinde temanın divider'ıdır. Bir dolgunun üstünde, o çizginin okunmayacağı yerde, title'ın bir payıdır: Subtle bir düğmenin kenarı gibi. Saydam bir renk verilirse çizgi çizilmez. |
Erişilebilirlik
- Klavye. Klavyeyle açılınca odağı alır: ilk kontrolü, kontrolü yoksa popover'ın kendisi. O zaman ok tuşları, Page Up ve Page Down, boşluk, Home ve End içeriği kaydırır. Tab içinde kalır; kapanınca odak çapaya, onu açan kontrole döner.
- Ekran okuyucu. Popover açılırken başlığı duyurulur; başlık içeriğin başlığıdır. Çevresinde basılacak bir scrim olmadığı için ekran okuyucu onu kendi kapatma eylemiyle kapatır.