使用VoiceOver更改已读项目的顺序

我在屏幕上有一堆按钮,这些按钮直观地定位,但不是由VoiceOver按直观顺序读取的。 这是因为某些按钮(如Up和Dwon)位于彼此的上方和下方。 然而,画外音似乎开始从左到右,从上到下阅读。

这导致画外音在“向上”之后读取“向上”右侧的按钮,而不是之后立即读取“向下”。

如何强制画外音阅读我想要阅读的按钮? 我应该提一下,我正在使用画外音上的滑动到循环元素function。

我的所有按钮都是UIView和UIButton的子类。 这是我使用的按钮启动器的示例。 忽略像素数 – 我知道这是不好的forms,但我现在处于紧张状态:

UIButton* createSpecialButton(CGRect frame, NSString* imageName, NSString* 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; } 

最简单的答案在于创建一个包含按钮的UIView子类,并对系统的可访问性调用做出不同的响应。 这些重要的电话是:

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

我已经看过其中的一些问题, 之前已经回答了一个问题,但我还没有看到如何重新排序VoiceOver焦点的一般示例。 所以这里是一个如何创建UIView子类的示例,该子类通过标记将其可访问的子视图公开给VoiceOver。

AccessibilitySubviewsOrderedByTag.h

 #import  @interface AccessibilitySubviewsOrderedByTag : UIView @end 

AccessibilitySubviewsOrderedByTag.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 

现在只需将按钮包含在此视图的实例中,并将按钮上的tag属性设置为焦点顺序。

您可以更改视图的accessibilityElements数组的顺序设置:

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

要么

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

如果需要以编程方式设置交互:

 [self.view1 setUserInteractionEnabled:YES]; 

如果视图被隐藏,则语音将不会通过它。

在Swift中,您只需设置view的accessiblityElements数组属性:

view.accessibilityElements = [view1, view2, view3] //你希望拥有的订单

我尝试了Wesley设置accessibilityElements数组的答案 ,但它对我不起作用。

Apple有一些文档通过代码中的示例增强了表视图单元的可访问性 。 基本上,您将单元格的可访问性标签(父视图)设置为子视图的可访问性标签的值。

 [cell setAccessibilityLabel:[NSString stringWithFormat:@"%@, %@", cityLabel, temperatureLabel]]; 

这对我有用。

我想你可以在故事板中做到这一点。 VoiceOver顺序由文档大纲中的视图顺序决定。

只需按正确的顺序拖放视图层次结构中的视图即可。

编辑:

对不起,我不能发布屏幕直到10声誉。 在故事板中,文档大纲是左侧区域,其中列出了包含子视图的场景。 在这里,子视图按顺序排列。 当您更改此顺序时,VoiceOver的阅读顺序将会更改。

这不直接回答原始问题,但它回答了问题的标题:

当我想让VoiceOver向下滑动一列时,我一直在使用包含该视图的列shouldGroupAccessibilityChildren设置shouldGroupAccessibilityChildren

我希望我早些时候知道这一点,因为将容器追溯到自动布局情况可能会很痛苦……

我知道这是一个旧线程,但我发现最简单的方法是将UIView作为子类(Swift 3)。 然后只需将故事板中的主要UIView类型修改为AccessibiltySubviewsOrderedByTag,并更新要按顺序读取的每个子视图中的标记。

class AccessibilitySubviewsOrderedByTag:UIView {

 override func layoutSubviews() { self.accessibilityElements = [UIView]() for accessibilitySubview in self.subviews { if accessibilitySubview.isAccessibilityElement { self.accessibilityElements?.append(accessibilitySubview) } } self.accessibilityElements?.sort(by: {($0 as AnyObject).tag < ($1 as AnyObject).tag}) } 

}

我昨天找到了方便的方式。 类似于@TejAces的回答。 制作一个新的swift文件,然后将这些内容复制到其中。

 import UIKit extension UIView { func updateOrder(_ direction: Bool = true) { var tempElements: [Any]? = [Any]() let views = (direction) ? subviews : subviews.reversed() for aView in views { tempElements?.append(aView) } accessibilityElements = tempElements } } class ReorderAccessibilityByStoryBoardView: UIView { override func didAddSubview(_ subview: UIView) { updateOrder() } } 

将UIView(包含要重新排序的视图)的类设置为ReorderAccessibilityByStoryBoardView。 然后,您可以通过重新排序故事板的视图列表来重新排序它们。

查看列表

由于子视图在StackView / ScrollView中不包含视图,因此您需要在此文件中创建一个独立的类。 如下面的ReorderAccessibilityByStoryBoardStackView。

 class ReorderAccessibilityByStoryBoardStackView: UIStackView { override func didAddSubview(_ subview: UIView) { updateOrder(false) } } 

使用这些代码,您还可以通过按特定顺序添加视图来重新排序代码中添加的视图。

Interesting Posts