Oluşturulan Anlamsal Bilgiler

Beste, uygulamanızın kullanıcı arayüzünü tanımlar ve composable'ların çalıştırılmasıyla oluşturulur. Kompozisyon, kullanıcı arayüzünüzü tanımlayan composable'lardan oluşan bir ağaç yapısıdır.

Beste'nin yanında, semantik ağacı adı verilen paralel bir ağaç bulunur. Bu ağaçta, kullanıcı arayüzünüz Erişilebilirlik hizmetleri ve Test çerçevesi için anlaşılabilecek alternatif bir şekilde açıklanmaktadır. 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şim kurmak ve hakkında iddialarda bulunmak için ağacı kullanır. Anlambilim ağacı, composable'larınızı çizme işlemi hakkında bilgi içermez ancak composable'larınızın anlamsal anlamları hakkında bilgi içerir.

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

Uygulamanız, Compose temelindeki ve malzeme kitaplığındaki composable'lar ve değiştiricilerden oluşuyorsa Anlambilim ağacı sizin için otomatik olarak doldurulur ve oluşturulur. Ancak özel düşük seviye composable eklerken bunların anlamlarını manuel olarak sağlamanız gerekir. Ayrıca ağacınızın ekrandaki öğelerin anlamını doğru veya tam olarak yansıtmadığı durumlar da olabilir. Bu durumda ağacı uyarlayabilirsiniz.

Örneğin, şu özel takvim composable:

Seçilebilir gün öğelerine sahip özel bir takvim
Şekil 2. Seçilebilir gün öğelerine sahip özel bir takvim.

Bu örnekte, tüm takvim Layout composable kullanılarak ve doğrudan Canvas öğesine işaretlenerek tek bir düşük seviyeli composable olarak uygulanmıştır. Başka bir işlem yapmazsanız erişilebilirlik hizmetleri, composable'ın içeriği ve kullanıcının takvim içindeki seçimi hakkında yeterli bilgi almaz. Örneğin, bir kullanıcı 17 sayısını içeren günü tıklarsa erişilebilirlik çerçevesi yalnızca tüm takvim denetimi için açıklama bilgilerini alır. Bu durumda, TalkBack erişilebilirlik hizmeti "Takvim"i veya daha da iyisi "Nisan Takvimi"ni duyurur ve kullanıcı hangi günün seçilmiş olduğunu merak eder. Bu composable'ı daha erişilebilir hale getirmek için anlamsal bilgileri manuel olarak eklemeniz gerekecektir.

Anlamsal özellikler

Kullanıcı arayüzü ağacındaki bazı anlamsal anlamlara sahip olan tüm düğümlerin Anlambilim ağacında paralel bir düğümü vardır. Anlambilim ağacındaki düğüm, karşılık gelen composable'ın anlamını ileten özellikleri içerir. Örneğin, Textcomposable, text anlamsal özelliğini içerir çünkü bu composable'ın anlamı budur. Icon, metinde Icon öğesinin anlamını ileten bir contentDescription özelliği (geliştirici tarafından ayarlanmışsa) içerir. Compose temel kitaplığı üzerine oluşturulan kompozisyonlar ve değiştiriciler ilgili özellikleri sizin için zaten ayarlamıştır. İsterseniz semantics ve clearAndSetSemantics değiştiricileriyle özellikleri kendiniz ayarlayabilir veya geçersiz kılabilirsiniz. Örneğin, bir düğüme özel erişilebilirlik işlemleri ekleyin, geçiş yapılabilir öğeler için alternatif bir durum açıklaması sağlayın veya belirli bir textcomposable'ın başlık olarak dikkate alınması gerektiğini belirtin.

Semantik ağacını görselleştirmek için Düzen Denetleyici Aracı'nı veya testlerde printToLog() yöntemini kullanın. Logcat'in içindeki mevcut Anlambilim ağacını yazdırır.

class MyComposeTest {

    @get:Rule
    val composeTestRule = createComposeRule()

    @Test
    fun MyTest() {
        // Start the app
        composeTestRule.setContent {
            MyTheme {
                Text("Hello world!")
            }
        }
        // Log the full semantics tree
        composeTestRule.onRoot().printToLog("MY TAG")
    }
}

