Как сфокусировать доступность на определенном сегменте в UISegmentedControl - PullRequest
0 голосов
/ 14 декабря 2018

OK. Этот ответ очень помогает.Я могу выбрать элемент доступности, когда отображается экран.Я просто добавляю

UIAccessibility.post(notification: .layoutChanged, argument: <a reference to the UI item to receive focus>)

в конец моего метода viewWillAppear (), и элемент получает фокус.

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

Есть лиспособ сделать это?Как правило, я стараюсь избегать «хакерских» решений (например, тех, на которые я только что ссылался), но я готов рассмотреть все, что угодно.

Спасибо!

ОБНОВЛЕНИЕ: Просто чтобы добавить оскорбление к травме, у меня также есть проблема с выбранным элементом, который я хочу выбрать, затем секунду спустя, экран переходит на выбор к первому элементу.Это, вероятно, тема для второго вопроса.

1 Ответ

0 голосов
/ 08 августа 2019

Я создал пустой проект, чтобы воспроизвести проблему следующим образом: enter image description here

Решением является с использованием selectedIndex для отображения выбранного сегмента и предоставление соответствующего объекта сегмента для уведомления VoiceOver : легко, не правда ли?

Я наивно полагал, что получение подпредставления в массиве сегментированных контрольных подпредставлений с помощьюselectedIndex выполнит эту работу, но это определенно невозможно, потому что подпредставления могут перемещаться внутри этого массива , как показано на следующем снимке (например, первый элемент в красной рамке) : enter image description here Единственный способ идентифицировать уникальный сегмент - это его кадр, поэтому я выбираю сегментированный контрольный индекс и кадр выбранного сегмента, чтобы передать их в предыдущий контроллер представления.

Это позволитдля отображения (индекс) и считывания (кадр, который идентифицирует объект для уведомления) соответствующий выбранный сегмент, когда этот экранпоявится после перехода.

Здесь и далее фрагменты кода для контроллера представления, содержащего кнопку «Следующий экран»:

class SOFSegmentedControl: UIViewController, UpdateSegmentedIndexDelegate {

    var segmentIndex = 0
    var segmentFrame = CGRect.zero


    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        if let segueName = segue.identifier {
            if (segueName == "SegmentSegue") {
                if let destVC = segue.destination as? SOFSegmentedControlBis {

                    destVC.delegate = self
                    destVC.segmentIndex = segmentIndex
                    destVC.segmentFrame = segmentFrame
                }
            }
        }
    }


    @IBAction func buttonAction(_ sender: UIButton) { self.performSegue(withIdentifier: "SegmentSegue", sender: sender) }


    func updateSegmentIndex(_ index: Int, withFrame frame: CGRect) {

        segmentIndex = index
        segmentFrame = frame
    }
}

... и для контроллера представления, отображающего сегментированныйуправление:

protocol UpdateSegmentedIndexDelegate: class { 
    func updateSegmentIndex(_ index: Int, withFrame frame: CGRect) 
}


class SOFSegmentedControlBis: UIViewController {

    @IBOutlet weak var mySegmentedControl: UISegmentedControl!

    var delegate: UpdateSegmentedIndexDelegate?
    var segmentFrame = CGRect.zero
    var segmentIndex = 0
    var segmentFrames = [Int:CGRect]()


    override func viewDidLoad() {
        super.viewDidLoad()

        mySegmentedControl.addTarget(self,
                                     action: #selector(segmentedControlValueChanged(_:)),
                                     for: .valueChanged)

        mySegmentedControl.selectedSegmentIndex = segmentIndex
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        print(mySegmentedControl.subviews)

        let sortedFrames = mySegmentedControl.subviews.sorted(by: { $0.frame.origin.x < $1.frame.origin.x})

        for (index, segment) in sortedFrames.enumerated() { segmentFrames[index] = segment.frame }

        if (self.segmentFrame == CGRect.zero) {
            UIAccessibility.post(notification: .screenChanged,
                                 argument: mySegmentedControl)
        } else {
            mySegmentedControl.subviews.forEach({
                if ($0.frame == self.segmentFrame) {
                    UIAccessibility.post(notification: .screenChanged,
                                         argument: $0)
                }
            })
        }
    }


    @objc func segmentedControlValueChanged(_ notif: NSNotification) {

        delegate?.updateSegmentIndex(mySegmentedControl.selectedSegmentIndex,
                                     withFrame: segmentFrames[mySegmentedControl.selectedSegmentIndex]!) }
    }

Окончательный результат выглядит следующим образом: enter image description here enter image description here

  1. Дважды нажмите, чтобы перейти кследующий экран.
  2. Выберите следующий элемент, чтобы сфокусировать второй сегмент.
  3. Дважды нажмите, чтобы выбрать сфокусированный элемент.
  4. Вернитесь на предыдущий экран благодаря Z gesture изначально известен iOS с контроллером навигации.Делегат передает индекс и фрейм выбранного сегмента.
  5. Дважды нажмите, чтобы перейти к следующему экрану.
  6. Сегмент, который был ранее выбран, считывается VoiceOver и остается выбранным.

Теперь вы можете Доступность фокуса на определенном сегменте в UISegmentedControl в соответствии с этим обоснованием.

Я стараюсь избегать "хакерских" решений (таких какодин, на который я только что ссылался), но я готов рассмотреть что угодно.

К сожалению, это решение является хакерским ... извините.Тем не менее, это работает, и я не мог найти другого в другом месте: рассматривать это как личное исправление, если у вас нет более чистого, чтобы поделиться?; o)

ОБНОВЛЕНИЕ ... Вероятно, это тема для второго вопроса.

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

...