Modifier l'ordre des éléments lus avec VoiceOver

J'ai un tas de buttons sur l'écran qui sont positionnés intuitivement visuellement mais ne sont pas lus dans un ordre intuitif par VoiceOver. C'est parce que certains buttons comme Up et Dwon sont placés au-dessus et en dessous l'un de l'autre. Cependant, la voix off commence à lire de gauche à droite, de haut en bas, semble-t-il.

Cela se traduit par la lecture de la voix off à la droite de "Up" après "Up", au lieu de lire "Down" immédiatement après.

Comment puis-je forcer la voix off à lire le button que je veux lire? Je devrais mentionner que j'utilise la fonction glisser-à-cycle-à travers les éléments sur la voix off.

Tous mes buttons sont des versions sous-classées de UIView et UIButton. Voici un exemple d'initiateur de button que j'utilise. Ignorez le nombre de pixels – Je sais que c'est une mauvaise forme mais je suis dans une impasse en ce moment:

UIButton* createSpecialButton(CGRect frame, NSSsortingng* imageName, NSSsortingng* activeImageName, id target, SEL obClickHandler) { UIButton* b = [UIButton buttonWithType:UIButtonTypeCustom]; [b setImage:[GlobalHelper nonCachedImage:imageName ofType:@"png"] forState:UIControlStateNormal]; [b setImage:[GlobalHelper nonCachedImage:activeImageName ofType:@"png"] forState:UIControlStateHighlighted]; [b addTarget:target action:obClickHandler forControlEvents:UIControlEventTouchUpInside]; b.frame= frame; return b; } - (UIButton *) createSendButton { CGFloat yMarker = 295; UIButton* b = createSpecialButton(CGRectMake(160, yMarker, 70, 45), @"Share_Btn", @"Share_Selected_Btn", self, @selector(sendAction)); b.accessibilityHint = @"Send it!"; b.accessibilityLabel = @"Stuff for voiceover to be added"; [self.view addSubview:b]; return b; } 

La réponse la plus simple consiste à créer une sous-class UIView qui contient vos buttons et qui répond différemment aux appels d'accessibilité du système. Ces appels importants sont:

 -(NSInteger)accessibilityElementCount -(id)accessibilityElementAtIndex: -(NSInteger)indexOfAccessibilityElement: 

J'ai vu quelques-unes de ces questions, et j'ai déjà répondu à une de ces questions, mais je n'ai pas vu d'exemple générique sur la façon de réorganiser le focus VoiceOver. Voici donc un exemple de création d'une sous-class UIView qui expose ses sous-vues accessibles à VoiceOver par tag.

AccessibilitySubviewsOrderedByTag.h

 #import <UIKit/UIKit.h> @interface AccessibilitySubviewsOrderedByTag : UIView @end 

AccessibilitéSubregementsOrderedByTag.m

 #import "AccessibilityDirectional.h" @implementation AccessibilitySubviewsOrderedByTag { NSMutableArray *_accessibilityElements; } //Lazy loading accessor, avoids instantiating in initWithCoder, initWithFrame, or init. -(NSMutableArray *)accessibilityElements{ if (!_accessibilityElements){ _accessibilityElements = [[NSMutableArray alloc] init]; } return _accessibilityElements; } // Required accessibility methods... -(BOOL)isAccessibilityElement{ return NO; } -(NSInteger)accessibilityElementCount{ return [self accessibilityElements].count; } -(id)accessibilityElementAtIndex:(NSInteger)index{ return [[self accessibilityElements] objectAtIndex:index]; } -(NSInteger)indexOfAccessibilityElement:(id)element{ return [[self accessibilityElements] indexOfObject:element]; } // Handle added and removed subviews... -(void)didAddSubview:(UIView *)subview{ [super didAddSubview:subview]; if ([subview isAccessibilityElement]){ // if the new subview is an accessibility element add it to the array and then sort the array. NSMutableArray *accessibilityElements = [self accessibilityElements]; [accessibilityElements addObject:subview]; [accessibilityElements sortUsingComparator:^NSComparisonResult(id obj1, id obj2){ // Here we'll sort using the tag, but really any sort is possible. NSInteger one = [(UIView *)obj1 tag]; NSInteger two = [(UIView *)obj2 tag]; if (one < two) return NSOrderedAscending; if (one > two) return NSOrderedDescending; return NSOrderedSame; }]; } } -(void)willRemoveSubview:(UIView *)subview{ [super willRemoveSubview:subview]; // Clean up the array. No check since removeObject: is a safe call. [[self accessibilityElements] removeObject:subview]; } @end 

Maintenant, enfermez simplement vos buttons dans une instance de cette vue et définissez la propriété de l'label sur vos buttons comme étant essentiellement l'ordre de mise au point.

Vous pouvez modifier le paramètre d'ordre du tableau accessibilityElements de la vue:

 self.view.accessibilityElements = @[self.view1, self.view2, self.view3, self.view4]; 

ou

 self.anotherView.accessibilityElements = @[self.label1, self.txtView1, self.label2, self.txtView2]; 

Si vous devez définir l'interaction par programmation:

 [self.view1 setUserInteractionEnabled:YES]; 

Si la vue est cachée, la voix ne passera pas à travers.

J'ai essayé la réponse de Wesley à la mise en place de l'array accessibilityElements mais ça n'a pas marché pour moi.

Apple a quelques documents améliorant l'accessibilité des cellules de vue de table avec un exemple dans le code. Fondamentalement, vous définissez l'label d'accessibilité de la cellule (la vue parente) sur les valeurs des labels d'accessibilité des vues enfants.

 [cell setAccessibilityLabel:[NSSsortingng ssortingngWithFormat:@"%@, %@", cityLabel, temperatureLabel]]; 

C'est ce qui a fonctionné pour moi.

Je pense que vous pouvez le faire dans le storyboard. L'ordre VoiceOver est déterminé par l'ordre des vues dans le plan du document.

Faites simplement glisser les vues dans la hiérarchie de vue dans le bon ordre.

Modifier:

Désolé, je ne peux pas postr des captures d'écran jusqu'à 10 réputation. Dans le storyboard, le contour du document est la zone à gauche où vos scènes avec leurs sous-vues sont répertoriées. Ici, les sous-vues sont sortingées les unes sous les autres. Lorsque vous modifiez cet ordre, l'ordre de lecture de VoiceOver change.

Dans Swift, il vous suffit de définir la propriété de tableau accessiblityElements de la vue:

view.accessibilityElements = [view1, view2, view3] // command que vous souhaitez avoir

Cela ne répond pas directement à la question initiale, mais il répond au titre de la question:

Lorsque je souhaite que VoiceOver balaye une colonne vers le bas, j'utilise une vue contenant pour la colonne avec l'set shouldGroupAccessibilityChildren .

J'aurais aimé le savoir plus tôt, car il peut être pénible d'insert rétroactivement des contenants dans une situation d'autolayout …