ios 使用 VoiceOver 更改阅读项目的顺序
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13279498/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Change order of read items with VoiceOver
提问by Mark S
I have a bunch of buttons on the screen which are positioned intuitively visually but are not read in an intuitive order by VoiceOver. This is because certain buttons like Up and Down are placed above and below each other. However, voiceover starts reading from Left to Right, from Top to Bottom, it seems.
我在屏幕上有一堆按钮,它们在视觉上直观地定位,但不是 VoiceOver 以直观的顺序读取的。这是因为某些按钮(例如向上和向下)位于彼此上方和下方。然而,画外音似乎是从左到右,从上到下阅读的。
This results in voiceover reading the button to the right of "Up" after "Up", instead of reading "Down" immediately afterward.
这导致画外音在“向上”之后朗读“向上”右侧的按钮,而不是在之后立即朗读“向下”。
How do I force voiceover to read the button that I want to read? I should mention that I'm using the swipe-to-cycle-through-elements feature on voiceover.
如何强制画外音阅读我想阅读的按钮?我应该提一下,我在画外音时使用了滑动到循环元素功能。
All my buttons are subclassed versions of UIView and UIButton. Here's an example of a button initiator I use. Ignore the pixel count - I know that's bad form but I'm in a pinch at the moment:
我所有的按钮都是 UIView 和 UIButton 的子类版本。这是我使用的按钮启动器的示例。忽略像素数 - 我知道这是不好的形式,但我现在处于紧要关头:
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;
}
采纳答案by NJones
The easiest answer to this lies in creating a UIView
subclass that contains your buttons, and responds differently to the accessibility calls from the system. These important calls are:
对此最简单的答案是创建一个UIView
包含按钮的子类,并对来自系统的辅助功能调用做出不同的响应。这些重要的电话是:
-(NSInteger)accessibilityElementCount
-(id)accessibilityElementAtIndex:
-(NSInteger)indexOfAccessibilityElement:
I've seen a few of these questions, and answered one before, but I've not seen a generic example of how to reorder the VoiceOver focus. So here is an example of how to create a UIView
subclass that exposes its accessible subviews to VoiceOver by tag.
我已经看过其中一些问题,并且之前回答过一个问题,但是我还没有看到如何重新排列 VoiceOver 焦点的通用示例。因此,这里有一个示例,说明如何创建一个UIView
子类,通过标记将其可访问的子视图公开给 VoiceOver。
AccessibilitySubviewsOrderedByTag.h
AccessibilitySubviewsOrderedByTag.h
#import <UIKit/UIKit.h>
@interface AccessibilitySubviewsOrderedByTag : UIView
@end
AccessibilitySubviewsOrderedByTag.m
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
Now simply enclose your buttons in an instance of this view, and set the tag property on your buttons to be essentially the focus order.
现在只需将您的按钮包含在此视图的实例中,并将按钮上的 tag 属性设置为本质上是焦点顺序。
回答by Wesley Galindo
You can change the order setting the view's accessibilityElements array:
您可以更改设置视图的 accessibilityElements 数组的顺序:
self.view.accessibilityElements = @[self.view1, self.view2, self.view3, self.view4];
or
或者
self.anotherView.accessibilityElements = @[self.label1, self.txtView1, self.label2, self.txtView2];
If you need to set the interaction enabled programmatically:
如果您需要以编程方式设置交互启用:
[self.view1 setUserInteractionEnabled:YES];
If the view is hidden the voice over will not pass through it.
如果视图被隐藏,画外音将不会通过它。
回答by Karthik damodara
In Swift you just have to set view's accessiblityElements array property:
在 Swift 中,你只需要设置视图的 accessiblityElements 数组属性:
view.accessibilityElements = [view1, view2, view3]
// order you wish to have
view.accessibilityElements = [view1, view2, view3]
// 您希望拥有的订单
回答by David Dunham
This doesn't directly answer the original question, but it answers the title of the question:
这并没有直接回答原始问题,但它回答了问题的标题:
When I want VoiceOver to swipe down a column, I have been using a containing view for the column with shouldGroupAccessibilityChildren
set.
当我希望 VoiceOver 向下滑动一列时,我一直在使用带有shouldGroupAccessibilityChildren
set的列的包含视图。
I wish I had known this earlier, because it can be a pain to retroactively insert containers into an autolayout situation…
我希望我早点知道这一点,因为将容器追溯插入自动布局情况可能会很痛苦……
回答by TejAces
I know this is an old thread, but I found that the easiest way to do it is to subclass UIView as such (Swift 3). Then simply modify your main UIView type in storyboard to AccessibiltySubviewsOrderedByTag and update the tags in each subview you want read in order.
我知道这是一个旧线程,但我发现最简单的方法是将 UIView 子类化(Swift 3)。然后只需将故事板中的主 UIView 类型修改为 AccessibiltySubviewsOrderedByTag 并按顺序更新每个子视图中的标签。
class AccessibilitySubviewsOrderedByTag: UIView {
类 AccessibilitySubviewsOrderedByTag: UIView {
override func layoutSubviews() {
self.accessibilityElements = [UIView]()
for accessibilitySubview in self.subviews {
if accessibilitySubview.isAccessibilityElement {
self.accessibilityElements?.append(accessibilitySubview)
}
}
self.accessibilityElements?.sort(by: {([cell setAccessibilityLabel:[NSString stringWithFormat:@"%@, %@", cityLabel, temperatureLabel]];
as AnyObject).tag < ( as AnyObject).tag})
}
}
}
回答by ChrisJF
I tried Wesley's answerof setting the array of the accessibilityElements
but it didn't work for me.
我尝试了Wesley 的设置数组的答案,accessibilityElements
但它对我不起作用。
Apple has some documentation Enhancing the Accessibility of Table View Cellswith an example in code. Basically you set the accessibility label of the cell (the parent view) to the values of the accessibility labels of the child views.
Apple 有一些文档以代码示例增强表视图单元的可访问性。基本上,您将单元格(父视图)的可访问性标签设置为子视图的可访问性标签的值。
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()
super.didAddSubview(subview)
}
}
This is what worked for me.
这对我有用。
回答by StefanJ
I think you can do it in the storyboard. The VoiceOver order is determined by the order of the views in the document outline.
我认为你可以在故事板中做到这一点。VoiceOver 的顺序由文档大纲中的视图顺序决定。
Just drag and drop the views in the view hierarchy in the right order.
只需按正确的顺序拖放视图层次结构中的视图。
Edit:
编辑:
Sorry I can not post screenhots until 10 reputation. In the storyboard, the document outline is the area on the left where your scenes with their subviews are listed. Here, subviews are ordered one below each other. When you change this order, the reading-order of VoiceOver will change.
对不起,我不能在 10 声望之前发布屏幕截图。在故事板中,文档大纲是左侧的区域,其中列出了您的场景及其子视图。在这里,子视图按顺序排列。当您更改此顺序时,VoiceOver 的阅读顺序将更改。
回答by Jinyu Meng
I found a convenience way yesterday. Similar to @TejAces ' answer. Make a new swift file, then copy these things into it.
我昨天找到了一个方便的方法。类似于@TejAces 的回答。创建一个新的 swift 文件,然后将这些内容复制到其中。
class ReorderAccessibilityByStoryBoardStackView: UIStackView {
override func didAddSubview(_ subview: UIView) {
updateOrder(false)
super.didAddSubview(subview)
}
}
Set the UIView(contains views you want to reorder)'s class as ReorderAccessibilityByStoryBoardView. Then you can reorder them by reordering storyboard's view list.
将 UIView(包含要重新排序的视图)的类设置为 ReorderAccessibilityByStoryBoardView。然后您可以通过重新排序故事板的视图列表来重新排序它们。
Because subview doesn't contain views in StackView/ScrollView, you need to make a independent class in this file. Such as the ReorderAccessibilityByStoryBoardStackView down below.
因为子视图不包含StackView/ScrollView中的视图,所以需要在这个文件中做一个独立的类。例如下面的 ReorderAccessibilityByStoryBoardStackView。
##代码##With these codes, you can also reorder view's added in code by adding them in a specific order.
使用这些代码,您还可以通过按特定顺序添加视图来重新排序代码中添加的视图。