我的视图控制器中的iOS 7视差效果


112

我正在使用Objective-C开发适用于iOS 7的应用程序。我的应用程序中有一个带有几个按钮和漂亮背景图像的屏幕。(这是一个简单的xib,UIButtons位于顶部UIImageView。)

我在想,如果这些按钮具有iOS 7主屏幕的视差效果,那就太酷了,因此,如果倾斜手机,您会看到背景。

如何在自己的应用中实现这种效果?



要迅速进行操作,请尝试:github.com/ArvindPrakashJoshi/AJParallaxEffect
Arvind

Answers:


273

在iOS 7中,Apple引入UIMotionEffect了添加与用户设备方向相关的Motion效果。例如,要在主屏幕上模拟视差效果,只需使用几行代码,就可以使用此处此处UIInterpolationMotionEffect说明的子类。

目标-C

// Set vertical effect
UIInterpolatingMotionEffect *verticalMotionEffect = 
  [[UIInterpolatingMotionEffect alloc] 
  initWithKeyPath:@"center.y"
             type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis];
verticalMotionEffect.minimumRelativeValue = @(-10);
verticalMotionEffect.maximumRelativeValue = @(10);

// Set horizontal effect 
UIInterpolatingMotionEffect *horizontalMotionEffect = 
  [[UIInterpolatingMotionEffect alloc] 
  initWithKeyPath:@"center.x"     
             type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis];
horizontalMotionEffect.minimumRelativeValue = @(-10);
horizontalMotionEffect.maximumRelativeValue = @(10);

// Create group to combine both
UIMotionEffectGroup *group = [UIMotionEffectGroup new];
group.motionEffects = @[horizontalMotionEffect, verticalMotionEffect];

// Add both effects to your view
[myBackgroundView addMotionEffect:group];

斯威夫特(感谢@Lucas):

// Set vertical effect
let verticalMotionEffect = UIInterpolatingMotionEffect(keyPath: "center.y",
type: .TiltAlongVerticalAxis)
verticalMotionEffect.minimumRelativeValue = -10
verticalMotionEffect.maximumRelativeValue = 10

// Set horizontal effect
let horizontalMotionEffect = UIInterpolatingMotionEffect(keyPath: "center.x",
    type: .TiltAlongHorizontalAxis)
horizontalMotionEffect.minimumRelativeValue = -10
horizontalMotionEffect.maximumRelativeValue = 10

// Create group to combine both
let group = UIMotionEffectGroup()
group.motionEffects = [horizontalMotionEffect, verticalMotionEffect]

// Add both effects to your view
myBackgroundView.addMotionEffect(group)

此外,您可以找到一堆库来简化此操作或将此功能添加到较旧的iOS版本:


2
NGAParallaxMotion适用于iOS 7+,而不适用于较旧的iOS版本。它为UIView提供了一个类别,使您可以设置.parallaxIntensity值,并用一行代码设置UIMotionEffect参数。
Dan Fabulich

2
谢谢!我已经更新了答案,以包括受支持的版本和要求。
veducm

1
实际上,您想将运动效果添加到背景视图,而不是前视图。但是除此之外,此代码还不错!谢谢。
gstroup

1
有谁知道如何检查用户是否禁用了效果?stackoverflow.com/questions/19132000/…–
Eric

3
@gstroup实际上,在主屏幕上,前景和背景都在移动。但是,如果只选择一层来应用视差效果,我同意背景可能是最好的。
Rubberduck

16

万一有人偷懒,可以迅速翻译。如果您觉得有用,请投票@veducm 回答

@IBOutlet var background : UIImageView!

func parallaxEffectOnBackground() {
    let relativeMotionValue = 50
    var verticalMotionEffect : UIInterpolatingMotionEffect = UIInterpolatingMotionEffect(keyPath: "center.y",
        type: .TiltAlongVerticalAxis)
    verticalMotionEffect.minimumRelativeValue = -relativeMotionValue
    verticalMotionEffect.maximumRelativeValue = relativeMotionValue

    var horizontalMotionEffect : UIInterpolatingMotionEffect = UIInterpolatingMotionEffect(keyPath: "center.x",
        type: .TiltAlongHorizontalAxis)
    horizontalMotionEffect.minimumRelativeValue = -relativeMotionValue
    horizontalMotionEffect.maximumRelativeValue = relativeMotionValue

    var group : UIMotionEffectGroup = UIMotionEffectGroup()
    group.motionEffects = [horizontalMotionEffect, verticalMotionEffect]

    self.background.addMotionEffect(group)
}

谢谢@卢卡斯!我更新了答案,也包含了快速示例。它基于这一点。随时查看它并进行任何必要的更改。
veducm 2015年

7

@veducm的解决方案可以短一些。如果分别添加x和y轴motionEffects,则UIMotionEffectGroup的x和y运动已过时。

UIInterpolatingMotionEffect *motionEffect;
motionEffect = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x"
                                                               type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis];
motionEffect.minimumRelativeValue = @(-25);
motionEffect.maximumRelativeValue = @(25);
[bgView addMotionEffect:motionEffect];

motionEffect = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.y"
                                                               type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis];
motionEffect.minimumRelativeValue = @(-25);
motionEffect.maximumRelativeValue = @(25);
[bgView addMotionEffect:motionEffect];

2
正如任何人使用此简化版本时一样,第一个动作效果需要具有typeof,UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis而不是UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis所布置的代码中的
样子

1
@BooHoo将它们作为一个组添加已过时了吗?你在哪里看到的?截至撰写本文时,Apple文档还没有关于它过时的信息。将它们分组的整个目的是为了提高性能。该组中的所有效果仅渲染一次。当您分别应用它们时,必须分别渲染它们。如果我记错了,请随时纠正我(并指向我的Apple文档。)
David Lari

