[TOC]
UIMotionEffect(运动效果)
UIMotionEffect是iOS7.0推出的API。
作用:根据设备运动角度来改变对应UIView的属性,从而实现动态效果。
API介绍
@interface UIMotionEffect : NSObject <NSCopying, NSCoding>
@interface UIInterpolatingMotionEffect : UIMotionEffect
@interface UIMotionEffectGroup : UIMotionEffect
UIMotionEffect 抽象类;直接继承自NSObject,支持了NSCopying和NSCoding protocol。
只提供了一个子类必须override的方法。
这个方法的输入参数只有一个,观察者角度的偏移。
这个方法的输出则是一个灵活的NSDictionary对象,里面包含了最终影响视差效果的各项属性和对应的值。
@interface UIMotionEffect : NSObject <NSCopying, NSCoding>
- (instancetype)init;
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder;
//子类重写的方法:
- (nullable NSDictionary<NSString *, id> *)keyPathsAndRelativeValuesForViewerOffset:(UIOffset)viewerOffset;
//e.g.
return value: @{ @"center": [NSValue valueFromCGPoint:CGPointMake(3.4, 1.2)],
@"layer.shadowOffset.x": @(-1.1)
}
@end
实际操作中,我们主要使用子类:
1.系统提供的子类
2.自定义子类
//---------------------------------------------------------------------
@interface UIInterpolatingMotionEffect : UIMotionEffect
- (instancetype)initWithKeyPath:(NSString *)keyPath type:(UIInterpolatingMotionEffectType)type;
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder;
//有4个property:
@property (readonly, nonatomic) NSString *keyPath; //左右翻转屏幕将要影响到的属性,比如center.x
@property (readonly, nonatomic) UIInterpolatingMotionEffectType type; //观察者视角,也就是屏幕倾斜的方式
typedef NS_ENUM(NSInteger, UIInterpolatingMotionEffectType) {
UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis, //水平
UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis //垂直
};
@property (nullable, strong, nonatomic) id minimumRelativeValue; //keyPath对应的值的变化范围 最小值
@property (nullable, strong, nonatomic) id maximumRelativeValue; //keyPath对应的值的变化范围 最大值
@end
//---------------------------------------------------------------------
@interface UIMotionEffectGroup : UIMotionEffect
@property (nullable, copy, nonatomic) NSArray<__kindof UIMotionEffect *> *motionEffects;
@end
实践
1.直接使用子类:UIInterpolatingMotionEffect
self.imgv = [[UIImageView alloc] initWithFrame:CGRectMake(10, 100, 300, 300)];
self.imgv.backgroundColor = [UIColor orangeColor];
self.imgv.image = [UIImage imageNamed:@"pikaqiu.jpg"];
[self.view addSubview:self.imgv];
//直接使用子类:UIInterpolatingMotionEffect
UIInterpolatingMotionEffect * xEffect = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x" type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis];
xEffect.minimumRelativeValue = [NSNumber numberWithFloat:-40.0];
xEffect.maximumRelativeValue = [NSNumber numberWithFloat:40.0];
[self.view addMotionEffect:xEffect];
2.自定义类: 继承UIMotionEffect
//重写这个方法
- (NSDictionary *)keyPathsAndRelativeValuesForViewerOffset:(UIOffset)viewerOffset
{
CGFloat originalOffset = viewerOffset.horizontal ;
CGFloat targetOffset = 512 * originalOffset;
return @{@"center.y": @(targetOffset)};
}
Swift
public class MyMotionEffect:UIMotionEffect {
override public func keyPathsAndRelativeValuesForViewerOffset(viewerOffset: UIOffset) -> [String : AnyObject]? {
//打印设备水平角度
NSLog("x:%f,y:%f", viewerOffset.horizontal,viewerOffset.vertical)
//返回对象是一个字典类型,key是修改UIView的键路径,value是修改的值
return ["center.y":fabs(viewerOffset.horizontal*1000)]
}
}
//e.g.
myView = UIView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
myView.backgroundColor = UIColor.redColor()
view.addSubview(myView)
myMotionEffect = MyMotionEffect()
myView.addMotionEffect(myMotionEffect)