Ders 16 / 17
Erişilebilirlik
Anlamsal ağaçta çocukların etiketlerinin birleştiren ataya yukarı gitmesinin, doğrudan ve dolaylı çocuklar için aynı yönün korunmasının ve birleşen etiketin ekran okuyucuya dış bir hareketle ulaşmasının ölçümü.
Yayın Güncelleme
Bu derste
- Anlamsal ağaçta çocukların etiketlerinin ataya yukarı gittiğini ölçer
- Doğrudan çocuk ile torunun etiketinin aynı yönde birleştiğini gösterir
- Birleşen etiketin ekran okuyucuya ağaç dışından ulaştığını ayırt eder
- Süs niteliğindeki ögenin etiket taşımamasının nedenini açıklar
İçindekiler
Ekranı göremeyen bir kullanıcı arayüzü ekran okuyucuyla kullanır. Okuyucu piksellere değil, platformun arayüz ağacından türettiği anlamsal ağaca bakar. Bu ağaç, her ögenin ne olduğunu, ne dediğini ve ne yapabildiğini taşır. Bir satırda simge, ürün adı ve fiyat varsa, ekran okuyucunun üç ayrı duraktan geçmesi yerine tek bir cümle okuması istenir: ürün adı, fiyat.
Bu birleştirme ağaç üzerinde yönü olan bir harekettir. Çocukların etiketleri, birleştiren atanın etiketine katılır. Bu dersin ölçüsü o hareketin yönüdür.
// Direction.kt — bir verinin arayuz agacinda hangi yone gittigini siniflandirir
class Tree(private val parentOf: Map<String, String>) {
fun contains(node: String): Boolean = node in parentOf.keys || node in parentOf.values
fun parent(node: String): String? = parentOf[node]
fun ancestors(node: String): List<String> {
val chain = mutableListOf<String>()
var current = parentOf[node]
while (current != null) {
chain.add(current)
current = parentOf[current]
}
return chain
}
}
class Move(val label: String, val from: String, val to: String, tree: Tree) {
val direction: String = when {
!tree.contains(from) || !tree.contains(to) -> "dis"
to in tree.ancestors(from) -> "yukari"
tree.parent(to) == from -> "asagi"
from in tree.ancestors(to) -> "derin"
else -> error("akrabasiz: $from ve $to")
}
fun describe() {
println("$label: kimden=$from | kime=$to -> $direction")
}
}
fun countDirections(moves: List<Move>) {
for (name in listOf("asagi", "yukari", "derin", "dis")) {
println("$name: ${moves.count { it.direction == name }}")
}
}
Anlamsal Ağaç ve Birleştirme
Her arayüz ögesi anlamsal ağaçta bir düğümdür. Düğüm; bir içerik açıklaması, bir rol ve eylemler taşıyabilir. Varsayılan olarak her düğüm ayrı bir durak olarak sunulur. Bir ata düğüm alt ağacını birleştirmek istediğinde, çocuklarının açıklamaları ona katılır ve ekran okuyucu ata düğümü tek durak olarak okur.
// Platform kodu: satirin anlamsal olarak birlestirilmesi
@Composable
fun CartRow(name: String, price: String) {
Row(Modifier.semantics(mergeDescendants = true) {}) {
Icon(Icons.Default.ShoppingCart, contentDescription = null)
Text(name)
Text(price)
}
}
mergeDescendants = true, bu satırın altındaki düğümlerin açıklamalarını satıra katar. Simgeye contentDescription = null verilmiştir: süs niteliğindeki bir ögenin okunması bir şey eklemez. Ekran okuyucu satırı “ürün adı, fiyat” olarak tek seferde okur. Birleştirmeyi bırakıp tüm alt ağacın yerine kendi açıklamasını vermek için clearAndSetSemantics kullanılır. Hazır arayüz bileşenleri, eylem alabildiklerinde dokunma hedefini en az bir boyuta tamamlar; kendi yazılan dokunulabilir ögede bu boyutu geliştirici verir. Bu boyut, düzen dersindeki boyut ve boşluk ilişkisi gibi platformun kuralıdır ve bu derste ölçülmez.
Model, platformun bu kuralını kurar; model platformun kendisi değildir. Yardımcı dosya birleştiren satırın ağacını kurar, hangi düğümlerin etiket taşıdığını ve birleşen etiketin metnini hesaplar. Ölçümlerin uçlarını da iki işlev verir: screenReader ekran okuyucunun adını döndürür, mergeOwner satırın ebeveynini ağaçtan okur. Bu derste hareketin bir ucu ağaçtan bulunur (mergeOwner); öteki uç, modelin adlandırdığı ve ağaçta olmayan bir kaynaktır (screenReader sabit bir ad döndürür).
// Semantics.kt — anlamsal agac ve birlesen etiket (modelin hesabi)
fun semanticsTree(): Tree = Tree(
mapOf(
"Screen" to "App",
"Row" to "Screen",
"Icon" to "Row",
"Title" to "Row",
"Wrap" to "Row",
"Price" to "Wrap",
)
)
fun screenReader(): String = "ScreenReader"
fun mergeOwner(tree: Tree): String = tree.parent("Row") ?: error("satir kokte")
fun labelHolders(labels: Map<String, String>): List<String> = labels.keys.sorted()
fun mergedDescription(labels: Map<String, String>): String =
labelHolders(labels).joinToString(", ") { labels.getValue(it) }
Etiketler Ataya Çıkar
İlk ölçümde iki düğüm etiket taşır: ürün adı doğrudan satırın çocuğudur, fiyat ise araya giren bir sarmalayıcının altındadır, yani satırın torunudur. Simge süs olduğu için etiketsizdir.
// Main.kt — etiket tasiyan dugumlerin birlesen atasi
fun main() {
val tree = semanticsTree()
val labels = mapOf("Title" to "Kalem", "Price" to "Bedel")
println("birlesen etiket: ${mergedDescription(labels)}")
val moves = labelHolders(labels).map { Move("etiket-$it", it, "Row", tree) }
for (move in moves) {
move.describe()
}
countDirections(moves)
}
birlesen etiket: Bedel, Kalem etiket-Price: kimden=Price | kime=Row -> yukari etiket-Title: kimden=Title | kime=Row -> yukari asagi: 0 yukari: 2 derin: 0 dis: 0
Her iki hareket de yukarı. Doğrudan çocuğun etiketi bir kat, torunun etiketi iki kat yukarı çıktı. Derin yönü yalnız aşağıya doğrudur; ataya çıkışta çocuk ya da torun fark etmez, hareket yukarıdır. Araya giren sarmalayıcı etiketi ne taşır ne değiştirir.
AD1. Model etiketleri tek birer sözcük olarak alır ve onları ad sırasıyla birleştirir. Platformun etiketleri okuma sırası, rol ve eylem bilgilerini katması ve birleşme koşulları (örneğin tıklanabilir bir düğümün kendi sınırını koruması) modelde yoktur.
Etiket Ekran Okuyucuya Gider
Birleşen etiket satırda kalmaz; ekran okuyucuya iletilir. Ekran okuyucu arayüz ağacının bir düğümü değildir. Platformun erişilebilirlik hizmetidir ve ağacı dışarıdan okur.
// Main.kt — birlesen etiketin ekran okuyucuya gidisi
fun main() {
val tree = semanticsTree()
val labels = mapOf("Title" to "Kalem", "Price" to "Bedel")
println("okunan: ${mergedDescription(labels)}")
Move("okuma", "Row", screenReader(), tree).describe()
}
okunan: Bedel, Kalem okuma: kimden=Row | kime=ScreenReader -> dis
Dış. Ekran okuyucu ağaçta olmadığı için hareketin bir ucu ağaç dışındadır. Satır, etiketi okuyucuya vermez; okuyucu etiketi satırdan alır. İki ayrı yönün zinciri vardır: etiketler ağaçta yukarı çıkar, ağacın tepesinde bekleyen birleşik etiket dışarıdan okunur.
AD2. Model okuyucuyu ağaçta bulunmayan bir ad olarak kurar. Okuyucunun odak sırası, kullanıcının hangi düğüme dokunduğu ve etiketin ne zaman okunduğu modelde yok.
Sınırlayıcı Ölçüm
Dersin yönü, etiketlerin ataya çıkışından gelir. Etiketin okuyucuya ulaşması dış, birleştirmenin ata tarafından açılması ise aşağıdır: ekran satıra birleştirme bayrağını verir. Aşağıdaki ölçüm dördünü bir arada gösterir.
// Main.kt — erisilebilirlik hareketleri
fun main() {
val tree = semanticsTree()
val labels = mapOf("Title" to "Kalem", "Price" to "Bedel")
val moves = labelHolders(labels).map { Move("etiket-$it", it, "Row", tree) } + listOf(
Move("birlestirme-bayragi", mergeOwner(tree), "Row", tree),
Move("okuma", "Row", screenReader(), tree),
)
for (move in moves) {
move.describe()
}
countDirections(moves)
}
etiket-Price: kimden=Price | kime=Row -> yukari etiket-Title: kimden=Title | kime=Row -> yukari birlestirme-bayragi: kimden=Screen | kime=Row -> asagi okuma: kimden=Row | kime=ScreenReader -> dis asagi: 1 yukari: 2 derin: 0 dis: 1
İki yukarı, bir aşağı, bir dış. Birleştirme bayrağı ekrandan satıra iner; etiketler satıra çıkar; birleşen etiket okuyucuya dışarıdan ulaşır. Yön ayrımı işlev ayrımıyla örtüşür: karar yukarıdan aşağı verilir, bilgi aşağıdan yukarı toplanır, okuma dışarıda gerçekleşir. Dersin yönü: yukarı.
AD3. Model birleştirmeyi tek bir satırda kurar. Birleştiren bir atanın başka bir birleştiren atanın içinde bulunması ve iç içe birleştirmenin etiketleri nasıl katacağı bu derste ölçülmedi.
Özet
- Bu dersin yönü: yukarı. Etiketler çocuklardan ve torunlardan birleştiren ataya çıkar.
- Ekran okuyucu piksellere değil, arayüz ağacından türetilen anlamsal ağaca bakar.
- Birleştiren ata, çocuklarının ve torunlarının etiketlerini toplar; etiketler ataya yukarı gider.
- Doğrudan çocuğun da torunun da etiketi aynı yönde, yukarı çıkar.
- Birleşen etiketin ekran okuyucuya gitmesi ağaç dışı, dış bir harekettir.
Sonraki Adım
Bu kursun ağacı bildirimsel arayüzün ağacıdır. Birçok uygulama ise henüz klasik görünüm sistemiyle yazılmış ekranlar taşır. Sonraki ders, iki dünyayı bir arada kullanmayı ve veri ağacın sınırını geçtiğinde yönün nasıl adlandırıldığını ölçer.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.