Change order of read items with VoiceOver

后端 未结 8 1186
醉话见心
醉话见心 2020-12-07 17:31

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 U

相关标签:
8条回答
  • 2020-12-07 18:04

    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.

    I wish I had known this earlier, because it can be a pain to retroactively insert containers into an autolayout situation…

    0 讨论(0)
  • 2020-12-07 18:05

    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:

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

    AccessibilitySubviewsOrderedByTag.h

    #import <UIKit/UIKit.h>
    @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
    

    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.

    0 讨论(0)
提交回复
热议问题