如何使用自定义视图在集合视图单元格上创建视差焦点效果?如果我使用图像视图,则要设置的属性将是,adjustsImageWhenAncestorFocused
但我的集合视图单元格包含UIView
使用核心图形绘制的自定义内容的子类.
@raulriera的答案很好,但只能在2D中移动单元格.此外,OP要求客观C示例.
出于同样的原因,我也想做这个效果 - 我的UICollectionView包含包含图像和标签的单元格.
我创建了一个UIMotionEffectGroup子类,因为接近Apple TV效果似乎需要四种不同的动作效果.前两个是@raulriera中的平面运动,另外两个是3D旋转.
现在只需要闪亮的环境层.任何接受者?:-)
这是我的动作效果组的代码:
(shiftDistance和tiltAngle常量设置效果的大小.给定的值看起来非常类似于Apple TV效果.)
#import#import "UIAppleTvMotionEffectGroup.h" @implementation UIAppleTvMotionEffectGroup - (id)init { if ((self = [super init]) != nil) { // Size of shift movements CGFloat const shiftDistance = 10.0f; // Make horizontal movements shift the centre left and right UIInterpolatingMotionEffect *xShift = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x" type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis]; xShift.minimumRelativeValue = [NSNumber numberWithFloat: shiftDistance * -1.0f]; xShift.maximumRelativeValue = [NSNumber numberWithFloat: shiftDistance]; // Make vertical movements shift the centre up and down UIInterpolatingMotionEffect *yShift = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.y" type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis]; yShift.minimumRelativeValue = [NSNumber numberWithFloat: shiftDistance * -1.0f]; yShift.maximumRelativeValue = [NSNumber numberWithFloat: shiftDistance]; // Size of tilt movements CGFloat const tiltAngle = M_PI_4 * 0.125; // Now make horizontal movements effect a rotation about the Y axis for side-to-side rotation. UIInterpolatingMotionEffect *xTilt = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"layer.transform" type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis]; // CATransform3D value for minimumRelativeValue CATransform3D transMinimumTiltAboutY = CATransform3DIdentity; transMinimumTiltAboutY.m34 = 1.0 / 500; transMinimumTiltAboutY = CATransform3DRotate(transMinimumTiltAboutY, tiltAngle * -1.0, 0, 1, 0); // CATransform3D value for maximumRelativeValue CATransform3D transMaximumTiltAboutY = CATransform3DIdentity; transMaximumTiltAboutY.m34 = 1.0 / 500; transMaximumTiltAboutY = CATransform3DRotate(transMaximumTiltAboutY, tiltAngle, 0, 1, 0); // Set the transform property boundaries for the interpolation xTilt.minimumRelativeValue = [NSValue valueWithCATransform3D: transMinimumTiltAboutY]; xTilt.maximumRelativeValue = [NSValue valueWithCATransform3D: transMaximumTiltAboutY]; // Now make vertical movements effect a rotation about the X axis for up and down rotation. UIInterpolatingMotionEffect *yTilt = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"layer.transform" type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis]; // CATransform3D value for minimumRelativeValue CATransform3D transMinimumTiltAboutX = CATransform3DIdentity; transMinimumTiltAboutX.m34 = 1.0 / 500; transMinimumTiltAboutX = CATransform3DRotate(transMinimumTiltAboutX, tiltAngle * -1.0, 1, 0, 0); // CATransform3D value for maximumRelativeValue CATransform3D transMaximumTiltAboutX = CATransform3DIdentity; transMaximumTiltAboutX.m34 = 1.0 / 500; transMaximumTiltAboutX = CATransform3DRotate(transMaximumTiltAboutX, tiltAngle, 1, 0, 0); // Set the transform property boundaries for the interpolation yTilt.minimumRelativeValue = [NSValue valueWithCATransform3D: transMinimumTiltAboutX]; yTilt.maximumRelativeValue = [NSValue valueWithCATransform3D: transMaximumTiltAboutX]; // Add all of the motion effects to this group self.motionEffects = @[xShift, yShift, xTilt, yTilt]; [xShift release]; [yShift release]; [xTilt release]; [yTilt release]; } return self; } @end
我在自定义的UICollectionViewCell子类中使用它是这样的:
@implementation MyCollectionViewCell - (void)didUpdateFocusInContext:(UIFocusUpdateContext *)context withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator { // Create a static instance of the motion effect group (could do this anywhere, really, maybe init would be better - we only need one of them.) static UIAppleTVMotionEffectGroup *s_atvMotionEffect = nil; if (s_atvMotionEffect == nil) { s_atvMotionEffect = [[UIAppleTVMotionEffectGroup alloc] init]; } [coordinator addCoordinatedAnimations: ^{ if (self.focused) { [self addMotionEffect: s_atvMotionEffect]; } else { [self removeMotionEffect: s_atvMotionEffect]; } completion: ^{ }]; } @end
您需要做的就是为子视图添加UIMotionEffect.像这样的东西
override func didUpdateFocusInContext(context: UIFocusUpdateContext, withAnimationCoordinator coordinator: UIFocusAnimationCoordinator) { coordinator.addCoordinatedAnimations({ [unowned self] in if self.focused { let verticalMotionEffect = UIInterpolatingMotionEffect(keyPath: "center.y", type: .TiltAlongVerticalAxis) verticalMotionEffect.minimumRelativeValue = -10 verticalMotionEffect.maximumRelativeValue = 10 let horizontalMotionEffect = UIInterpolatingMotionEffect(keyPath: "center.x", type: .TiltAlongHorizontalAxis) horizontalMotionEffect.minimumRelativeValue = -10 horizontalMotionEffect.maximumRelativeValue = 10 let motionEffectGroup = UIMotionEffectGroup() motionEffectGroup.motionEffects = [horizontalMotionEffect, verticalMotionEffect] yourView.addMotionEffect(motionEffectGroup) } else { // Remove the effect here } }, completion: nil) }