Bu testin sonucu şu şekilde olur:

    Printing with useUnmergedTree = 'false'
    Node #1 at (l=0.0, t=63.0, r=221.0, b=120.0)px
     |-Node #2 at (l=0.0, t=63.0, r=221.0, b=120.0)px
       Text = '[Hello world!]'
       Actions = [GetTextLayoutResult]

Anlamsal özelliklerin, composable'ın anlamını nasıl ilettiğini düşünün. Switch kullanmayı düşünün. Kullanıcıya şöyle görünür:

Şekil 3. "Açık" ve "Kapalı" durumdaki bir anahtar.

Bu öğenin anlamını açıklamak için şunu söyleyebilirsiniz: "Bu, 'Açık' durumundaki geçiş yapılabilir bir öğe olan bir Anahtardır. Etkileşimde bulunmak için bu düğmeyi tıklayabilirsiniz."

Anlamsal özellikler tam olarak bu amaçla kullanılır. Bu Switch öğesinin anlamsal düğümü, Düzen İnceleyici ile görselleştirildiği gibi aşağıdaki özellikleri içerir:

Bir Switch composable'ın Anlambilim özelliklerini gösteren Layout Inspector
Şekil 4. Bir Switch composable'ın Anlambilim özelliklerini gösteren Layout Inspector.

Role, öğenin türünü gösterir. StateDescription, "Açık" durumuna nasıl referans verilmesi gerektiğ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 (örneğin, "Etkin") hale getirilebilir. ToggleableState, Switch'in mevcut durumudur. OnClick özelliği, bu öğeyle etkileşim kurmak için kullanılan yöntemi kullanır. Anlamsal özelliklerin tam listesi için SemanticsProperties nesnesine bakın. Yapılabilecek Erişilebilirlik İşlemlerinin tam listesi için SemanticsActions nesnesine göz atın.

Uygulamanızdaki her composable'ın anlamsal özelliklerini takip ederek birçok güçlü olasılığın önünü açarsınız. Birkaç örnek:

  • TalkBack, ekranda gösterilenleri sesli okumak için bu özellikleri kullanır ve kullanıcının ekranla sorunsuz bir şekilde etkileşimde bulunmasına olanak tanır. Switch composable için TalkBack, "Açık; Switch; geçiş yapmak için iki kez dokunun" diyebilir. Kullanıcı, ekranına iki kez dokunarak Anahtar'ı kapatabilir.
  • Test çerçevesi, düğümleri bulmak, onlarla etkileşimde bulunmak ve iddialarda bulunmak için özellikleri kullanır. Switch için örnek bir test şu şekilde olabilir:
    val mySwitch = SemanticsMatcher.expectValue(
        SemanticsProperties.Role, Role.Switch
    )
    composeTestRule.onNode(mySwitch)
        .performClick()
        .assertIsOff()

Birleştirilmiş ve birleştirilmemiş Semantik ağacı

Daha önce belirtildiği gibi, kullanıcı arayüzü ağacındaki her composable, sıfır veya daha fazla semantik özelliğine sahip olabilir. Anlamsal özellik ayarlanmamış composable, Semantik ağacına dahil edilmez. Bu şekilde, Anlamsal ağacı yalnızca gerçekten anlamsal anlam içeren düğümleri içerir. Bununla birlikte, bazen ekranda gösterilenin doğru anlamını iletmek için belirli düğümlerin alt ağaçlarını birleştirmek ve bunları tek bir düğüm olarak ele almak da yararlıdır. Bu şekilde, her alt düğümle ayrı ayrı uğraşmak yerine bir düğüm kümesini bir bütün olarak değerlendirebilirsiniz. Genel bir kural olarak, bu ağaçtaki her düğüm Erişilebilirlik hizmetleri kullanılırken odaklanılabilir bir öğeyi temsil eder.

Böyle bir composable'a ö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")
}

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

Birleştirilmiş tek yapraklı anlamsal temsil
Şekil 5. Tek yapraklı anlamsal temsil birleştirildi.

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

Temel ve Materyal Oluşturma kitaplıklarındaki çeşitli değiştiriciler ve composable'lar bu özelliğe sahiptir. Örneğin, clickable ve toggleable değiştiricileri kendi alt öğelerini otomatik olarak birleştirir. Ayrıca ListItem composable, alt öğelerini de birleştirir.

Ağaçları inceleyin

