Pantrix UI

Material 3 köprüsü

Material 3 kullanan bir uygulamanın Pantrix'e nasıl geçebileceği ya da ikisini bir arada nasıl kullanabileceği: iki temanın aynı renkleri, yazıları ve şekilleri konuşması. Sorun Pantrix'e özgü değildir.

Kütüphanenin kendisi Material'sız kalır: köprü Material'ı kullanan tek modüldür ve hiçbir kütüphane modülü ona bağlanmaz. Burada Material 3 hakkında söylenen her şey Material 3 1.9.0'ın ve 1.11.0-alpha07'nin kaynaklarında okunmuş ya da bu depoda koşan bir testte görülmüştür (11. bölüm).

1. Sorun

2. Kurulum

commonMain.dependencies {
    implementation("com.pantrixui:material3:0.1.0-alpha03")
}

Modül Material 3'ün son kararlı sürümüne, 1.9.0'a göre derlenir. Bu bir alt sınırdır: uygulamada daha yeni bir Material 3 varsa Gradle onu seçer ve köprü onunla çalışır. Material 3'ün CMP'deki sürümleri 1.9.0'dan sonra yalnızca alfa ve beta olarak çıktı; köprü kullanıcısına bir alfa dayatmamak için kararlı olana bağlanır. Tema API'si 1.9.0 ile 1.11.0-alpha07'de aynıdır: 48 renk, 15 yazı stili, 5 şekil.

3. İki yön

Material bir uygulamada Pantrix

MaterialTheme(colorScheme = appScheme) {
    Scaffold { padding ->
        PantrixThemeFromMaterial {
            // Pantrix'in bileşenleri uygulamanın Material temasının renkleri, yazıları ve şekilleriyle
            PantrixButton(text = "Kaydet", onClick = {}, modifier = Modifier.padding(padding))
        }
    }
}

PantrixThemeFromMaterial çevresindeki MaterialTheme'i okur ve bir PantrixTheme kurar. Renkler şemanın toPantrixColors()'ıdır ve tema şema kadar koyudur. Yazılar Material'ın ölçeğinden, Pantrix'in kendi ölçeği üstüne kurulur; şekiller yarıçaplarına göre alınır. Geri kalan her şey (boşluklar, hareket, dil, analitik) Pantrix'in kendisinindir ya da içerideki bir PantrixTheme'in verdiği.

Ekranın en dıştaki Pantrix teması bu olduğu için Android'in çubuklarının simgelerini ve iOS'un durum çubuğunu, klavyesini ve kontrollerini şemanın koyuluğuna uydurur (sistem çubukları rehberi). Çubuklarını kendisi ayarlayan ya da renkli çubuklu bir Material uygulaması PantrixThemeFromMaterial(followSystemBars = false) { … } yazar.

Pantrix bir uygulamada Material

PantrixTheme {
    MaterialThemeFromPantrix {
        // Pantrix'te olmayan bir Material bileşeni, Pantrix'in temasıyla
        Slider(value = volume, onValueChange = { volume = it })
    }
}

MaterialThemeFromPantrix çevresindeki Pantrix temasını okur ve bir MaterialTheme kurar: şema toColorScheme(), yazı ölçeği toMaterialTypography(), şekiller toMaterialShapes().

Düz dönüşümler

İki sarmalayıcının altında altı fonksiyon var; bir uygulama temasını kendisi kuracaksa onları kullanır:

Material → PantrixPantrix → Material
ColorScheme.toPantrixColors(base)PantrixColors.toColorScheme()
Typography.toPantrixTypography(base)PantrixTypography.toMaterialTypography()
Shapes.toPantrixShapes(base)PantrixShapes.toMaterialShapes(fallback)

Örnek uygulama

samples/pantrix-material3 iki yönü tek ekranda gösterir. Aynı form bir kez Material'ın bileşenleriyle, bir kez Pantrix'inkilerle çizilir. Uygulama bir Material uygulaması olarak başlar (markasının şemasıyla, PantrixThemeFromMaterial). Bir düğmeyle Pantrix'in kendi temasıyla yazılmış bir uygulamaya döner (MaterialThemeFromPantrix). Ekran öteki temaya değerleriyle taşınır: yalnızca görünüş değişir. README'si nasıl çalıştırılacağını söyler.

4. Eşleme tabloları

Renkler: Material → Pantrix

