VoiceOver читает метку доступности дважды, когда фокусируется не на UILabel titleView - PullRequest
0 голосов
/ 02 марта 2019

У меня возникла странная проблема с VoiceOver.

Цели:

  • Установите UIStackView, содержащее несколько UILabel, как мои navigationItem.titleView.
  • Пометьте представление стека как элемент доступности и установите для его accessibilityLabel соответствующее значение.
  • Установите представление стека в качестве начального фокуса VoiceOver, вызвав UIAccessibility.post(notification: .screenChanged, argument: navigationItem.titleView) внутри viewDidAppear(animated:).

Ожидаемый результат:

  • Когда появляется контроллер вида, фокус оказывается на виде заголовка, и VoiceOver считывает содержимое метки доступности один раз.

Фактический результат:

  • VoiceOver начинает читать содержимое метки доступности, а затем частично (или иногда после завершения) продолжает читать его во второй раз.

Эта проблема не возникает, если для navigationItem.titleView задан экземпляр UILabel.

Кто-нибудь знает, почему это происходит?Это ошибка в iOS?

Я настроил простой проект, демонстрирующий эту проблему здесь: https://github.com/rzulkoski/Focus-TitleView-Bug

1 Ответ

0 голосов
/ 02 марта 2019

Причина, по которой вы читаете заголовок во второй раз, кроется в вашем коде.

В вашем viewDidLoad вы устанавливаете метку доступности стека, которую VoiceOver автоматически считывает, чтобы сообщить пользователю об изменении.

Далее вы сообщаете об этом изменении сообщением в вашем viewDidAppear, которое VoiceOver естественным образом считывает.

Чтобы избежать этого, просто удалите stackView.accessibilityLabel = label.text в вашем setupNavigationItem добавьте этот фрагмент в вашу личную ленивую переменную метки init:

if (self.view.subviews.contains(stackView)) {
        stackView.accessibilityLabel = label.text
}

Обновление stackView.accessibilityLabel таким образом не вызывает VoiceOver, чтобы сообщить пользователю, и позволяет понять вашу цель.

Однако я не рекомендую зачитывать заголовок в качестве первого элемента новой страницы, если вы не измените порядок представленных элементов.

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

  • Возможно, они не найдут способ вернуться на предыдущую страницу.
  • Они могут быть потеряны, если получат первый элементстраницы с 4 пальцами просто нажмите , потому что они получат кнопку назад, а не заголовок.

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

==========

РЕДАКТИРОВАТЬ (обходной путь)

Что касается технической проблемы, вы правы в своем комментарии, это решение выше работает благодаря чтению метки VoiceOver.

Я зафиксировалрешение в вашей ветке git, которое вы дали в своем первоначальном посте.

Проблема связана с UIStackView, который я не могу объяснить в этом случае и не могу решить ни как есть.

Чтобы достичь вашей цели, ясоздал UIAccessibilityELement для стека, который может быть идеально доступен и доступен без двойного чтения с пост-уведомлением.

Я сделал это, потому что не мог программно получить новый размер стека, когда надписи находятся в ...может быть кресть подкласс UIStackView и войти в его layoutSubviews может быть хитростью?

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

==========

РЕДАКТИРОВАТЬ (решение)

Проблема заключается в способе titleViewnavigationItem создано.Лучший способ достичь своей цели - это:

  • Инициализировать ваш titleView как простой UIView, кадр которого совпадает с представлением стека.
  • Добавить представление стека как подпредставление послеуказав его фрейм и его свойства доступности.

Выполните следующие шаги в вашем коде:

  • Добавьте черту .header в свойстве stackview:

    private lazy var stackView: UIStackView = {
        let stackView = UIStackView(frame: .zero)
        stackView.axis = .vertical
        stackView.alignment = .center
        stackView.distribution = .equalSpacing
        stackView.isAccessibilityElement = true
        stackView.accessibilityTraits = .header
        return stackView
    }()
    
  • Измените регистр стека в разделе кода "switch ... case ...", как показано ниже:

    case .stackView:
        label.text = "UIStackView"
        label.sizeToFit()
        stackView.addArrangedSubview(label)
    
        label2.text = subtitle
        label2.sizeToFit()
        stackView.addArrangedSubview(label2)
    
        stackView.frame.size.width = max(label.frame.width, label2.frame.width)
        stackView.frame.size.height = label.frame.height + label2.frame.height
    
        stackView.accessibilityLabel = label.text?.appending(", \(label2.text!)")
    
        navigationItem.titleView = UIView(frame: stackView.frame)
        navigationItem.titleView?.addSubview(stackView)
    }
    

Теперь postNotification считывает ваш стек только один раз как первый элемент вашего экрана.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...