Anlamsal ağaç aslında iki farklı ağaçtır. mergeDescendants, true olarak ayarlandığında alt düğümleri birleştiren birleştirilmiş bir Semantik ağacı vardır. Ayrıca, birleştirme işlemini uygulamayan ancak her düğümün bozulmadan kalmasını sağlayan birleştirilmemiş bir Semantik ağacı vardır. Erişilebilirlik hizmetleri birleştirilmiş ağacı kullanır ve mergeDescendants özelliğini dikkate alarak kendi birleştirme algoritmalarını uygular. Test çerçevesi varsayılan olarak birleştirilmiş ağacı kullanır.

Her iki ağacı da printToLog() yöntemiyle inceleyebilirsiniz. Varsayılan olarak ve önceki örneklerde olduğu gibi, birleştirilen ağaç günlüğe kaydedilir. Bunun yerine, ayrılan 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 İnceleyici, görünüm filtresinde tercih edilen ağacı seçerek hem birleştirilmiş hem de ayrılmamış Semantik ağacını görüntülemenizi sağlar:

Hem birleştirilmiş hem de ayrılmış Anlamsal ağacın görüntülenmesine olanak tanıyan Düzen İnceleyici görünüm seçenekleri
Şekil 6. Hem birleştirilmiş hem de ayrılmamış Anlamsal ağacın görüntülenmesine olanak tanıyan Düzen İnceleyici görünüm seçenekleri.

Düzen İnceleyici, ağacınızdaki her bir düğüm için özellikler panelinde o düğümde ayarlanmış olan Birleştirilmiş Anlamları ve Anlamları gösterir.

Anlamsal özellikler birleştirildi ve ayarlandı
Şekil 7. Anlamsal özellikler birleştirildi ve ayarlandı.

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

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

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

Birleştirme davranışı

Bir composable, alt öğelerinin birleştirilmesi gerektiğini belirttiğinde bu birleştirme işlemi tam olarak nasıl gerçekleşir?

Her anlambilim mülkünün tanımlanmış bir birleştirme stratejisi vardır. Örneğin, ContentDescription özelliği tüm alt ContentDescription değerlerini bir listeye ekler. Bir anlamsal özelliğin SemanticsProperties.kt içindeki mergePolicy uygulamasını kontrol ederek birleştirme stratejisini kontrol edin. Özellikler üst veya alt değeri alabilir, değerleri bir liste veya dizede birleştirebilir, birleştirmeye hiçbir şekilde izin vermeyerek bunun yerine istisna uygulayabilir ya da başka bir özel birleştirme stratejisini kullanabilir.

Önemli bir not, kendisinin mergeDescendants = true olarak ayarladığı alt öğelerin birleştirmeye dahil edilmemesidir. Bir örneği inceleyin:

Resim, metin ve yer işareti simgesi içeren liste öğesi
Şekil 8. Resim, metin ve yer işareti simgesi içeren liste öğesi.

Burada, tıklanabilir bir liste öğesi bulunmaktadır. Kullanıcı satıra bastığında uygulama, kullanıcının makaleyi okuyabileceği makale ayrıntıları sayfasına gider. Liste öğesinin içinde makaleye yer işareti koymak için bir düğme bulunur. Bu düğme, iç içe tıklanabilir bir öğe oluşturur. Böylece düğme birleştirilmiş ağaçta ayrı olarak görünür. Bu satırdaki içeriğin geri kalanı birleştirilir:

Birleştirilmiş ağaç, Satır düğümünün içindeki bir listede birden çok metin içeriyor. Ayrılmış ağaç, composable'ın (Metin) her biri için ayrı düğümler içerir.
Şekil 9. Birleştirilmiş ağaç, Satır düğümünün içindeki bir listede birden çok metin içeriyor. Ayrılmış ağaç, her Metin composable için ayrı düğümler içerir.

Anlambilim ağacını uyarlayın

Daha önce belirtildiği gibi, belirli anlamsal özellikleri 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 geçerlidir. Doğru özellikleri ve birleştirme davranışını ayarlamazsanız uygulamanıza erişilemeyebilir ve testler beklediğinizden farklı çalışabilir. Semantik ağacını uyarlamanız gereken bazı yaygın kullanım durumları hakkında daha fazla bilgi edinmek için erişilebilirlik belgelerini okuyun. Test hakkında daha fazla bilgi edinmek istiyorsanız test kılavuzunu inceleyin.

Ek kaynaklar