Anlambilim

Bir bileşenin taşıdığı birincil bilgiler (ör. Text bileşeninin metin dizesi) dışında, kullanıcı arayüzü öğeleri hakkında daha fazla ek bilgi edinmek yararlı olabilir.

Compose'daki bir bileşenin anlamı ve rolü hakkındaki bilgilere söz dizimi denir. Söz dizimi, erişilebilirlik, otomatik doldurma ve test gibi hizmetlere composable'lar hakkında ek bağlam bilgisi sağlamanın bir yoludur. Örneğin, bir kamera simgesi görsel olarak yalnızca bir resim olabilir ancak semantik anlamı "Fotoğraf çek" olabilir.

Uygun semantikleri uygun Compose API'leriyle birleştirerek erişilebilirlik hizmetlerine bileşeniniz hakkında mümkün olduğunca fazla bilgi sağlarsınız. Bu hizmetler daha sonra bileşeni kullanıcıya nasıl göstereceğine karar verir.

Material, Compose kullanıcı arayüzü ve Foundation API'leri, belirli rollerine ve işlevlerine uygun yerleşik anlamlarla birlikte gelir. Ancak mevcut API'ler için bu anlamları değiştirebilir veya özel bileşenler için belirli ihtiyaçlarınıza göre yeni anlamlar ayarlayabilirsiniz.

Semantik özellikler

Semantik özellikler, ilgili derlenebilir öğenin anlamını iletir. Örneğin, Text bileşeni, bu bileşenin anlamı olduğu için text semantik özelliğini içerir. Icon, simgenin anlamını metin olarak aktaran bir contentDescription özelliği (geliştirici tarafından ayarlandıysa) içerir.

Semantik özelliklerin, bir bileşenin anlamını nasıl aktardığını düşünün. Switch kullanmayı düşünebilirsiniz. Kullanıcının gördüğü görünüm:

Şekil 1. "Açık" ve "Kapalı" durumundaki bir Switch.

Bu öğenin anlamını açıklamak için şunları söyleyebilirsiniz: "Bu, "Açık" durumundaki açma/kapatma düğmesi olan bir anahtardır. Etkileşim kurmak için tıklayabilirsiniz."

Anlambilim özellikleri tam olarak bu amaç için kullanılır. Bu Switch öğesinin anlamsal düğümü, Layout Inspector ile görselleştirilen aşağıdaki özellikleri içerir:

Bir Switch bileşeninin anlambilim özelliklerini gösteren Layout Inspector
Şekil 2. Switch composable
öğesinin anlambilim özelliklerini gösteren Layout Inspector.

Role, öğenin türünü belirtir. StateDescription, "Açık" durumuna nasıl referans verileceğini açıklar. Varsayılan olarak bu, "Açık" kelimesinin yerelleştirilmiş bir sürümüdür ancak bağlama göre daha spesifik hale getirilebilir (örneğin, "Etkin"). ToggleableState, Switch'in mevcut durumudur. OnClick özelliği, bu öğeyle etkileşimde bulunmak için kullanılan yönteme referans verir.

Uygulamanızdaki her bir derlenebilir öğenin anlambilim özelliklerini takip etmek birçok güçlü olasılığın kilidini açar:

  • Erişilebilirlik hizmetleri, ekranda gösterilen kullanıcı arayüzünü temsil etmek ve kullanıcıların bu arayüzle etkileşime geçmesine izin vermek için özellikleri kullanır. Talkback, anahtar bileşeni için "Açık; Anahtar; değiştirmek için iki kez dokunun" şeklinde bir duyuru yapabilir. Kullanıcı, anahtarı kapatmak için ekranına iki kez dokunabilir.
  • Test çerçevesi, düğümleri bulmak, onlarla etkileşim kurmak ve iddialarda bulunmak için özellikleri kullanır:
    val mySwitch = SemanticsMatcher.expectValue(
        SemanticsProperties.Role, Role.Switch
    )
    composeTestRule.onNode(mySwitch)
        .performClick()
        .assertIsOff()

