我在VoiceOver上遇到一个奇怪的问题。
目标:
UIStackView
的{{1}}设置为我的UILabel
。navigationItem.titleView
设置为适当的值。accessibilityLabel
内调用UIAccessibility.post(notification: .screenChanged, argument: navigationItem.titleView)
,将堆栈视图设置为VoiceOver的初始焦点。预期结果:
实际结果:
如果我将viewDidAppear(animated:)
设置为navigationItem.titleView
的实例,则不会发生此问题。
有人知道为什么会这样吗?是iOS中的错误吗?
我建立了一个简单的项目,在这里演示了这个问题: https://github.com/rzulkoski/Focus-TitleView-Bug
答案 0 :(得分:1)
第二遍阅读标题的原因在代码中。
在static void Main(string[] args)
{
var gradeId = 1;
var context = new SchoolContext();
var data = context.Grades.Include(x => x.Students.Where(how to pass gradeId here)).SingleOrDefault();
}
中,设置VoiceOver自动读取的堆栈视图可访问性标签,以将更改通知用户。
接下来,您通过viewDidLoad
中的帖子通知此更改,VoiceOver也自然会读出。
要防止这种情况发生,只需在viewDidAppear
函数中删除stackView.accessibilityLabel = label.text
并将此代码段添加到您的私有惰性var标签init中即可:
setupNavigationItem
以这种方式更新if (self.view.subviews.contains(stackView)) {
stackView.accessibilityLabel = label.text
}
不会触发VoiceOver通知用户,而是可以达到目的。
但是,不建议您将标题作为新页面的第一个元素读出来,除非您reorder出现的元素。
VoiceOver用户自然不会猜测标题前面是否存在另一个元素:
从技术上说,您的问题已通过上面的代码段解决了,但从概念上讲,如果您仍然希望将标题显示为第一个元素,则建议对元素进行重新排序。
==========
编辑(解决方法)
关于技术问题,您的评论是正确的,由于VoiceOver读取了标签,因此上述解决方案可以正常工作。
我在最初帖子中给您的git分支中提交了一个解决方案。
问题与UIStackView有关,在这种情况下我无法解释,也无法按原样解决。
为了达到您的目的,我为stackview创建了一个stackView.accessibilityLabel
,可以完美地到达该对象并暴露出来,而无需使用后通知进行双重读取。
我这样做是因为标签插入时无法以编程方式获取新的stackview大小...也许创建一个UIStackView子类并进入其UIAccessibilityELement
可能是窍门?
此解决方案应该作为一种解决方法,但我不知道在UIStackview中出现此行为的原因。
==========
编辑(解决方案)
问题是创建layoutSubviews
中的titleView
的方式。实现目标的最好方法是:
navigationItem
,其框架与stackview的框架相同。按照以下代码中的步骤进行操作:
在stackview属性中添加UIView
特性:
.header
在“ switch ... case ...”代码部分中更改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
}()
现在,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)
}
仅读取一次堆栈视图作为屏幕的第一个元素。