在tvOS中,如何为自定义视图添加聚焦效果和动画缩放?

16

我在我的tvOS应用程序中有一个自定义的UICollectionViewCell。它里面有一个UIImageView和一些UILabel。我可以通过实现UIFocusEnvironment协议来使单元格聚焦,但是我无法弄清楚如何给我的自定义单元格提供聚焦外观(高程并响应触摸板上的用户移动)。

我知道UIImageViewadjustsImageWhenAncestorFocused属性,但这只会提高我的单元格中的图像,而不是整个单元格。

是否有一种方法可以让tvOS将标准聚焦外观/行为应用于我的自定义视图,还是我必须全部手动完成?

提前致谢。

2个回答

18

tvOS 12.0+更新:看看苹果提供的新类别TVUIKit!现在你可以创建具有焦点行为的自定义视图了!

————

我在苹果开发者论坛上问了同样的问题。苹果员工回答:

对于自定义视图,您必须自己实现聚焦外观。在聚焦更新方法中,您可以执行诸如应用变换和使用UIMotionAffect API等操作。

- (void)didUpdateFocusInContext:(UIFocusUpdateContext *)context withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator {
    if (context.nextFocusedView == self) {
       // handle focus appearance changes
    }
    else {
       // handle unfocused appearance changes
    }
}

我认为为UIView创建一个扩展可以帮助我们将相同的行为应用于任何自定义视图。

也许他们希望我们实现更有趣的方式来向用户展示焦点?这是只在UIImageView上轻松启用此功能的好理由(更别提这个行为还在UIImageView上添加了模拟光效果,这很美丽,但也许仅适用于图像)。


0

如之前的回答所述,没有标准的方法,但是有三个选项可供选择:

  1. (推荐) 实现自定义的焦点行为,类似于 UIImageView 的倾斜效果:

    class MotionView: UIView {
    
     let motionEffectGroup = UIMotionEffectGroup()
    
     override init(frame: CGRect = .zero) {
     super.init(frame:frame)
     self.backgroundColor = .red
     addFocusMotionEffect()
    }
    
    required init?(coder: NSCoder) {
     fatalError("init(coder:) has not been implemented")
    }
    
    func addFocusMotionEffect() {
     let min = CGFloat(-15)
     let max = CGFloat(15)
    
     let xMotion = UIInterpolatingMotionEffect(keyPath: "layer.transform.translation.x", type: .tiltAlongHorizontalAxis)
     xMotion.minimumRelativeValue = min
     xMotion.maximumRelativeValue = max
    
     let yMotion = UIInterpolatingMotionEffect(keyPath: "layer.transform.translation.y", type: .tiltAlongVerticalAxis)
     yMotion.minimumRelativeValue = min
     yMotion.maximumRelativeValue = max
    
     motionEffectGroup.motionEffects = [xMotion,yMotion]
    
     self.addMotionEffect(motionEffectGroup)
    }
    
    func removeFocusMotionEffect() {
     UIView.animate(withDuration: 0.5) {
         self.removeMotionEffect(self.motionEffectGroup)
     }
    }
    
  • UIImageView 设为单元格 contentView 中的主要视图,然后将你的自定义视图追加到 imageViewoverlayContentetView 上,以便随着 UIImageView 一起动画:

    self.imageView.overlayContentView.addSubview(logoView)

  • 从 TVUIKit 添加适当的元素,目前(截至 2022 年)TVCardView 的作用很好。然后将 CardView 添加为子视图到你的 UICollectionViewCell 上方的 UIImageView 或者 TVPosterView 上,它会协调它们的动画。需要将你的自定义视图添加为 TVCardViewcontentView 的子视图。不足之处是,TVCardView 实际上不能有清晰的背景,也不能更改其圆角。

     class CardView: TVCardView{
     override init(frame: CGRect = .zero) {
     super.init(frame:frame)
    
    
     let lbl = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 50))
     lbl.text = "Test Label"
     self.contentView.addSubview(lbl)
     self.cardBackgroundColor = .red
    
    }
    
    required init?(coder: NSCoder) {
     fatalError("init(coder:) has not been implemented")
    }
    
    }
    

  • 网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接