Compose temel kitaplığının üzerine inşa edilen birleştirilebilirler ve değiştiriciler, ilgili özellikleri varsayılan olarak sizin için ayarlar. İsteğe bağlı olarak, belirli kullanım alanları için erişilebilirlik desteğini iyileştirmek amacıyla bu özellikleri manuel olarak değiştirebilir veya bileşenlerinizin birleştirme veya temizleme stratejisini değiştirebilirsiniz.

Erişilebilirlik hizmetlerine bileşeninizin belirli içerik türünü bildirmek için çeşitli farklı anlamlar uygulayabilirsiniz. Bu eklemeler, mevcut temel anlamsal bilgileri destekler ve erişilebilirlik hizmetlerinin, bileşeninizin nasıl temsil edildiği, duyurulduğu veya etkileşime geçildiği konusunda ince ayar yapmasına yardımcı olur.

Anlambilim özelliklerinin tam listesi için SemanticsProperties nesnesine bakın. Olası Erişilebilirlik İşlemlerinin tam listesi için SemanticsActions nesnesine bakın.

Başlıklar

Uygulamalar genellikle uzun makaleler veya haber sayfaları gibi metin açısından zengin içeriklere sahip ekranlar içerir. Bu ekranlar genellikle başlıklar içeren farklı alt bölümlere ayrılır:

Kaydırılabilir bir kapsayıcıda makale metni bulunan bir blog yayını.
Şekil 3. Makale metninin kaydırılabilir bir kapsayıcıda yer aldığı bir blog yayını.

Erişilebilirlik gereksinimi olan kullanıcılar, bu tür bir ekranda kolayca gezinme konusunda zorluk yaşayabilir. Bazı erişilebilirlik hizmetleri, gezinme deneyimini iyileştirmek için doğrudan bölümler veya başlıklar arasında daha kolay gezinme olanağı sunar. Bunu etkinleştirmek için bileşeninizin semantik özelliğini tanımlayarak heading olduğunu belirtin:

@Composable
private fun Subsection(text: String) {
    Text(
        text = text,
        style = MaterialTheme.typography.headlineSmall,
        modifier = Modifier.semantics { heading() }
    )
}

Uyarılar ve pop-up'lar

Bileşeniniz bir uyarı veya pop-up (ör. Snackbar) ise erişilebilirlik hizmetlerine yeni bir yapının veya içerik güncellemelerinin kullanıcılara iletilebileceğini bildirmek isteyebilirsiniz.

Uyarı benzeri bileşenler liveRegion semantik özelliğiyle işaretlenebilir. Bu, erişilebilirlik hizmetlerinin kullanıcıyı bu bileşende veya alt bileşenlerinde yapılan değişiklikler hakkında otomatik olarak bilgilendirmesine olanak tanır:

PopupAlert(
    message = "You have a new message",
    modifier = Modifier.semantics {
        liveRegion = LiveRegionMode.Polite
    }
)

Kullanıcıların dikkatinin yalnızca ekrandaki uyarılara veya değişen önemli içeriklere kısaca çekilmesi gereken çoğu durumda liveRegionMode.Polite'ü kullanmanız gerekir.

Rahatsız edici geri bildirimleri önlemek için liveRegion.Assertive öğesini ölçülü bir şekilde kullanmanız gerekir. Kullanıcıların zamana duyarlı içeriklerden haberdar edilmesi gerektiği durumlarda kullanılmalıdır:

PopupAlert(
    message = "Emergency alert incoming",
    modifier = Modifier.semantics {
        liveRegion = LiveRegionMode.Assertive
    }
)

Kullanıcıları sürekli geri bildirimlerle boğmamak için canlı bölgeler, geri sayım zamanlayıcıları gibi sık güncellenen içeriklerde kullanılmamalıdır.

Pencere benzeri bileşenler

ModalBottomSheet'e benzer pencere benzeri özel bileşenlerin, çevredeki içerikten ayırt edilebilmesi için ek sinyallere ihtiyacı vardır. Bunun için paneTitle semantiklerini kullanabilirsiniz. Böylece, ilgili tüm pencere veya bölme değişiklikleri, ana semantik bilgileriyle birlikte erişilebilirlik hizmetleri tarafından uygun şekilde temsil edilebilir:

