Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I prevent UIaccessibility from saying "heading" for controls created inside viewforheaderinsection?

So, I have a tableview and inside the viewforheaderinsection, I create a view, create some controls such as buttons and segmented controls programmatically. I add those controls as subview of the view and then return the view. The problem is when Accessibility reads the controls, it appends "heading" at the end. It says "button" pauses and then says "heading". I know I can convert the headerview to cells to suppress the "heading" callout but that is not an option. The project is pretty big and it requires a lot of time to change headerviews to cells. Is there a way to suppress the "heading" callout without changing headerview to cell?

like image 396
Suraj Avatar asked Aug 25 '16 15:08

Suraj


2 Answers

You need to implement

-(void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section;

for example

- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section
{
     view.accessibilityTraits = UIAccessibilityTraitNone;
}

inside that function, set the accessibility trait for the header to UIAccessibilityTraitNone, or simply remove UIAccessibilityTraitHeader.

Doing it inside

-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section 

will not do any good because the iOS will add the header trait later on. You need to modify the trait right before the header is being displayed.

like image 84
CocoaAficionado Avatar answered Nov 05 '22 08:11

CocoaAficionado


The answer by @cocoaaficionado did not work for me on iOS 10.3.

What I had to do was the following:

For your header view, you need to froce by subclassing, the accessibilityElements property of the view, and use UIAccessibilityElements instead of UIView/UILabel/UIButton directly.

@interface NotAHeadingView : UIView

@end

@implementation NotAHeadingView

- (void)layoutSubviews
{
    [super layoutSubviews];

    NSMutableArray *accessibilityElements = [NSMutableArray arrayWithCapacity:self.subviews.count];
    for (UIView *view in self.subviews) {
        UIAccessibilityElement *element = [[UIAccessibilityElement alloc] initWithAccessibilityContainer:self];
        // remove Header trait
        element.accessibilityTraits = view.accessibilityTraits & ~UIAccessibilityTraitHeader;
        element.accessibilityFrame = view.accessibilityFrame;
        element.accessibilityLabel = view.accessibilityLabel;
        element.accessibilityValue = view.accessibilityValue;
        element.accessibilityHint = view.accessibilityHint;
        element.accessibilityFrameInContainerSpace = view.frame;
        [accessibilityElements addObject:element];
    }

    self.accessibilityElements = accessibilityElements;
}

@end

UIViews seem to automatically inherit the Header trait from the view hierarchy, even overriding traits for their direct superview isn't enough. This worked on an iOS 10.3 device for me.

This works for simple cases, but did not work for me when applied to a very complex section header view (multiple child viewControllers managing the subviews, deep view hierarchy including scrollViews) - instead it was much easier to resign how this view worked to avoid section headers for these elements. YMMV

like image 2
Ashton-W Avatar answered Nov 05 '22 07:11

Ashton-W