首页 > 解决方案 > UICollectionViewCell 自定义子视图没有获得焦点

问题描述

我创建了自定义海报视图,因此它可以在多个集合视图单元格中重复使用(就像 TVUIKit 中的 TVPosterView 一样)。我将它直接添加到具有所有所需约束的单元格内容视图中。

问题是当单元格被聚焦时,这个子视图没有接收焦点更新(didUpdateFocus ..)所以我不能自定义它的焦点/非焦点约束等。奇怪的是里面的图像视图正在获得浮动效果。

如果我将单元格的 preferredFocusEnvironments 指定为return [self.posterView] + super. preferredFocusEnvironments,则 UI 的行为与预期相同,但集合视图委托方法 didSelect 未调用!

提前感谢您的帮助!

标签: uicollectionviewcelltvos

解决方案


似乎 didUpdateFocus 没有调用焦点单元的所有子视图及其系统设计。来自文档:

焦点更新到新视图后,焦点引擎在所有焦点环境上调用此方法,这些焦点环境按升序包含先前焦点视图、下一个焦点视图或两者。您应该重写此方法以更新应用的状态以响应焦点的变化。使用提供的动画协调器对与更新相关的视觉外观变化进行动画处理。有关动画协调器的更多信息,请参阅 UIFocusAnimationCoordinator。

注意:所以这意味着didUpdateFocus将在 UICollectionViewCell 上首先调用,而不是在 UIViewController 子类上,按升序排列。对于子视图,您需要手动注册customDidUpdateFocus将在通知更新中触发的方法。例如,要更新它的外观,我们可以使用通知 (tvOS 11+),请参阅下面的示例。

func customDidUpdateFocus(isFocused: Bool, with coordinator: UIFocusAnimationCoordinator) { /* Custom logic to customize appearance */ }

// Register observer
observerToken = NotificationCenter.default.addObserver(forName: UIFocusSystem.didUpdateNotification, object: nil, queue: .main) { [weak self] (note) in
        guard let self = self else { return }
        guard let context = note.userInfo?[UIFocusSystem.focusUpdateContextUserInfoKey] as? UIFocusUpdateContext else { return }
        guard let coordinator = note.userInfo?[UIFocusSystem.animationCoordinatorUserInfoKey] as? UIFocusAnimationCoordinator else { return }
        
        if let prev = context.previouslyFocusedView, self.isDescendant(of: prev) {
            self.didUpdateFocus(isFocused: false, with: coordinator)
        } else if let next = context.nextFocusedView, self.isDescendant(of: next) {
            self.didUpdateFocus(isFocused: true, with: coordinator)
        }
    }

推荐阅读