6
const static CGFloat kCustomIOS7MotionEffectExtent = 10.0; 

- (void)applyMotionEffects:(UIView *YOUR_VIEW) {
     if (NSClassFromString(@"UIInterpolatingMotionEffect")) {
         UIInterpolatingMotionEffect *horizontalEffect = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x"
                                                                                                        type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis];
         horizontalEffect.minimumRelativeValue = @(-kCustomIOS7MotionEffectExtent);
         horizontalEffect.maximumRelativeValue = @( kCustomIOS7MotionEffectExtent);
         UIInterpolatingMotionEffect *verticalEffect = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.y"
                                                                                                      type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis];
         verticalEffect.minimumRelativeValue = @(-kCustomIOS7MotionEffectExtent);
         verticalEffect.maximumRelativeValue = @( kCustomIOS7MotionEffectExtent);
         UIMotionEffectGroup *motionEffectGroup = [[UIMotionEffectGroup alloc] init];
         motionEffectGroup.motionEffects = @[horizontalEffect, verticalEffect]; 
         [YOUR_VIEW addMotionEffect:motionEffectGroup];
     }
}

1
@Rob根据您的建议更新了答案
damithH 2014年

5

这是一个易于整合对iOs7 +的影响的类别:

NSString *const centerX = @"center.x";
NSString *const centerY = @"center.y";

//#define IS_OS_7_OR_LATER    ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)

@implementation UIView (TLMotionEffect)

- (void)addCenterMotionEffectsXYWithOffset:(CGFloat)offset {

//    if(!IS_OS_7_OR_LATER) return;
    if(floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1) return;

    UIInterpolatingMotionEffect *xAxis;
    UIInterpolatingMotionEffect *yAxis;

    xAxis = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:centerX type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis];
    xAxis.maximumRelativeValue = @(offset);
    xAxis.minimumRelativeValue = @(-offset);

    yAxis = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:centerY type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis];
    yAxis.minimumRelativeValue = @(-offset);
    yAxis.maximumRelativeValue = @(offset);

    UIMotionEffectGroup *group = [[UIMotionEffectGroup alloc] init];
    group.motionEffects = @[xAxis, yAxis];

    [self addMotionEffect:group];
}

@end

https://github.com/jvenegas/TLMotionEffect


1
尽管此链接可以回答问题,但最好在此处包括答案的基本部分,并提供链接以供参考。如果链接的页面发生更改,仅链接的答案可能会失效。
Maciej Swic 2014年

在此处集成整个github项目将非常困难
Bejil 2014年

1
您不必带整个项目,而只需像我通过编辑答案所展示的那样,是必不可少的部分。这样一来,当Github崩溃,您拉回购协议或天空掉下时,代码就会始终存在。
Maciej Swic 2014年


3

这将帮助希望为tableView或collectionView实现视差的人。

  • 首先,为表格视图创建单元格,然后将图像视图放入其中。

  • 将图像高度设置为略高于单元格高度。如果像元高度= 160,则使图像高度为200(要产生视差效果,可以相应地更改它)

  • 将这两个变量放入viewController或扩展tableView委托的任何类中

let imageHeight:CGFloat = 150.0
let OffsetSpeed: CGFloat = 25.0
  • 在同一个类中添加以下代码
 func scrollViewDidScroll(scrollView: UIScrollView) {
    //  print("inside scroll")

    if let visibleCells = seriesTabelView.visibleCells as? [SeriesTableViewCell] {
        for parallaxCell in visibleCells {
            var yOffset = ((seriesTabelView.contentOffset.y - parallaxCell.frame.origin.y) / imageHeight) * OffsetSpeedTwo
            parallaxCell.offset(CGPointMake(0.0, yOffset))
        }
    }
}
  • 其中seriesTabelView是我的UItableview

  • 现在让我们转到该tableView的单元格并添加以下代码

func offset(offset: CGPoint) {
        posterImage.frame = CGRectOffset(self.posterImage.bounds, offset.x, offset.y)
    }
  • 是posterImage是我的UIImageView

如果要将其实现到collectionView,只需将tableView vairable更改为您的collectionView变量

就是这样。我不确定这是否是最好的方法。但这对我有用。希望它也对您有用。让我知道是否有问题


2

真的很容易做到,为什么要引用复杂的代码。去尝试一下。加工

在imageview上查看与图像视图大小完全相同的视图。默认情况下,视图集0的alpha。

//MARK: Scroll View Delegate methods
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{

NSLog(@"X: %f Y: %f",scrollView.contentOffset.x,scrollView.contentOffset.y);

CGFloat scrollY = _mainScrollView.contentOffset.y;
CGFloat height = _alphaView.frame.size.height;

CGFloat alphaMonitor = scrollY/height;

_alphaView.alpha = alphaMonitor;
}

-1

快速翻译:

// Set vertical effect
let verticalMotionEffect = UIInterpolatingMotionEffect(keyPath: "center.y", type: .TiltAlongVerticalAxis)
verticalMotionEffect.minimumRelativeValue = -value
verticalMotionEffect.maximumRelativeValue = value

// Set vertical effect
let horizontalMotionEffect = UIInterpolatingMotionEffect(keyPath: "center.x", type: .TiltAlongHorizontalAxis)
verticalMotionEffect.minimumRelativeValue = -value
verticalMotionEffect.maximumRelativeValue = value

let group = UIMotionEffectGroup()
group.motionEffects = [horizontalMotionEffect, verticalMotionEffect]
self.motionEffect = group
self.addMotionEffect(group)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.