Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Conversation

darrenaustin
Copy link
Contributor

Currently on iOS, when a screen change has occurred (a route change), we pass the most recent route scope's label as the parameter to the UIAccessibilityScreenChangedNotification. VoiceOver then picks a new node to move its a11y focus to. The way it does this is seems pretty random, depending on the structure of the SemanticObjects we present it, and doesn't give us a lot of control. However, the parameter to UIAccessibilityScreenChangedNotification can also be the SemanticObject that we want to have focus after the change.

This PR makes use of this and passes the new route's label node as the focus for the screen change. This fixes a couple of issues: flutter/flutter#46625, and flutter/flutter#44001.

This seems like a good fix to me, but I am not that familiar with how our semantic tree deals with scopes. Can anyone see any issue with using the label node for focus instead of just announcing the label and letting VoiceOver pick the focus for us?

use the route's name node as the focused node.
@dnfield
Copy link
Contributor

dnfield commented Dec 16, 2019

Is there some way we could test this?

@darrenaustin
Copy link
Contributor Author

darrenaustin commented Dec 16, 2019

Is there some way we could test this?

I don't think we have any system in place for automated testing of this on iOS, so I am not sure what we can do here.

I have run this manually against several test apps and the gallery. I didn't see anything that seemed broken to me, but that is certainly not exhaustive. Do we have a better way to evaluate these kinds of changes?

- (id)routeFocusObject {
// Returns the first SemanticObject in this branch that has
// the NamesRoute flag with a non-nil semantic label. Otherwise
// returns nil.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it guaranteed that a node with kNamesRoute is always focusable?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe so. In the isAccessibilityElement method on SemanticsObject it uses:

  return (([self node].flags & ~flutter::kScrollableSemanticsFlags) != 0 &&
          [self node].flags != static_cast<int32_t>(flutter::SemanticsFlags::kIsHidden)) ||
         ![self node].label.empty() || ![self node].value.empty() || ![self node].hint.empty() ||
         ([self node].actions & ~flutter::kScrollableSemanticsActions) != 0;

So any node with a label should be a11y focusable.

@goderbauer
Copy link
Member

@vick08 pointed out in material-components/material-components-flutter-gallery#517 that the focus should always go to the first element on the screen. Maybe he can help with figuring if this is ok behavior.

@vick08
Copy link

vick08 commented Jan 6, 2020

Sorry. What I said in the mentioned issue is that accessibility services should manage the focus according to their specific needs. We should simply provide the necessary signals.
In this specific instance, we should be posting the notification that will place the focus on the first item on the screen. However, the developer should be able to override this parameter if they want to send the focus elsewhere.
Hope this helps!

@dnfield
Copy link
Contributor

dnfield commented Jul 16, 2020

Closing in favor of #19826

@dnfield dnfield closed this Jul 16, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants