当用户在触摸板上稍微移动时,tvOS主菜单上的行为是在聚焦时必须具有整个单元格标题。
我有:imageView.adjustsImageWhenAncestorFocused = true
,图片倾斜,但只在单元格内。细胞本身不会移动。
如何让细胞倾斜移动?
编辑:
所以我在我的imageView上将clipsToBounds
设置为true
,因为有些单元格是圆形的。所以这就是削减倾斜变换。我需要圆形单元格,所以我可能必须自己创建动画。
答案 0 :(得分:1)
我最终做的是在方形单元格上使用默认焦点动画,并在圆形单元格中使用自定义动画。它并不完全相同 - 它没有聚光灯效果,也没有倾斜。它只是左右移动。倾斜不会太难以放入 - 不确定如何做到聚光灯。
这是我的UICollectionViewCell子类解决方案:
import UIKit
class VevoTVCell: UICollectionViewCell {
private struct Constants {
static let ShadowBlur = CGFloat(40.0)
static let FocusedOverlayAlpha = CGFloat(0.0)
static let UnfocusedOverlayAlpha = CGFloat(0.3)
static let FocusedLabelAlpha = CGFloat(1.0)
static let UnfocusedLabelAlpha = CGFloat(0.8)
static let FocusedScaleTransform = CGFloat(1.15)
}
var imageView: UIImageView!
var overlay: UIView!
var titleLabel: UILabel!
var subLabel: UILabel!
var isRounded: Bool = false {
didSet {
if (isRounded) {
imageView.layer.cornerRadius = bounds.height/2
overlay.layer.cornerRadius = bounds.height/2
imageView.adjustsImageWhenAncestorFocused = false
imageView.clipsToBounds = true
} else {
imageView.layer.cornerRadius = 0
overlay.layer.cornerRadius = 0
imageView.adjustsImageWhenAncestorFocused = true
imageView.clipsToBounds = false
}
setNeedsLayout()
}
}
private lazy var panGesture: UIPanGestureRecognizer = {
let pan = UIPanGestureRecognizer(target: self,
action: Selector("viewPanned:")
)
pan.cancelsTouchesInView = false
return pan
}()
override init(frame: CGRect) {
super.init(frame: frame)
clipsToBounds = false
// Set up UI elements
imageView = UIImageView(frame: bounds)
imageView.contentMode = UIViewContentMode.ScaleAspectFill
imageView.adjustsImageWhenAncestorFocused = true
contentView.addSubview(imageView)
titleLabel = UILabel(frame: CGRectZero)
contentView.addSubview(titleLabel)
subLabel = UILabel(frame: CGRectZero)
contentView.addSubview(subLabel)
overlay = UIView(frame: bounds)
overlay.backgroundColor = UIColor.blackColor()
overlay.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
overlay.alpha = Constants.UnfocusedOverlayAlpha
imageView.addSubview(overlay)
layer.shadowColor = UIColor.blackColor().CGColor
layer.shadowRadius = Constants.ShadowBlur
unfocusItem()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
// MARK: Focus
override func didUpdateFocusInContext(context: UIFocusUpdateContext, withAnimationCoordinator coordinator: UIFocusAnimationCoordinator) {
super.didUpdateFocusInContext(context, withAnimationCoordinator: coordinator)
coordinator.addCoordinatedAnimations({ () -> Void in
if self.focused {
self.focusItem()
} else {
self.unfocusItem()
}
}) { () -> Void in
}
}
func focusItem() {
superview?.bringSubviewToFront(self)
// -- use custom focus animation for rounded cells (can't use default because we have to clip imageView)
if (isRounded) {
// -- (need slight delay otherwise jumps because of other focus animation
let dispatchTime: dispatch_time_t = dispatch_time(DISPATCH_TIME_NOW, Int64(0.1 * Double(NSEC_PER_SEC)))
dispatch_after(dispatchTime, dispatch_get_main_queue(), {
print(" ---- adding pan")
self.contentView.addGestureRecognizer(self.panGesture)
})
//self.overlay.frame = bounds
self.overlay.alpha = Constants.FocusedOverlayAlpha
self.titleLabel.alpha = Constants.FocusedLabelAlpha
self.subLabel.alpha = Constants.FocusedLabelAlpha
let b = CATransform3DMakeScale(Constants.FocusedScaleTransform, Constants.FocusedScaleTransform, 1)
self.layer.transform = b
self.layer.shadowOpacity = 0.6
} else {
imageView.clipsToBounds = false
}
}
func unfocusItem() {
superview?.sendSubviewToBack(self)
if (isRounded) {
contentView.removeGestureRecognizer(panGesture)
//self.overlay.frame = bounds
self.overlay.alpha = Constants.UnfocusedOverlayAlpha
self.titleLabel.alpha = Constants.UnfocusedLabelAlpha
self.subLabel.alpha = Constants.UnfocusedLabelAlpha
layer.transform = CATransform3DIdentity
self.imageView.transform = CGAffineTransformMakeTranslation(1.0,1.0)
self.layer.shadowOpacity = 0.0
} else {
imageView.clipsToBounds = true
}
}
// MARK: Focus - Panning (Custom focus animation for rounded cells)
private var initialPanPosition: CGPoint?
func viewPanned(pan: UIPanGestureRecognizer) {
switch pan.state {
case .Began:
print(" ---- PAN -- BEGAN")
initialPanPosition = pan.locationInView(contentView)
case .Changed:
print(" ---- PAN -- CHANGED")
if let initialPanPosition = initialPanPosition {
let currentPosition = pan.locationInView(contentView)
let diff = CGPoint(
x: currentPosition.x - initialPanPosition.x,
y: currentPosition.y - initialPanPosition.y
)
let parallaxCoefficientX = 1 / self.contentView.frame.width * 10
let parallaxCoefficientY = 1 / self.contentView.frame.height * 10
self.imageView.transform = CGAffineTransformMakeTranslation(
diff.x * parallaxCoefficientX,
diff.y * parallaxCoefficientY
)
}
default:
// .Canceled, .Failed, etc.. return the view to it's default state.
print(" ---- PAN -- DEFAULT")
UIView.animateWithDuration(0.3,
delay: 0,
usingSpringWithDamping: 0.8,
initialSpringVelocity: 0,
options: .BeginFromCurrentState,
animations: { () -> Void in
self.imageView.transform = CGAffineTransformMakeTranslation(1.0,1.0)
},
completion: nil)
}
}
}
我使用了来自http://eeeee.io/2015/11/13/apple-tv-parallax-gesture.html
的代码示例我需要修复此代码的一件事是,当您最初关注某个单元格时,不会调用UIPanGestureRecognizer方法viewPanned
。用户必须将手指从遥控器上移开,然后调用viewPanned
。此外,一旦调用了单元格viewPanned
,即使您专注于另一个单元格然后重新聚焦在该单元格上,它也会起作用。这很奇怪。