Проблема фокусировки UIAccessibilityElement в длинном представлении внутри UITableViewCell - PullRequest
1 голос
/ 10 марта 2020

У меня есть UITableViewCell, содержащий представление, которое имеет некоторые дочерние элементы доступности. Вид довольно длинный, длиннее одного экрана.

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

Почему это не работает? Как заставить его работать правильно?

Почему иногда выбранный элемент находится вне экрана? Как сделать это на экране?

Вот пример кода .

  1. Когда двойное нажатие работает правильно, вы увидите журнал в консоли Xcode.
  2. Это упрощенный образец. Я не могу использовать отдельные ячейки в реальном приложении. Думайте об этом как о расширенном текстовом представлении со ссылками, и пользователи используют щелчок влево и вправо для выбора ссылок.

1 Ответ

1 голос
/ 11 марта 2020

Почему не работает? Как заставить его работать правильно?

С VoiceOver OFF ❌, функция tap печатает элемент, когда вы касаетесь его И , если он виден, потому что жест касания происходит только на экране.

Когда VoiceOver ON ✅, вы должны думать так же, даже если программа чтения с экрана может считывать предыдущие метки, которые находятся вне экрана: при двойном касании одним пальцем для элемента вне экрана жест не может быть обработан с помощью GestureRecognizer.
Решением может быть использование метода accessibilityActivate , который срабатывает, когда двойное касание происходит на a11y. элемент.

Я предлагаю создать класс меток, в котором вы реализуете эту функцию:

class myLabel:UILabel {

    init(frame: CGRect, index: Int) {
        super.init(frame: frame)

        text = "\(index)"
        isAccessibilityElement = true
        isUserInteractionEnabled = true

        addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(tap)))
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func accessibilityActivate() -> Bool {
        print(text!)
        return true
    }

    @objc func tap(sender: UITapGestureRecognizer) {

        guard sender.state == .recognized else { return }
        print(sender.view!)
    }
}

Класс LongView имеет следующий код для определения его поведения:

class LongView: UIView {

    override var isAccessibilityElement: Bool {
        get { return false }
        set {   }
    }

    override var accessibilityElementsHidden: Bool {
        get { return false }
        set {   }
    }

    override init(frame: CGRect) {
        super.init(frame: frame)

        let screenWidth = UIScreen.main.bounds.width
        var x: CGFloat = 20
        var y: CGFloat = 20
        let width: CGFloat = 200
        let height: CGFloat = 40
        let spacing: CGFloat = 20

        for index in 0..<20 {

            let label = myLabel(frame: CGRect(x: x, y: y, width: width, height: height),
                                index: index)
            addSubview(label)

            x += width + spacing
            if x + width > screenWidth {
                y += height + spacing
                x = spacing
            }
        }
    }

    required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }

    override var intrinsicContentSize: CGSize {

        CGSize(width: UIScreen.main.bounds.width,
               height: subviews.map { $0.frame.maxY }.max()! + 20)
    }
}

И класс ячеек табличного представления выглядит следующим образом:

class Cell: UITableViewCell {

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)

        let longView = LongView()

        longView.accessibilityElementsHidden = false
        contentView.addSubview(longView)

        longView.translatesAutoresizingMaskIntoConstraints = false
        longView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true
        longView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true
        longView.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
        longView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
    }

    required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
}

Теперь вы можете заметить, что:

  • Функция GestureRecognizer будет запускаться, когда VoiceOver выключен.
  • Жест двойного касания одним пальцем будет обрабатываться, когда VoiceOver включен для каждой отдельной метки, присутствующей на экране, или нет. 10

Я не уверен, что все добавленные строки необходимы для достижения вашей цели, но это обоснование для решения вашей проблемы фокусировки UIAccessibilityElement в длинном представлении внутри UITableViewCell, ???

...