PantrixMaterial
primary rolü (color, onColor, container, onContainer)primary, onPrimary, primaryContainer, onPrimaryContainer
danger rolüerror, onError, errorContainer, onErrorContainer
neutral rolüsecondary, onSecondary, secondaryContainer, onSecondaryContainer
backgroundbackground
surfacesurfaceContainerLow
onSurfaceonSurface
textPrimaryonBackground
textSecondaryonSurfaceVariant
textInverseinverseOnSurface
border, borderStrongoutline
divideroutlineVariant
scrimscrim'in rengi, base'in saydamlığıyla
success, info, warning, borderHover, focusRing, disabledContainer, disabledContent, textDisabled, chartMaterial'da karşılığı yok: base'den (5. bölüm)

İki eşleme bilerek seçildi:

Renkler: Pantrix → Material

MaterialPantrix
primary, onPrimary, primaryContainer, onPrimaryContainerprimary rolü
secondary ve eşlerineutral rolü
tertiary ve eşleriinfo rolü
error ve eşleridanger rolü
background, surfacebackground (Material'ın kendi şemalarındaki gibi ikisi aynı)
onBackgroundtextPrimary
onSurfaceonSurface
onSurfaceVarianttextSecondary
surfaceContainerLowsurface
surfaceContainer, surfaceContainerHigh, surfaceContainerHighestsurface'in üstüne textPrimary'den %4, %8, %12
surfaceContainerLowestYazıdan uzak olan zemin: açık temada surface, koyu temada background
surfaceDim, surfaceBrightİki uç: yazıya doğru olanı %16, öteki en uzak zemin
surfaceVariantsurfaceContainerHighest
surfaceTintprimary.color
inverseSurface, inverseOnSurfaceneutral.color, textInverse
inversePrimaryprimary.container
outline, outlineVariantborderStrong, border
scrimscrim, tam saydamsızlıkta (Material bileşeni kullanırken kendisi %32'ye indirir)
primaryFixed, primaryFixedDim, onPrimaryFixed, onPrimaryFixedVariant ve secondary, tertiary için eşleriRolün container'ı ve onContainer'ı

outlineVariant Pantrix'in bölücüsünden değil kutunun kenarından gelir. Material 3 1.9.0 çerçeveli düğmeyi, seçilmemiş çipi ve çerçeveli kartı bu renkle çizer. Pantrix'in bölücüsüyle bu kenar yüzeye karşı açıkta da koyuda da 1,24:1'de kalıyor, zor seçiliyordu. Pantrix'in kendi alan ve çip kenarıyla (border) açıkta 1,47:1, koyuda 1,62:1'dir; Material'ın temel şemasında aynı kenar 1,57:1 ve 1,82:1'dir. Bedeli: Material'ın bölücüleri (HorizontalDivider da bu rengi kullanır) Pantrix'inkilerden bir ton koyu çizilir.

Yazı

Her stil boyca karşılığı olanı alır. Pantrix'in ölçeği: display 36, headline 28, title 22, callout 18, body 16, label 14, footnote 12, caption 11 ve eş aralıklı code 14. Material'ın temel ölçeği: display 57/45/36, headline 32/28/24, title 22/16/14, body 16/14/12, label 14/12/11.

PantrixMaterial → PantrixPantrix → Material
displaydisplaySmalldisplayLarge, displayMedium, displaySmall
headlineheadlineMediumheadlineLarge, headlineMedium
titletitleLargeheadlineSmall, titleLarge
calloutbodyLarge'ın yazı tipi ve ağırlığı, base'in callout boyunda—
bodybodyLargetitleMedium, bodyLarge
labellabelLargetitleSmall, bodyMedium, labelLarge
footnotebodySmallbodySmall, labelMedium
captionlabelSmalllabelSmall
codebase'in code'u—

Material'ın vurgulu stilleri (…Emphasized) düz stilleriyle aynıdır. 1.9.0'da vurgulu stilleri ayrıca veren kurucu internal'dır; açık kurucu bir uygulamanın ölçeğini böyle kurar.

Şekiller

Basamaklar adlarına göre değil yarıçaplarına göre eşlenir. Material'ın ölçeği Pantrix'inkinden bir basamak daha yuvarlaktır: Material'ın küçük basamağı 8 dp, Pantrix'inki 4 dp. Adlara göre eşlenseydi Material temasındaki her Pantrix bileşeni iki kat yuvarlak olurdu; 18 dp'lik bir onay kutusu 8 dp köşeyle daireye döner, radyo düğmesine benzerdi. Yarıçapa göre eşlenince Material'ın kendi ölçeği Pantrix'in kendi ölçeğini verir; bir bileşen öteki sistemin temasında da kendi temasındaki kadar yuvarlaktır.

PantrixMaterial → PantrixPantrix → Material
xs (2 dp)base'in xs'i—
sm (4 dp)extraSmall (4 dp)extraSmall
md (8 dp)small (8 dp)small
lg (12 dp)medium (12 dp)medium
xl (16 dp)large (16 dp)large ve extraLarge

Pantrix'in xs'i Material'ın her basamağından daha az yuvarlaktır; base'den gelir. Material'ın extraLarge'ı (28 dp) Pantrix'in her basamağından daha yuvarlaktır: Material → Pantrix yönünde karşılığı yoktur, öteki yönde en yuvarlak basamağı, xl'yi alır. Böylece Material'ın diyalogları ve alt sayfaları Pantrix'in köşeli bir markasında da köşeli olur.

none (köşeli) ile full (tam yuvarlak) iki sistemde de aynıdır. Material yalnızca köşelerden yapılmış şekil (CornerBasedShape) alır: köşelerden yapılmamış bir Pantrix şekli o basamakta fallback'in şeklini alır (varsayılanı Material'ın kendi ölçeği). Material'ın deneysel üç şekli (largeIncreased, extraLargeIncreased, extraExtraLarge) eşlenmez.

5. Karşılığı olmayanlar ve base

Material'ın şemasında başarı, bilgi ve uyarı rolü, üstüne gelinen kenar, odak halkası, devre dışı renkler ve grafik renkleri yoktur. toPantrixColors(base) bunları base'den alır. Varsayılan base, Pantrix'in kendi renkleridir, şema kadar koyu: koyu bir şema için PantrixColors.Dark. Bir uygulama kendi başarı yeşilini vermek isterse kendi base'ini verir:

val colors = appScheme.toPantrixColors(base = PantrixColors.Light.copy(success = brandGreen))

Yazıda da callout'un boyu ve code base'den gelir; toPantrixTypography(base)'e verilen ölçek genellikle rememberPantrixTypography()'dir. Şekillerde xs base'den gelir; toPantrixShapes(base)'in varsayılanı Pantrix'in kendi ölçeğidir.

6. Gidip gelme

7. Karışık ekran: içerik rengi ve yazı stili

İki sarmalayıcı kökte öteki sistemin değerlerini de doldurur:

Ekranın derinindeki bir sınır için iki küçük sarmalayıcı daha var:

Surface(color = MaterialTheme.colorScheme.primaryContainer) {
    // Material'ın yüzeyindeki Pantrix içeriği, yüzeyin içerik rengini alır
    PantrixContentFromMaterial { PantrixText("Taslak kaydedildi") }
}

PantrixSurface(color = PantrixTheme.colors.primary.color, contentColor = PantrixTheme.colors.primary.onColor) {
    // Pantrix'in dolgusundaki Material içeriği, dolgunun içerik rengini alır
    MaterialContentFromPantrix { Text("Yeni") }
}

8. Material'ın temel şeması Pantrix'in kurallarıyla

Material'ın temel şemaları (lightColorScheme(), darkColorScheme()) Pantrix renklerine çevrilip Pantrix'in kendi renklerine uyguladığı kurallarla ölçüldü (WCAG 2.2: yazı 4.5:1, bir kontrolün işareti ve odak halkası 3:1):

MaterialContrastTest bu sonucu tutar: eşleme ya da Material'ın şeması değişirse test düşer.

9. Köprüde olmayanlar

10. Test etmek

Köprünün testleri ui/material3/src/commonTest'te, beş hedefte koşar: eşlemeler alan alan, gidip gelme, iki sarmalayıcı ve karışık ekranın içerik rengi, Material'ın temel şemasının kontrast ölçümü. Android'in ana makine ağacında ortak testler koşmadığından, iki sarmalayıcıyı Robolectric'te ayrıca bir test çizer (MaterialThemesOnAndroidTest).

Bir uygulama kendi temasını şöyle sınar:

@Test
fun pantrix_s_screen_takes_the_app_s_colours() = runComposeUiTest {
    lateinit var colors: PantrixColors
    setContent { MaterialTheme(colorScheme = appScheme) { PantrixThemeFromMaterial { colors = PantrixTheme.colors } } }
    waitForIdle()
    assertEquals(appScheme.primary, colors.primary.color)
}

11. Doğrulananlar ve doğrulanmayanlar

Doğrulananlar

Doğrulanmayanlar