Почему не работает? Как заставить его работать правильно?
С 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, ???