当前位置:  开发笔记 > 编程语言 > 正文

在UICollectionViewCell上创建视差焦点效果

如何解决《在UICollectionViewCell上创建视差焦点效果》经验,为你挑选了2个好方法。

如何使用自定义视图在集合视图单元格上创建视差焦点效果?如果我使用图像视图,则要设置的属性将是,adjustsImageWhenAncestorFocused但我的集合视图单元格包含UIView使用核心图形绘制的自定义内容的子类.



1> Simon Tillso..:

@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


原来如此.那里的问题似乎是az排序问题.看起来图像和文本被设置在几乎相同的z位置,因此图像纹理在某些角度遮挡文本.解决方案是将z中的转换应用于文本对象,使其保持在图像上方.

2> raulriera..:

您需要做的就是为子视图添加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)
}

推荐阅读
echo7111436
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有