iOS Uitableview Accessibility Order Is Wrong After Setting Accessibilityelements on Uitableviewcell

Unable to configure voice over accessibility for a custom UITableViewCell

First of all, from the pattern you described, I'm not sure why you would want to differentiate between different elements in a cell. Generally, Apple keeps every cell a single accessibility element. A great place to see the expected iOS VO behavior for cells with labels and switches is in Settings App.

If you still believe the best way to handle your cells is to make them contain individual elements, then that is actually the default behavior of a cell when the UITableViewCell itself does not have an accessibility label. So, I've modified your code below and run it on my iOS device (running 9.3) and it works as you described you would like.

You'll notice a few things.

  1. I deleted all the custom accessibilityElements code. It is not necessary.
  2. I deleted the override of isAccessibilityElement on the UITableViewCell subclass itself. We want default behavior.
  3. I commented out setting the content view as an accessibilityElement -- we want that to be NO so that the tree-builder looks inside of it for elements.
  4. I set customAccessoryView's isAccessibilityElement to NO as well for the same reason as above. Generally, NO says "keep looking down the tree" and YES says "stop here, this is my leaf as far as accessibility is concerned."

I hope this is helpful. Once again, I do really encourage you to mimic Apple's VO patterns when designing for Accessibility. I think it's awesome that you're making sure your app is accessible!

#import "MyCustomTableViewCell.h"

@interface MyCustomTableViewCell()

@property (nonatomic, strong) UIView *customAccessoryView;
@property (nonatomic, strong) NSString *alertTextString;
@property (nonatomic, strong) NSMutableArray* accessibleElements;
@end

@implementation MyCustomTableViewCell

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
if(self = [super initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:reuseIdentifier]) {
[self configureTableCell];
}
return self;
}

// just added this here to get the cell to lay out for myself
- (void)layoutSubviews {
[super layoutSubviews];

const CGFloat margin = 8;

CGRect b = self.bounds;

CGSize labelSize = [self.alertLabel sizeThatFits:b.size];
CGFloat maxX = CGRectGetMaxX(b);
self.alertLabel.frame = CGRectMake(margin, margin, labelSize.width, labelSize.height);

CGSize switchSize = [self.mySwitch sizeThatFits:b.size];
self.customAccessoryView.frame = CGRectMake(maxX - switchSize.width - margin * 2, b.origin.y + margin, switchSize.width + margin * 2, switchSize.height);
self.mySwitch.frame = CGRectMake(margin, 0, switchSize.width, switchSize.height);
}

- (void)configureTableCell
{
//Alert label
self.alertLabel = [[self class] makeAlertLabel];
//[self.contentView setIsAccessibilityElement:YES];
//
[self.contentView addSubview:self.alertLabel];

// Custom AccessoryView for easy styling.
self.customAccessoryView = [[UIView alloc] initWithFrame:CGRectZero];
[self.customAccessoryView setIsAccessibilityElement:NO]; // Setting this to NO tells the the hierarchy builder to look inside
[self.contentView addSubview:self.customAccessoryView];
self.customAccessoryView.backgroundColor = [UIColor purpleColor];

//switch
self.mySwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
//[self.mySwitch addTarget:self action:@selector(switchWasFlipped:) forControlEvents:UIControlEventValueChanged];
[self.mySwitch setIsAccessibilityElement:YES]; // This is default behavior
[self.mySwitch setAccessibilityTraits:UIAccessibilityTraitButton]; // No tsure why this is here
[self.mySwitch setAccessibilityLabel:@"my swich"];
[self.mySwitch setAccessibilityHint:@"Tap to do something."];
self.mySwitch.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
[self.customAccessoryView addSubview:self.mySwitch];
}

+ (UILabel *)makeAlertLabel
{
UILabel *alertLabel = [[UILabel alloc] initWithFrame:CGRectZero];
alertLabel.backgroundColor = [UIColor clearColor];
alertLabel.text = @"";
alertLabel.numberOfLines = 0;
[alertLabel setIsAccessibilityElement:YES];
return alertLabel;
}

-(void)setAlertHTMLText:(NSString*)title{
_alertTextString = [NSString stringWithString:title];
[self.alertLabel setText:_alertTextString];
}

@end

Incorrect accessibility order in UICollectionViewCell with viewForSupplementaryElement

It turns out the incorrect ordering was caused by using a UITableViewCell as the header view for the UICollectionView. A crash manifested when scrolling with VoiceOver turned on and I managed to stop this crash by returning the contentView of the cell in the UIAccessibilityContainer protocol.

#pragma mark - UIAccessibilityContainer

-(NSInteger)accessibilityElementCount {

int headerCount = self.headerView ? 1 : 0;
int footerCount = self.footerView ? 1 : 0;

return ([self.dataValues count] + headerCount + footerCount;
}

-(id)accessibilityElementAtIndex:(NSInteger)index {
if (index == 0) {
if (self.headerView) {
if ([self.headerView isKindOfClass:[UITableViewCell class]]) {
UIView *header = ((UITableViewCell *)self.headerView).contentView;
header.shouldGroupAccessibilityChildren = YES;
return header;
}
return self.headerView;
}
}
if (self.headerView) index -= 1;

if (index >= [self.dataValues count]) {
if ([self.footerView isKindOfClass:[UITableViewCell class]]) {
return ((UITableViewCell *)self.footerView).contentView;
}
return self.footerView;
}

return [self collectionView:_collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0]];
}

The answer to this question pointed me in the right direction:

iOS VoiceOver crash (message sent to deallocated instance)

AccessibilityElements not working in TableView

It's fairly uncommon to have subelements of a cell be accessibility elements of their own. If you look at other apps on your device (Apple's own apps usually have good accessibility) you will see that in most cases the table view cell is a single accessibility element that contains all the information from its subelements in its label.

You can achieve this by making the cell an accessibility element and the subelements not be accessibility elements. Then, you construct a custom accessibility label out of the different pieces of information in the order that you find most suitable.



Related Topics



Leave a reply



Submit