ShareSheet(
    message = "Choose how to share this photo",
    modifier = Modifier
        .fillMaxWidth()
        .align(Alignment.TopCenter)
        .semantics { paneTitle = "New bottom sheet" }
)

Referans olarak, Material 3'ün bileşenleri için paneTitle'ü nasıl kullandığına bakın.

Hata bileşenleri

Hata benzeri bileşenler gibi diğer içerik türleri için erişilebilirlik ihtiyaçları olan kullanıcılar için ana anlamsal bilgileri genişletmek isteyebilirsiniz. Hata durumlarını tanımlarken erişilebilirlik hizmetlerini error semantikleri hakkında bilgilendirebilir ve genişletilmiş hata mesajları sağlayabilirsiniz.

Bu örnekte TalkBack, ana hata metni bilgilerini okur ve ardından ek, genişletilmiş mesajlar gösterir:

Error(
    errorText = "Fields cannot be empty",
    modifier = Modifier
        .semantics {
            error("Please add both email and password")
        }
)

İlerleme durumu izleme bileşenleri

İlerlemeyi izleyen özel bileşenler için kullanıcıları mevcut ilerleme değeri, aralığı ve adım boyutu da dahil olmak üzere ilerleme değişiklikleri hakkında bilgilendirmek isteyebilirsiniz. Bunu progressBarRangeInfo semantiğiyle yapabilirsiniz. Bu, erişilebilirlik hizmetlerinin ilerleme değişikliklerinden haberdar olmasını ve kullanıcıları buna göre güncellemesini sağlar. Farklı yardımcı teknolojilerin, ilerleme durumunun arttığını veya azaldığını belirtmek için benzersiz yöntemleri de olabilir.

ProgressInfoBar(
    modifier = Modifier
        .semantics {
            progressBarRangeInfo =
                ProgressBarRangeInfo(
                    current = progress,
                    range = 0F..1F
                )
        }
)

Liste ve öğe bilgileri

Birçok öğe içeren özel listelerde ve ızgaralarda, erişilebilirlik hizmetlerinin toplam öğe sayısı ve dizinler gibi daha ayrıntılı bilgiler de alması yararlı olabilir.

Erişilebilirlik hizmetleri, bu uzun listede sırasıyla liste ve öğelerde collectionInfo ve collectionItemInfo semantiklerini kullanarak kullanıcıları metinsel semantik bilgilere ek olarak toplam koleksiyondaki hangi öğe dizini içinde bulundukları konusunda bilgilendirebilir:

MilkyWayList(
    modifier = Modifier
        .semantics {
            collectionInfo = CollectionInfo(
                rowCount = milkyWay.count(),
                columnCount = 1
            )
        }
) {
    milkyWay.forEachIndexed { index, text ->
        Text(
            text = text,
            modifier = Modifier.semantics {
                collectionItemInfo =
                    CollectionItemInfo(index, 0, 0, 0)
            }
        )
    }
}

Durum açıklaması

Bir composable, Android çerçevesinin composable'ın bulunduğu durumu okumak için kullandığı semantikler için bir stateDescription tanımlayabilir. Örneğin, açma/kapatma düğmeli bir bileşen "işaretli" veya "işaretsiz" durumda olabilir. Bazı durumlarda, Oluştur'un kullandığı varsayılan durum açıklaması etiketlerini geçersiz kılmak isteyebilirsiniz. Bunu, bir bileşeni açma/kapatma özelliğine sahip olarak tanımlamadan önce durum açıklaması etiketlerini açıkça belirterek yapabilirsiniz:

@Composable
private fun TopicItem(itemTitle: String, selected: Boolean, onToggle: () -> Unit) {
    val stateSubscribed = stringResource(R.string.subscribed)
    val stateNotSubscribed = stringResource(R.string.not_subscribed)
    Row(
        modifier = Modifier
            .semantics {
                // Set any explicit semantic properties
                stateDescription = if (selected) stateSubscribed else stateNotSubscribed
            }
            .toggleable(
                value = selected,
                onValueChange = { onToggle() }
            )
    ) {
        /* ... */
    }
}

