Изменить порядок чтения элементов с помощью VoiceOver - программирование
Подтвердить что ты не робот

Изменить порядок чтения элементов с помощью VoiceOver

У меня есть куча кнопок на экране, которые позиционируются интуитивно визуально, но не читаются в интуитивном порядке VoiceOver. Это связано с тем, что некоторые кнопки, такие как "Вверх" и "Вниз", расположены над и под друг другом. Тем не менее, голос за кадром начинает читать слева направо, сверху донизу, кажется.

Это приводит к тому, что голос за кадром просматривает кнопку справа от "Вверх" после "Вверх", вместо того, чтобы сразу же читать "Вниз".

Как заставить голос за кадром читать кнопку, которую я хочу читать? Я должен упомянуть, что я использую функцию swipe-to-cycle-through-elements для озвучивания.

Все мои кнопки - это подклассы версий 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;
}
4b9b3361

Ответ 1

Самый простой ответ на этот вопрос заключается в создании подкласса UIView, который содержит ваши кнопки, и по-разному реагирует на вызовы доступности из системы. Эти важные вызовы:

-(NSInteger)accessibilityElementCount
-(id)accessibilityElementAtIndex:
-(NSInteger)indexOfAccessibilityElement:

Я видел несколько из этих вопросов, а ответил на вопрос до, но я не видел общий пример того, как изменить порядок фокусировки VoiceOver. Итак, вот пример того, как создать подкласс UIView, который предоставляет свои доступные подзадачи для VoiceOver по тегу.

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

Теперь просто вставьте свои кнопки в экземпляр этого представления и установите свойство тега на ваших кнопках, чтобы быть по существу порядком фокусировки.

Ответ 2

Вы можете изменить настройку порядка массива accessibilityElements:

self.view.accessibilityElements = @[self.view1, self.view2, self.view3, self.view4];

или

self.anotherView.accessibilityElements = @[self.label1, self.txtView1, self.label2, self.txtView2];

Если вам необходимо установить интерактивное взаимодействие программно:

[self.view1 setUserInteractionEnabled:YES];

Если вид скрыт, голос не пройдет через него.

Ответ 3

В Swift вам просто нужно установить свойство access accessiblityElements свойства:

view.accessibilityElements = [view1, view2, view3]//закажите, что хотите

Ответ 4

Я попробовал ответ Уэсли об установке массива accessibilityElements, но это не сработало для меня.

В Apple есть документация Повышение доступности ячеек таблицы с примером в коде. В основном вы устанавливаете метку доступности ячейки (родительское представление) на значения ярлыков доступности дочерних представлений.

[cell setAccessibilityLabel:[NSString stringWithFormat:@"%@, %@", cityLabel, temperatureLabel]];

Это то, что сработало для меня.

Ответ 5

Я думаю, вы можете сделать это в раскадровке. Порядок VoiceOver определяется порядком представлений в контуре документа.

Просто перетащите представления в иерархии представлений в правильном порядке.

Edit:

Извините, я не могу опубликовать скриншоты до 10 репутации. В раскадровке контур документа - это область слева, где перечислены ваши сцены с их подзонами. Здесь подзоны упорядочены один под другим. Когда вы измените этот порядок, порядок чтения VoiceOver изменится.

Ответ 6

Я знаю, что это старый поток, но я обнаружил, что самый простой способ сделать это - подкласс UIView как таковой (Swift 3). Затем просто измените свой основной тип UIView в раскадровке на AccessibiltySubviewsOrderedByTag и обновите теги в каждом подсмотре, который вы хотите прочитать в порядке.

класс AccessibilitySubviewsOrderedByTag: UIView {

override func layoutSubviews() {

    self.accessibilityElements = [UIView]()
    for accessibilitySubview in self.subviews {
        if accessibilitySubview.isAccessibilityElement {
            self.accessibilityElements?.append(accessibilitySubview)
        }
    }
    self.accessibilityElements?.sort(by: {($0 as AnyObject).tag < ($1 as AnyObject).tag})
}

}

Ответ 7

Вчера я нашел удобный способ. Как и ответ @TejAces. Создайте новый быстрый файл, а затем скопируйте в него все.

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()
    }
}

Задайте класс UIView (содержит виды, которые вы хотите переупорядочить) как ReorderAccessibilityByStoryBoardView. Затем вы можете переупорядочить их, переупорядочив список раскадровки.

view list

Поскольку subview не содержит представлений в StackView/ScrollView, вам нужно сделать независимый класс в этом файле. Например, ReorderAccessibilityByStoryBoardStackView ниже.

class ReorderAccessibilityByStoryBoardStackView: UIStackView {
    override func didAddSubview(_ subview: UIView) {
        updateOrder(false)
    }
}

С помощью этих кодов вы также можете изменить порядок, добавленный в код, добавив их в определенном порядке.

Ответ 8

Это напрямую не отвечает на исходный вопрос, но отвечает на заголовок вопроса:

Когда я хочу, чтобы VoiceOver удалял столбец, я использовал содержащее представление для столбца с shouldGroupAccessibilityChildren.

Хотел бы я знать это раньше, потому что это может быть болью, чтобы задним числом вставлять контейнеры в ситуацию автоотключения...