Я углубился в проблему и обнаружил следующее: accessibilityTraversalBefore
и accessibilityTraversalAfter
флаги в деле вступают в силу, но только для того, для чего они предназначены - они предназначены для приложения Accessibility Service (например, Talkback).Другими словами, если вы удалите атрибут focusable
из корневого макета, вы увидите, что навигация верна.
Но эти флаги не влияют на то, как AccessibilityNode
построен для корня ViewGroup
.Как видно из источников ViewGroup#onInitializeAccessibilityNodeInfoInternal()
, фактическая логика построения текста не учитывает, как дети строят свою навигацию, используя верхние упомянутые флаги.
Чтобы решитьпроблема, я удалил чрезмерные флаги из макета XML как таковой:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="true"
tools:context=".MainActivity">
<TextView
android:id="@+id/before"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:importantForAccessibility="no"
android:text="Before"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/after"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:importantForAccessibility="no"
android:text="After"
app:layout_constraintBottom_toTopOf="@+id/before"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
И внутри действия / фрагмента хоста:
val root = findViewById<ViewGroup>(R.id.root)
ViewCompat.setAccessibilityDelegate(root, object : AccessibilityDelegateCompat() {
override fun onInitializeAccessibilityNodeInfo(
host: View?,
info: AccessibilityNodeInfoCompat?
) {
val stringBuilder = StringBuilder()
root.children.forEach { view ->
val label = if (view is TextView) view.text else ""
stringBuilder.append("$label, ")
}
info?.text = stringBuilder.toString()
super.onInitializeAccessibilityNodeInfo(host, info)
}
})
Это приведет к желаемому результату: Talkback будет "До, После" .
К сожалению, это подверженный ошибкам код, означающий, что если вы реструктурируете иерархию представления таким образом, этот порядок потомков будет заменен, то текст этого узластроительная логика станет нарушенной.Тем не менее, я не смог придумать лучшего решения и не вижу возможности поручить родителям учитывать флаги упорядочения дочерних элементов (на основе источников).