动画/缩放在tvOS聚焦自定义视图



我有一个自定义的UICollectionViewCell在我的tvOS应用程序。它有一个UIImageView和一些UILabel s在它。我可以通过实现UIFocusEnvironment协议而没有任何问题地使单元集中,但是我不知道如何给我的自定义单元集中的外观。(抬高和响应用户在触摸板上的移动)。

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

是否有一种方法可以使tvOS应用(看似)标准焦点外观/行为到我的自定义视图,还是我必须手动完成?

tvOS 12.0+更新:查看Apple在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,这是美丽的,但可能只对图像有意义)。

正如前面的答案所述,没有标准的方法,但是有3个选项供您选择:

  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的主导视图,然后将您的自定义视图附加到imageView's overlayContentetView,以便您的自定义视图将与UIImageView一起动画,如下所示:

    self.imageView.overlayContentView.addSubview(logoView)

  • 从TVUIKit中添加合适的元素,该元素具有行为,目前截至2022年,TVCardView服务器的目的很好。然后将CardView作为UICollectionViewCell的子视图添加到UIImageViewTVPosterView之上,它将与它们协调其动画。您需要将自定义视图添加为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")
    }
    }
    
  • 最新更新