Geçiş sırasını değiştirme

Geçiş sırası, erişilebilirlik hizmetlerinin kullanıcı arayüzü öğeleri arasında gezinme sırasıdır. Oluşturma uygulamasında öğeler, genellikle soldan sağa ve ardından yukarıdan aşağıya doğru olan beklenen okuma sırasına göre düzenlenir. Ancak, doğru okuma sırasını belirlemek için Oluştur'un ek ipuçlarına ihtiyaç duyabileceği bazı durumlar vardır.

isTraversalGroup ve traversalIndex, Compose'un varsayılan sıralama algoritmasının yeterli olmadığı senaryolarda erişilebilirlik hizmetlerinin tarama sırasını etkilemenize olanak tanıyan anlamsal özelliklerdir. isTraversalGroup, özelleştirme gerektiren anlamsal açıdan önemli grupları tanımlarken traversalIndex, bu gruplardaki öğelerin sırasını ayarlar. Bir gruptaki tüm öğelerin birlikte seçilmesi gerektiğini belirtmek için isTraversalGroup'ü tek başına veya daha fazla özelleştirme için traversalIndex ile birlikte kullanabilirsiniz.

Ekran okuyucu gezinme sırasını kontrol etmek için uygulamanızda isTraversalGroup ve traversalIndex tuşlarını kullanın.

Öğeleri gruplandırma

isTraversalGroup, bir semantik düğümünün tarama grubu olup olmadığını tanımlayan bir Boole özelliğidir. Bu tür düğümlerin işlevi, düğümün alt öğelerini düzenlerken sınır veya kenar görevi görmektir.

Bir düğümde isTraversalGroup = true ayarının yapılması, diğer öğelere geçmeden önce söz konusu düğümün tüm alt öğelerinin ziyaret edileceği anlamına gelir. isTraversalGroup öğesini sütun, satır veya kutu gibi ekran okuyucu tarafından odaklanamayan düğümlerde ayarlayabilirsiniz.

Aşağıdaki örnekte isTraversalGroup kullanılmaktadır. Dört metin öğesi döndürür. Soldaki iki öğe bir CardBox öğesine, sağdaki iki öğe ise başka bir CardBox öğesine aittir:

// CardBox() function takes in top and bottom sample text.
@Composable
fun CardBox(
    topSampleText: String,
    bottomSampleText: String,
    modifier: Modifier = Modifier
) {
    Box(modifier) {
        Column {
            Text(topSampleText)
            Text(bottomSampleText)
        }
    }
}

@Composable
fun TraversalGroupDemo() {
    val topSampleText1 = "This sentence is in "
    val bottomSampleText1 = "the left column."
    val topSampleText2 = "This sentence is "
    val bottomSampleText2 = "on the right."
    Row {
        CardBox(
            topSampleText1,
            bottomSampleText1
        )
        CardBox(
            topSampleText2,
            bottomSampleText2
        )
    }
}

Kod, aşağıdakine benzer bir çıkış oluşturur:

Sol sütunda "Bu cümle soldaki sütundadır", sağ sütunda ise "Bu cümle sağ taraftadır" yazan iki sütunlu metin düzeni.
Şekil 1. İki cümlenin yer aldığı bir düzen (biri sol sütunda, diğeri sağ sütunda).

Hiçbir anlam bilgisi ayarlanmadığı için ekran okuyucunun varsayılan davranışı, öğeleri soldan sağa ve yukarıdan aşağıya doğru taramaktır. Bu varsayılan ayar nedeniyle TalkBack, cümle parçalarını yanlış sırada okur:

"Bu cümle" → "Bu cümle" → "sol sütundadır." → "sağ tarafta."

Parçaları doğru şekilde sıralamak için orijinal snippet'i isTraversalGroup değerini true olarak ayarlayacak şekilde değiştirin:

@Composable
fun TraversalGroupDemo2() {
    val topSampleText1 = "This sentence is in "
    val bottomSampleText1 = "the left column."
    val topSampleText2 = "This sentence is"
    val bottomSampleText2 = "on the right."
    Row {
        CardBox(
//      1,
            topSampleText1,
            bottomSampleText1,
            Modifier.semantics { isTraversalGroup = true }
        )
        CardBox(
//      2,
            topSampleText2,
            bottomSampleText2,
            Modifier.semantics { isTraversalGroup = true }
        )
    }
}

isTraversalGroup her CardBox için özel olarak ayarlandığından, öğeleri sıralarken CardBox sınırları geçerli olur. Bu durumda, önce sol CardBox, ardından sağ CardBox okunur.

Artık TalkBack, cümle parçalarını doğru sırada okuyor:

"Bu cümle" → "sol sütunda." → "Bu cümle" → "sağda."

Geçiş sırasını özelleştirme

traversalIndex, TalkBack'in tarama sırasını özelleştirmenize olanak tanıyan bir kayan nokta mülkü. TalkBack'in düzgün çalışması için öğeleri gruplandırmak yeterli değilse ekran okuyucunun sıralamasını daha da özelleştirmek için traversalIndex öğesini isTraversalGroup ile birlikte kullanın.