Özel işlemler

Özel işlemler, motor becerilerinde veya başka engellerde olan kullanıcıların etkileşim kurması zor olabileceğinden, kapatmak için kaydırma veya sürükleyip bırakma gibi daha karmaşık dokunmatik ekran hareketleri için kullanılabilir.

Silmek için kaydır hareketini daha erişilebilir hale getirmek istiyorsanız silme işlemini ve etiketini buraya aktararak özel bir işleme bağlayabilirsiniz:

SwipeToDismissBox(
    modifier = Modifier.semantics {
        // Represents the swipe to dismiss for accessibility
        customActions = listOf(
            CustomAccessibilityAction(
                label = "Remove article from list",
                action = {
                    removeArticle()
                    true
                }
            )
        )
    },
    state = rememberSwipeToDismissBoxState(),
    backgroundContent = {}
) {
    ArticleListItem()
}

Ardından TalkBack gibi bir erişilebilirlik hizmeti, bileşeni vurgular ve menüsünde daha fazla işlem olduğunu belirtir. Bu işlem, menüyü kapatmak için kaydırma hareketini temsil eder:

TalkBack işlem menüsünün görselleştirmesi
Şekil 4. TalkBack işlem menüsünün görselleştirmesi.

Özel işlemlerin bir diğer kullanım alanı, daha fazla işleme sahip öğelerin bulunduğu uzun listelerdir. Kullanıcıların her bir öğe için her bir işlemi tek tek incelemesi sıkıcı olabileceğinden bu listeler özel işlemler için idealdir:

=Anahtar Erişimi gezinmesinin ekranda görselleştirilmesi
Şekil 5. Anahtar Erişimi gezinmesinin ekranda görselleştirilmesi.

Özellikle Anahtar Erişimi veya Sesli Erişim gibi etkileşime dayalı yardımcı teknolojiler için yararlı olan gezinme deneyimini iyileştirmek amacıyla, işlemleri tek tek gezinme yerine ayrı bir işlem menüsüne taşımak için kapsayıcıda özel işlemleri kullanabilirsiniz:

ArticleListItemRow(
    modifier = Modifier
        .semantics {
            customActions = listOf(
                CustomAccessibilityAction(
                    label = "Open article",
                    action = {
                        openArticle()
                        true
                    }
                ),
                CustomAccessibilityAction(
                    label = "Add to bookmarks",
                    action = {
                        addToBookmarks()
                        true
                    }
                ),
            )
        }
) {
    Article(
        modifier = Modifier.clearAndSetSemantics { },
        onClick = openArticle,
    )
    BookmarkButton(
        modifier = Modifier.clearAndSetSemantics { },
        onClick = addToBookmarks,
    )
}

Bu durumlarda, özel işlemlere taşırken orijinal alt öğelerin anlamlarını clearAndSetSemantics değiştiricisiyle manuel olarak temizlediğinizden emin olun.

Anahtar Erişimi'ni örnek olarak ele alalım. Kapsayıcı seçildiğinde menüsü açılır ve buradaki iç içe yerleştirilmiş işlemleri listeler:

Makale listesi öğesinin Anahtar Erişimi vurgusu
Şekil 6. Makale listesi öğesinin Anahtar Erişimi vurgusu.
Anahtar Erişimi işlem menüsünün görselleştirmesi.
Şekil 7. Anahtar Erişimi işlem menüsünün görselleştirmesi.

Anlam ağacı

Bir kompozisyon, uygulamanızın kullanıcı arayüzünü tanımlar ve bileşenlerin çalıştırılmasıyla oluşturulur. Kompozisyon, kullanıcı arayüzünüzü tanımlayan bileşenlerden oluşan bir ağaç yapısıdır.

