Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-140463

[A11y] QML ListView elements unordered on reverse traversal

XMLWordPrintable

    • Android, iOS/tvOS/watchOS, Windows

      When traversing QML ListView items with a screen reader on Windows, Android, and iOS, the elements can become unordered (macOS does not show this behavior). This occurs when the ListView has to recreate items that appear earlier in the list (e.g., when scrolling up). The accessibility traversal order no longer matches the model's order.

      This leads to two issues for screen reader users:
      1. The screen reader might announce an element as the "end of the list" even when more items are available.
      2. The screen reader focus "jumps" between elements that should be sequential.

      This behavior stems from the way elements are created and appended to the list of children in ListView. In QQuickItemViewPrivate::initItem the new list element gets created and, through QQuickItem::setParentItem(QQuickItem *parentItem), QQuickItemPrivate::addChild(QQuickItem *child) gets called. addChild always appends to childItems.
      This explains why this behavior only manifests when moving backward(up the list), as moving forward appends the elements in the correct order.

      I have tried a crude way to prepend child items when the modelIndex of the new item is lower than the modelIndex of the first item and this resolved the issue in my tests.
      However, this fix is not robust when creating items asynchronously and there may be more places in ListView where a prepending is necessary.

      Minimal Reproducible Example:

      import QtQuick
      import QtQuick.Controls
      
      ApplicationWindow {
          visible: true
      
          ListView {
              id: listview
              anchors.fill: parent
      
              model: 20
              delegate: Text {
                  Accessible.role: Accessible.StaticText
                  Accessible.name: text
                  height: 200
                  onActiveFocusChanged: if (activeFocus) {
                       listview.positionViewAtIndex(index, ListView.Center);
                       listview.currentIndex = index
                   }
                  text: "Element: " + index
              }
          }
      }
      

        For Gerrit Dashboard: QTBUG-140463
        # Subject Branch Project Status CR V

            qt.team.quick.subscriptions Qt Quick and Widgets Team
            jtrillma Jens Trillmann
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:

                There is 1 open Gerrit change