traversalIndex mülkü aşağıdaki özelliklere sahiptir:

  • traversalIndex değerleri daha düşük olan öğelere öncelik verilir.
  • Olumlu veya olumsuz olabilir.
  • Varsayılan değer: 0f.
  • Geçiş dizininin geçiş davranışını etkilemesi için metin veya düğmeler gibi ekran öğeleri gibi erişilebilirlik hizmetleri tarafından seçilebilir ve odaklanılabilir bir bileşende ayarlanması gerekir.
    • Örneğin, bir sütunda yalnızca traversalIndex ayarlanırsa (Column) sütunda isTraversalGroup de ayarlanmazsa bu ayar hiçbir etki göstermez.

Aşağıdaki örnekte, traversalIndex ve isTraversalGroup'yi birlikte nasıl kullanabileceğiniz gösterilmektedir.

Kadran, standart traversal sıralamasının işe yaramadığı yaygın bir senaryodur. Bu bölümdeki örnekte, kullanıcının bir kadran üzerindeki sayıları gezerek saat ve dakika aralıklarını seçebileceği bir zaman seçici gösterilmektedir.

Üstünde saat seçici bulunan bir kadran.
Şekil 2. Bir kadran resmi.

Aşağıdaki basitleştirilmiş snippet'te, 12'den başlayıp daire etrafında saat yönünde hareket eden 12 sayının çizildiği bir CircularLayout vardır:

@Composable
fun ClockFaceDemo() {
    CircularLayout {
        repeat(12) { hour ->
            ClockText(hour)
        }
    }
}

@Composable
private fun ClockText(value: Int) {
    Box(modifier = Modifier) {
        Text((if (value == 0) 12 else value).toString())
    }
}

Saat kadranı varsayılan soldan sağa ve yukarıdan aşağıya sıralamayla mantıksal olarak okunmadığından TalkBack sayıları sırayla okumaz. Bu sorunu düzeltmek için aşağıdaki snippet'te gösterildiği gibi artan sayaç değerini kullanın:

@Composable
fun ClockFaceDemo() {
    CircularLayout(Modifier.semantics { isTraversalGroup = true }) {
        repeat(12) { hour ->
            ClockText(hour)
        }
    }
}

@Composable
private fun ClockText(value: Int) {
    Box(modifier = Modifier.semantics { this.traversalIndex = value.toFloat() }) {
        Text((if (value == 0) 12 else value).toString())
    }
}

Geçiş sıralamasını doğru şekilde ayarlamak için önce CircularLayout'ü bir geçiş grubu yapın ve isTraversalGroup = true'ü ayarlayın. Ardından, her saat metni düzene çizilirken karşılık gelen traversalIndex değerini sayaç değerine ayarlayın.

Sayaç değeri sürekli olarak arttığından, ekrana sayılar eklendikçe her saat değerinin traversalIndex değeri de büyür. 0 olan saat değerinin traversalIndex değeri 0, 1 olan saat değerinin traversalIndex değeri ise 1'dir. Bu şekilde, TalkBack'in bunları okuduğu sıra belirlenir. Artık CircularLayout içindeki sayılar beklenen sırada okunuyor.

Ayarlanan traversalIndexes yalnızca aynı gruplandırmadaki diğer dizinlere göre olduğundan ekran sıralamasının geri kalanı korunmuştur. Diğer bir deyişle, önceki kod snippet'inde gösterilen anlamsal değişiklikler yalnızca isTraversalGroup = true ayarının bulunduğu kadran içindeki sıralamayı değiştirir.

CircularLayout's semantikleri isTraversalGroup = true olarak ayarlanmasa bile traversalIndex değişikliklerinin geçerli olmaya devam ettiğini unutmayın. Ancak bunları bağlayan CircularLayout olmadan, saat kadranının on iki hanesi ekrandaki diğer tüm öğeler ziyaret edildikten sonra son olarak okunur. Bunun nedeni, diğer tüm öğelerin varsayılan traversalIndex değerinin 0f olması ve saat metin öğelerinin diğer tüm 0f öğelerinden sonra okunmasıdır.

API ile ilgili dikkat edilmesi gereken noktalar

Geçiş API'lerini kullanırken aşağıdakileri göz önünde bulundurun:

  • isTraversalGroup = true, gruplandırılmış öğeleri içeren üst öğede ayarlanmalıdır.
  • traversalIndex, anlam bilgisi içeren ve erişilebilirlik hizmetleri tarafından seçilecek bir alt bileşende ayarlanmalıdır.
  • İncelediğiniz tüm öğelerin aynı zIndex düzeyinde olduğundan emin olun. Bu, anlamları ve tarama sırasını da etkiler.
  • Geçiş dizinlerinin hangi bileşenlere uygulandığını etkileyebileceğinden, anlamların gereksiz yere birleştirilmediğinden emin olun.