Voice Over 使用总结

来源:互联网 发布:禅道linux安装 编辑:程序博客网 时间:2024/05/18 17:26
1. 如果初始化UIBarButtonItem的时候,customView为UIButton的话,为UIBarButtonItem或UIButton设置accessibilityLabel均可;如果加了一层UIView做为UIButton的containerView,然后把这个containerView设置为UIBarButtonItem的customView,这个时候则只能对UIButton设置accessibilityLabel

案例:返回按钮的修改;其他页面rightbarbuttonitem的修改


2. 对于UITableViewCell,直接通过设置cell的accessibilityLabel属性来实现即可,可以将各个控件的accessibilityLabel组装成一行更加移动简单的文字返回。Apple官方的示例代码或者在自定义UITableViewCell的时候覆盖accessibilityLabel即可:
@implementation WeatherTableViewController
// This is a view that provides weather information. It contains a city subview and a temperature subview, each of which provides a separate label.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
    // set up the cell here...
    NSString *cityLabel = [self.weatherCity accessibilityLabel];
    NSString *temperatureLabel = [self.weatherTemp accessibilityLabel];
    // Combine the city and temperature information so that VoiceOver users can get the weather information with one gesture.
    [cell setAccessibilityLabel:[NSString stringWithFormat:@"%@, %@", cityLabel, temperatureLabel]];
    return cell;
}
@end
参考资料:
1.https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/iPhoneAccessibility/Making_Application_Accessible/Making_Application_Accessible.html
2.https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/TableView_iPhone/TableViewCells/TableViewCells.html
案例:订单列表页cell的修改,下单页cell的修改,首页cell的修改
3. 对于自定义View,需要把UIView变为UIAccessibilityContainer,基本上来说,就是实现下面四个方法,实际上就是需要自己管理所有的UIAccessibilityElement对象,包括这些UIAccessibilityElement对象的label、index、accessibilityFrame。注意设置UIAccessibilityElement对象的accessibilityFrame时,这里的坐标系是相对于window的坐标系,设置的时候,需要转换一下坐标系。
主要体现在实现下面这四个方法:
- (BOOL)isAccessibilityElement;   //返回NO,是container的话,肯定不会是accessibilityElement;也可以在外部设置这个参数;
- (NSInteger)accessibilityElementCount;
- (id)accessibilityElementAtIndex:(NSInteger)index;
- (NSInteger)indexOfAccessibilityElement:(id)element;
示例代码,一个评分控件Voice over实现,这个控件内部有多个UIImageView,为每个UIImageView创建一个UIAccessibilityElement,这时候这个控件就是所谓的UIAccessibilityContainer,所以需要实现上面那几个方法:
- (NSArray *)_getAccessiblityArray
{
    if (_accessibilityArray == nil) {
         _accessibilityArray = [NSMutableArray new];
        for (NSInteger i = 0; i < _imageViews.count; i++) {
            UIAccessibilityElement *element = [[UIAccessibilityElement alloc] initWithAccessibilityContainer:self];
            [_accessibilityArray addObject:element];
        }
    }
    return _accessibilityArray;
}
- (NSString *)_getAccessibilityString:(NSInteger)index rating:(CGFloat)rating
{
    NSString *accessibilityString = nil;
    accessibilityString = [NSString stringWithFormat:@"%@星", @(rating)];
    return accessibilityString;
}
- (BOOL)isAccessibilityElement
{
    return NO;
}
- (NSInteger)accessibilityElementCount
{
    return [[self _getAccessiblityArray] count];
}
- (id)accessibilityElementAtIndex:(NSInteger)index
{
    if (index < 0 || index >= [self _getAccessiblityArray].count) {
        return nil;
    }
    UIAccessibilityElement *element = [self _getAccessiblityArray][index];
    UIImageView *imageView = _imageViews[index];
    element.accessibilityFrame = [[[UIApplication sharedApplication] keyWindow] convertRect:imageView.frame fromView:self];
    element.accessibilityLabel = [self _getAccessibilityString:index rating:index + 1];
    return element;
}
- (NSInteger)indexOfAccessibilityElement:(id)element
{
    NSInteger index = [[self _getAccessiblityArray] indexOfObject:element];
    if (index < 0 || index >= [self _getAccessiblityArray].count) {
        return NSNotFound;
    }
    return index;
}
案例:WMTabbarButton的修改;WMRatingControl的修改
4. 设置一个UIView是否voice accessible,通过设置UIView的isAccessibilityElement为YES,默认UIView的这个属性为NO,通过这个就可以做到,在这个View的展示期间,拦截其下层accessible view的触发,否则,点击这个view的时候,会认为在其他View的UIAccessibilityElement的accessibilityFrame内,所以会触发其他View的voice over。这个可以类比UIView的touch事件机制,正常的UIView不会拦截其下面层次View的touch事件,但是当实现touch:begin方法的时候,就会拦截这些事件,其下面的UIView就无法获得这些touch事件。
在voice over的修改过程中,其实使用的最多的是这个属性,比如当我们通过UIView实现一个弹窗的时候,我们把这个UIView加入到UIWindow当中,如果背景view没有设置isAccessibilityElement为YES的话,我们点击这些空白区域的时候,就会触发弹窗下面View的accessibility element。解决方式很简单,设置背景view的isAccessibilityElement为YES,或者专门添加一个背景view来解决这个问题:
         // voice over accessibility helper view
        UIView *accessibilityBackView = [[UIView alloc] initWithFrame:self.bounds];
        accessibilityBackView.backgroundColor = [UIColor clearColor];
        accessibilityBackView.isAccessibilityElement = YES;
        accessibilityBackView.accessibilityHint = @"双击关闭";
        accessibilityBackView.userInteractionEnabled = NO;
        accessibilityBackView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
        [self insertSubview:accessibilityBackView atIndex:0];
案例:分享红包页面的修改;首页筛选框的修改;WMPickerView的修改
5. voice over对时间的支持,可以使用NSDateFormatter的+ (NSString *)localizedStringFromDate:(NSDate *)date dateStyle:(NSDateFormatterStyle)dstyle timeStyle:(NSDateFormatterStyle)tstyle方法来完成,我这边设置datestyle可以使用NSDateFormatterMediumStyle,而timestyle使用NSDateFormatterShortStyle,实现效果还不错。
参考资料:
  1. http://stackoverflow.com/questions/13418641/accessible-time-labels-on-ios
案例:订单列表页面的修改
6. voice over对web view的支持,给标签添加alt属性
7. 判断voice over是否正在运行:http://stackoverflow.com/questions/8827951/ios-voiceover-status

参考资料
  1. http://noark9.github.io/2014/03/10/using-voice-over/
  2. https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/iPhoneAccessibility/Introduction/Introduction.html
  3. http://www.solstice-mobile.com/blog/programming-for-ios-accessibility-voiceover
  4. http://stackoverflow.com/questions/5872453/uiaccessibilitycontainer-in-a-table-view
0 0
原创粉丝点击