Kompozisyonun yanında anlam ağacı adı verilen paralel bir ağaç bulunur. Bu ağaç, kullanıcı arayüzünüzü Erişilebilirlik hizmetleri ve Test çerçevesi için anlaşılır olacak şekilde alternatif bir şekilde açıklar. Erişilebilirlik hizmetleri, uygulamayı belirli bir ihtiyacı olan kullanıcılara açıklamak için ağacı kullanır. Test çerçevesi, uygulamanızla etkileşime geçmek ve uygulamanız hakkında iddialarda bulunmak için ağacı kullanır. Anlam ağacı, bileşenlerinizi nasıl çizeceğiniz hakkında bilgi içermez ancak bileşenlerinizin anlamsal anlamı hakkında bilgi içerir.

Tipik bir kullanıcı arayüzü hiyerarşisi ve anlamsal ağacı
Şekil 8. Tipik bir kullanıcı arayüzü hiyerarşisi ve anlamsal ağacı.

Uygulamanız, Compose temelinden ve materyal kitaplığından alınan birleştirilebilir öğelerden ve değiştiricilerden oluşuyorsa anlam ağacı sizin için otomatik olarak doldurulur ve oluşturulur. Ancak özel düşük düzeyli birleştirilebilirler eklerken bunların anlamlarını manuel olarak sağlamanız gerekir. Ağınızın, ekrandaki öğelerin anlamını doğru veya tam olarak yansıtmadığı durumlar da olabilir. Bu durumda ağacı uyarlayabilirsiniz.

Örneğin, aşağıdaki özel takvim bileşenini düşünün:

Seçilebilir gün öğeleriyle derlenebilecek özel bir takvim
Şekil 9. Seçilebilir gün öğeleriyle derlenebilecek özel bir takvim.

Bu örnekte takvimin tamamı, Layout kompozit öğesi kullanılarak ve doğrudan Canvas'a çizilerek tek bir düşük düzeyli kompozit öğe olarak uygulanır. Başka bir işlem yapmazsanız erişilebilirlik hizmetleri, bileşimin içeriği ve kullanıcının takvimdeki seçimi hakkında yeterli bilgi almaz. Örneğin, bir kullanıcı 17'yi içeren günü tıklarsa erişilebilirlik çerçevesi yalnızca takvim denetiminin tamamının açıklama bilgilerini alır. Bu durumda TalkBack erişilebilirlik hizmeti "Takvim" veya "Nisan Takvim"i duyurur ve kullanıcı hangi günün seçildiğini merak eder. Bu bileşiği daha erişilebilir hale getirmek için anlamsal bilgileri manuel olarak eklemeniz gerekir.

Birleştirilmiş ve birleştirilmemiş ağaç

Daha önce de belirtildiği gibi, kullanıcı arayüzü ağacındaki her bir bileşen için sıfır veya daha fazla anlambilim özelliği ayarlanabilir. Bir bileşenin anlambilim özelliği ayarlanmamışsa bu bileşen, anlambilim ağacının bir parçası olarak dahil edilmez. Bu sayede, semantik ağacı yalnızca gerçekten semantik anlam içeren düğümleri içerir. Ancak bazen ekranda gösterilen şeyin doğru anlamını iletmek için belirli düğüm alt ağaçları birleştirmek ve bunları tek bir düğüm olarak ele almak da yararlıdır. Böylece, her alt düğümle tek tek uğraşmak yerine bir düğüm grubunu bir bütün olarak değerlendirebilirsiniz. Genel kural olarak, bu ağaçtaki her düğüm, Erişilebilirlik hizmetleri kullanılırken odaklanılabilir bir öğeyi temsil eder.

Bu tür bir derlenebilir öğeye örnek olarak Button verilebilir. Birden fazla alt düğüm içerse bile bir düğmeyi tek bir öğe olarak değerlendirebilirsiniz:

Button(onClick = { /*TODO*/ }) {
    Icon(
        imageVector = Icons.Filled.Favorite,
        contentDescription = null
    )
    Spacer(Modifier.size(ButtonDefaults.IconSpacing))
    Text("Like")
}

Anlam ağacında, düğmenin alt öğelerinin özellikleri birleştirilir ve düğme ağaçta tek bir yaprak düğüm olarak sunulur:

Birleştirilmiş tek yaprak anlamsal temsili
Şekil 10. Birleştirilmiş tek yapraklı semantik gösterim.

