I converted Simon Tilson's answer to swift 3.0 and posted here to save typing for people in the future. Thanks so much for a great solution.
class UIAppleTVMotionEffectGroup : UIMotionEffectGroup{ // size of shift movements let shiftDistance : CGFloat = 10.0 let tiltAngle : CGFloat = CGFloat(M_PI_4) * 0.125 required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } override init() { super.init() // Make horizontal movements shift the centre left and right let xShift = UIInterpolatingMotionEffect(keyPath: "center.x", type: UIInterpolatingMotionEffectType.tiltAlongHorizontalAxis) xShift.minimumRelativeValue = shiftDistance * -1.0 xShift.maximumRelativeValue = shiftDistance let yShift = UIInterpolatingMotionEffect(keyPath: "center.y", type: UIInterpolatingMotionEffectType.tiltAlongVerticalAxis) yShift.minimumRelativeValue = 0.0-shiftDistance yShift.maximumRelativeValue = shiftDistance let xTilt = UIInterpolatingMotionEffect(keyPath: "layer.transform", type: UIInterpolatingMotionEffectType.tiltAlongHorizontalAxis) var transMinimumTiltAboutY = CATransform3DIdentity transMinimumTiltAboutY.m34 = 1.0 / 500.0 transMinimumTiltAboutY = CATransform3DRotate(transMinimumTiltAboutY, tiltAngle * -1.0, 0, 1, 0) var transMaximumTiltAboutY = CATransform3DIdentity transMaximumTiltAboutY.m34 = 1.0 / 500.0 transMaximumTiltAboutY = CATransform3DRotate(transMaximumTiltAboutY, tiltAngle , 0, 1, 0) xTilt.minimumRelativeValue = transMinimumTiltAboutY xTilt.maximumRelativeValue = transMaximumTiltAboutY let yTilt = UIInterpolatingMotionEffect(keyPath: "layer.transform", type: UIInterpolatingMotionEffectType.tiltAlongVerticalAxis) var transMinimumTiltAboutX = CATransform3DIdentity transMinimumTiltAboutX.m34 = 1.0 / 500.0 transMinimumTiltAboutX = CATransform3DRotate(transMinimumTiltAboutX, tiltAngle * -1.0, 1, 0, 0) var transMaximumTiltAboutX = CATransform3DIdentity transMaximumTiltAboutX.m34 = 1.0 / 500.0 transMaximumTiltAboutX = CATransform3DRotate(transMaximumTiltAboutX, tiltAngle , 1, 0, 0) yTilt.minimumRelativeValue = transMinimumTiltAboutX yTilt.maximumRelativeValue = transMaximumTiltAboutX self.motionEffects = [xShift,yShift,xTilt,yTilt] }
}
I added a little pop to the subclass part of UICollectionView. Note the structural wrapper for the static variable
override func didUpdateFocus(in context: UIFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) { struct wrapper { static let s_atvMotionEffect = UIAppleTVMotionEffectGroup() } coordinator.addCoordinatedAnimations( { var scale : CGFloat = 0.0 if self.isFocused { self.addMotionEffect(wrapper.s_atvMotionEffect) scale = 1.2 } else { self.removeMotionEffect(wrapper.s_atvMotionEffect) scale = 1.0 } let transform = CGAffineTransform(scaleX: scale, y: scale) self.layer.setAffineTransform(transform) },completion: nil) }
source share