Hi all, I'm investigating an accessibility issue ...
# compose-ios
h
Hi all, I'm investigating an accessibility issue with compose iOS. When turning on
full keyboard access
(support.apple.com/en-gb/…/ios), its hard / nigh impossible to scroll through the contents of a lazy column. According to my testing it seems as if a new element is focussed through the keyboard compose scrolls a little bit, but not enough to show the next element, causing the next tab press to circle back to the top. Its also not consistent, sometimes we get lucky and compose scrolls ahead far enough so the next tab press can focus on the next item. And when you have the UI "just right" it works better than other times, See attached in the thread some videos showing the problem. I think this needs to be fixed within compose itself, there even are already some reports for (youtrack.jetbrains.com/issue/CMP-9859/iOS-Focus-jumps-to-top-when-navigating-LazyColumn-with-keyboard and youtrack.jetbrains.com/issue/CMP-10130/iOS-Accessibility-Keyboard-wont-navigate-to-offscreen-elements), but in case I need a fix sooner, I've written a solution for the short term as well. I wanted to share this with you and raise awareness of the issue, and maybe the thoughts of some others (maybe others have resolved this issue way better than I have attempted right now?) See more in the thread. Thanks
👍 2
Initially I wanted to fix it using focus listeners, but when using keyboard navigation, its not conveyed as a focus event on the element. So instead I used a
BringIntoViewRequester
, and observed UIKit focus updates (through UIFocusDidUpdateNotification) to know what element is focussed on by the keyboard. And to know what compose component was associated with that I abused the
testTag
, which corresponds to the
accessibilityIdentifier
, so I could call
bringIntoView
for the focussed element. Then the
bringIntoView
was also buggy, if the size didnt have enough bottom padding it wouldnt do anything at all, so i opted to request it always in the center of the screen, which works as long as you dont press tab too quickly in succession. I've put this code in a singular modifier called
iosKeyboardFocusable()
See snippet:
👀 1
ios-keyboard-navigation-fix.kt
For my reproducer I got a simple lazycolumn with 20 cards. To understand how it works ive tried several setups of the sample: • setup 1: A scaffold with no arguments, consuming the innerPadding as padding in the child LazyColumn, and using a small card. • setup 2: A scaffold with empty window insets, not using the inner padding and windowInsetsPadding set to statusBars, using small cards (works the best of the broken flows, but breaks when cards are bigger, see setup 3) • setup 3: The same as setup 2, but with big cards (included a vertical spacer of 40dp between title and text). See snippet for this reproducer
reproducer.kt
My fix works for all of the 3 setups, and for good measure I also took a video of how it looks normally without the fix. See attached the 6 videos. For the broken flows, it seems that bottom arrow works better than tab, because when tab circles back to the top, it scrolls up again, whereas bottom arrow circles back to the top it doesnt scroll back up, so there is a higher chance that the next time we get at the bottom that it is able to scroll just enough to show the next item. For the fixed flow, apparantly shift-tab up navigation works worse than arrow key up navigation, its visible in the 2nd setup with the fix applied. To know what every flow is, you can expand the videos and look at the name (should be somehting like setup-number-with/without-fix.mov
j
For the fixed flows, am I seeing correctly that continuing down at the bottom jumps up to only the first visible item, instead of the actual first item?
h
If you mean that if you go from the 20th item, press tab again, instead of ending up at item 1, we end up at item ~12 or ~15, which happens to be at the top of the screen, yes thats correct. Not sure if this is intended by apple, havent investigated that yet. At least keyboard users can navigate up using up arrow / shift tab
👍 1