我创建了一个空白项目如下重现问题:
解决方案是使用selectedIndex 显示选定的段并为VoiceOver notification 提供适当的段对象:很简单,不是吗?
我天真地认为使用selectedIndex 获取分段控制子视图数组中的子视图可以完成这项工作,但这绝对不可能,因为子视图可以在此数组内移动,如下面的快照突出显示(例如红框的第一个元素):
识别唯一段的唯一方法是它的框架,所以我拾取分段控制索引和选定段的框架,以将它们传递给前一个视图控制器。
这将允许显示(索引)并读出(标识通知对象的框架)当此屏幕将在转换后出现时适当的选定段.
以下是包含“下一个屏幕”按钮的视图控制器的代码 sn-ps:
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]!) }
}
最终结果如下:
- 双击可转到下一个屏幕。
- 选择下一个元素以聚焦第二个片段。
- 双击以选择焦点元素。
- 感谢
Z gesture,iOS 自带导航控制器,可以返回上一个屏幕。委托传递所选段的索引和框架。
- 双击可转到下一个屏幕。
- 之前选择的片段被 VoiceOver 读出并且仍然被选中。
您现在可以将可访问性重点放在 UISegmentedControl 中的特定段上。
我尽量避免使用“hacky”解决方案(比如我刚才提到的那个),但我愿意考虑任何事情。
不幸的是,这个解决方案很老套……抱歉。但是,它有效,我在其他任何地方都找不到另一个:除非您找到更清洁的共享,否则将其视为个人修复? ;o)
更新...这可能是第二个问题的主题。
我无法重现您更新的行为:如果您为此问题创建了专门的主题,请添加最详细的代码和上下文,以便提供最准确的解决方案。