Composable'lar ve değiştiriciler, Modifier.semantics (mergeDescendants = true) {} çağrısı yaparak alt öğelerinin anlambilim özelliklerini birleştirmek istediklerini belirtebilir. Bu özelliğin true olarak ayarlanması, anlambilim özelliklerinin birleştirilmesi gerektiğini gösterir. Button örneğinde, Button bileşiği, bu semantics değiştiriciyi içeren clickable değiştiriciyi dahili olarak kullanır. Bu nedenle, düğmenin alt öğe düğümleri birleştirilir. Kompozitinizde birleştirme davranışını ne zaman değiştirmeniz gerektiği hakkında daha fazla bilgi edinmek için erişilebilirlik belgelerini okuyun.

Foundation ve Material Compose kitaplıklarında bu özelliğin ayarlandığı çeşitli değiştiriciler ve birleştirilebilirler vardır. Örneğin, clickable ve toggleable değiştiricileri, alt öğelerini otomatik olarak birleştirir. Ayrıca, ListItem birleşebilir öğesi alt öğelerini birleştirir.

Ağacı inceleme

Anlam ağacı aslında iki farklı ağaçtan oluşur. mergeDescendants true olarak ayarlandığında alt öğeleri birleştiren bir birleştirilmiş anlam ağacı vardır. Birleştirme işlemini uygulamayan ancak her düğümü olduğu gibi koruyan birleştirilmemiş bir anlam ağacı da vardır. Erişilebilirlik hizmetleri, birleştirilmemiş ağacı kullanır ve mergeDescendants mülkünü dikkate alarak kendi birleştirme algoritmalarını uygular. Test çerçevesi varsayılan olarak birleştirilmiş ağacı kullanır.

printToLog() yöntemini kullanarak her iki ağacı da inceleyebilirsiniz. Varsayılan olarak ve önceki örneklerde olduğu gibi, birleştirilen ağaç kaydedilir. Bunun yerine birleştirilmemiş ağacı yazdırmak için onRoot() eşleştiricinin useUnmergedTree parametresini true olarak ayarlayın:

composeTestRule.onRoot(useUnmergedTree = true).printToLog("MY TAG")

Düzen Denetleyici, görüntüleme filtresinde tercih ettiğiniz öğeyi seçerek hem birleştirilmiş hem de birleştirilmemiş anlam ağacını görüntülemenizi sağlar:

Hem birleştirilmiş hem de birleştirilmemiş semantik ağacının görüntülenmesine olanak tanıyan düzen denetleyicisi görüntüleme seçenekleri
Şekil 11. Hem birleştirilmiş hem de birleştirilmemiş semantik ağacının görüntülenmesine olanak tanıyan düzen denetleyicisi görüntüleme seçenekleri.

Düzen Denetleyici, ağacınızdaki her düğüm için hem birleştirilmiş semantikleri hem de özellikler panelinde söz konusu düğümde ayarlanan semantikleri gösterir:

Mantıksal özellikler birleştirildi ve ayarlandı
Şekil 12. Anlambilim özellikleri birleştirildi ve ayarlandı.

Test Çerçevesi'ndeki eşleyiciler varsayılan olarak birleştirilmiş semantik ağacını kullanır. Bu nedenle, içinde gösterilen metni eşleştirerek bir Button ile etkileşimde bulunabilirsiniz:

composeTestRule.onNodeWithText("Like").performClick()

onRoot eşleştiricide olduğu gibi eşleştiricilerin useUnmergedTree parametresini true olarak ayarlayarak bu davranışı geçersiz kılın.

Ağacı uyarlama

Daha önce de belirtildiği gibi, belirli anlambilim özelliklerini geçersiz kılabilir veya temizleyebilir ya da ağacın birleştirme davranışını değiştirebilirsiniz. Bu, özellikle kendi özel bileşenlerinizi oluştururken önemlidir. Doğru özellikleri ve birleştirme davranışını ayarlamadan uygulamanıza erişilemeyebilir ve testler beklediğinizden farklı davranabilir. Test hakkında daha fazla bilgi edinmek istiyorsanız test kılavuzunu inceleyin.