首页 文章

使用VoiceOver可以访问大单元格的嵌套集合视图

提问于
浏览
6

在我目前正在处理的应用程序中,有一个嵌套的集合视图设置 . 外部集合视图包含可垂直滚动的大单元格,每个单元格包含另一个具有较小单元格的集合视图(子集合视图中的布局不同,这就是为什么有多个单元格) .

在视觉上,一切正常,但我遇到了Voice Over的一个问题:当我到达第一个子集合视图中的最后一个项目时(即外部集合视图的第一个单元格的最后一项),我不能通过滑动选择下一个项目 . 相反,iOS会将声音视为最后一个项目 .

我可以用三指滑动向下滚动,然后选择下一个元素,但这显然不是必需的 . 选择最后一个元素并以相反的顺序返回,按预期工作 .

只有当一个单元格(外部集合视图)最初可见时才会出现问题 . 如果可以看到多个单元格,一切正常 . 但是,我无法更改外部单元格的大小,因为这会完全改变布局 .

我在下面创建了一个示例视图控制器来演示该问题 . 除了单元格的大小之外,项目中的两个集合视图是相同的 . 具有较小单元格的第一个集合视图按预期工作 . 第二个没有(当选择下一个单元格时,iOS会在选择最后一个可见单元格时播放“嘟嘟”声,即使有更多单元格进一步向下) .

所以,我的问题是:

  • 如何使第二个集合视图的行为与第一个相同?

  • 如何通过水平滑动访问第二个集合视图中的单元格?

到目前为止我尝试的解决方案:

  • 一篇SO帖子建议为嵌套集合视图创建包装器视图 . 这似乎没有任何区别 .

  • 我试图在集合视图的自定义子类中自己实现UIAccessibilityContainer协议 . 这似乎以奇怪的方式打破滚动 .

  • 在随机位置放置"layout changed"通知以查看是否有帮助(它没有)

编辑:演示此问题的ViewController的完整代码:

class ViewController: UIViewController, UICollectionViewDataSource {
    let outerCollectionView = UICollectionView(frame: CGRect(x: 0, y: 40, width: 320, height: 250), collectionViewLayout: UICollectionViewFlowLayout())

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .green
        outerCollectionView.backgroundColor = .blue

        (outerCollectionView.collectionViewLayout as! UICollectionViewFlowLayout).itemSize = CGSize(width: 250, height: 300)
        outerCollectionView.register(OuterCell.self, forCellWithReuseIdentifier: "outerCell")
        view.addSubview(outerCollectionView)
        outerCollectionView.dataSource = self
    }

    func numberOfSections(in collectionView: UICollectionView) -> Int { return 1 }
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return 4 }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "outerCell", for: indexPath) as! OuterCell
        cell.outerIndex = indexPath.row + 1
        return cell
    }
}

class OuterCell: UICollectionViewCell, UICollectionViewDataSource {
    var innerCollectionView = UICollectionView(frame: CGRect(x: 0, y: 0, width: 300, height: 500), collectionViewLayout: UICollectionViewFlowLayout())
    var outerIndex: Int = 0

    override init(frame: CGRect) {
        super.init(frame: frame)
        (innerCollectionView.collectionViewLayout as! UICollectionViewFlowLayout).itemSize = CGSize(width: 140, height: 80)
        innerCollectionView.backgroundColor = .yellow
        innerCollectionView.register(InnerCell.self, forCellWithReuseIdentifier: "innerCell")
        contentView.addSubview(innerCollectionView)
        innerCollectionView.dataSource = self
    }
    required init?(coder aDecoder: NSCoder) {
        fatalError("unused")
    }
    func numberOfSections(in collectionView: UICollectionView) -> Int { return 1 }
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return 3 }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "innerCell", for: indexPath) as! InnerCell
        cell.label.text = "Cell \(outerIndex) / \(indexPath.item+1)"
        return cell
    }
}

class InnerCell: UICollectionViewCell {
    let label = UILabel(frame: CGRect(origin: .zero, size: CGSize(width: 100, height: 30)))

    override init(frame: CGRect) {
        super.init(frame: frame)
        contentView.backgroundColor = .white
        contentView.addSubview(label)
    }
    required init?(coder aDecoder: NSCoder) {
        fatalError("unused")
    }
}

编辑:这是一个显示问题的视频:https://vimeo.com/229249955(请注意,我在那里添加了一些描述) .

1 回答

  • 2

    根据我的理解问题,一旦到达内部集合视图中的最后一个单元格,就无法滚动到外部集合视图中的下一个单元格 . 但是三指滑动有效 .

    这是因为集合视图上的反弹属性 . 尝试关闭内部集合视图上的bounce属性 .

    在上面的代码中,在OuterCell init方法中添加以下代码行 .

    innerCollectionView.bounces = false
    

相关问题