版本記錄
版本號 | 時間 |
---|---|
V1.0 | 2017.12.02 |
前言
適當的動畫展示可以提高APP的炫酷效果,提高用戶忠誠度和粘性,但是在動畫集成過程中掌唾,不僅可能帶來性能問題,還會引起其他交互中的問題忿磅,這些都是開發(fā)人員在開發(fā)過程中比較耗時和需要注意的問題糯彬。接下來這幾篇我就說一下做各種動畫時碰到的各種性能等各種坑和問題。
問題概述
利用UIKit的UIView做動畫的時候葱她,當控件在運動的時候是不允許交互的撩扒。這一篇我們就說一下這個問題,配合具體的Demo吨些,見GitHub - 刀客傳奇却舀。
問題解決
下面我們就看一下這個問題,先寫一個動畫锤灿,具體代碼如下所示挽拔。
1. ViewController.m
#import "ViewController.h"
#import "JJGiftView.h"
@interface ViewController ()
@property (nonatomic, strong) JJGiftView *giftView;
@end
@implementation ViewController
#pragma mark - Override Base Function
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor lightGrayColor];
self.giftView = [[JJGiftView alloc] init];
self.giftView.backgroundColor = [UIColor redColor];
[self.view addSubview:self.giftView];
[self.giftView startAnimation];
}
@end
2. JJGiftView.h
#import <UIKit/UIKit.h>
@interface JJGiftView : UIView
- (void)startAnimation;
@end
3. JJGiftView.m
#import "JJGiftView.h"
@interface JJGiftView()
@property (nonatomic, strong) UIImageView *testImageView;
@property (nonatomic, assign) CGFloat giftWidth;
@property (nonatomic, assign) CGFloat giftHeight;
@property (nonatomic, assign) CGFloat startXRatio;
@property (nonatomic, assign) CGFloat startYRatio;
@property (nonatomic, assign) CGFloat pauseXRatio;
@property (nonatomic, assign) CGFloat pauseYRatio;
@property (nonatomic, assign) CGFloat endXRatio;
@property (nonatomic, assign) CGFloat endYRatio;
@property (nonatomic, assign) CGFloat startDuration;
@property (nonatomic, assign) CGFloat endDuration;
@property (nonatomic, assign) CGFloat pauseDuration;
@end
@implementation JJGiftView
#pragma mark - Override Base Function
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(imageViewDidTapped:)];
[self addGestureRecognizer:tapGesture];
}
return self;
}
#pragma mark - Object Private Function
- (void)startAnimation
{
self.giftWidth = 100.0;
self.giftHeight = 100.0;
self.startXRatio = 0.2;
self.startYRatio = 0.1;
self.pauseXRatio = 0.5;
self.pauseYRatio = 0.5;
self.endXRatio = 0.8;
self.endYRatio = 1.0;
self.startDuration = 5;
self.pauseDuration = 1;
self.endDuration = 5;
CGSize screenSize = [UIScreen mainScreen].bounds.size;
//其實位置
self.frame = CGRectMake(self.startXRatio * screenSize.width, self.startYRatio * screenSize.height, self.giftWidth, self.giftHeight);
[UIView animateWithDuration:self.startDuration delay:0 options:UIViewAnimationOptionAllowUserInteraction animations:^{
self.frame = CGRectMake(self.pauseXRatio * screenSize.width, self.pauseYRatio * screenSize.height, self.giftWidth, self.giftHeight);
} completion:^(BOOL finished) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(self.pauseDuration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[UIView animateWithDuration:self.endDuration delay:0 options:UIViewAnimationOptionAllowUserInteraction animations:^{
self.frame = CGRectMake(self.endXRatio * screenSize.width, self.endYRatio * screenSize.height, self.giftWidth, self.giftHeight);
} completion:^(BOOL finished) {
NSLog(@"動畫結束了");
}];
});
}];
}
#pragma mark - Action && Notification
- (void)imageViewDidTapped:(UITapGestureRecognizer *)tapGesture
{
CGFloat redValue = arc4random_uniform(255)/255.0;
CGFloat greenValue = arc4random_uniform(255)/255.0;
CGFloat blueValue = arc4random_uniform(255)/255.0;
self.backgroundColor = [UIColor colorWithRed:redValue green:greenValue blue:blueValue alpha:1.0];
}
@end
下面我們就看一下效果。
這里但校,我們就發(fā)現個問題螃诅,盡管給視圖我們添加了手勢,并且做UIView動畫的時候状囱,option使用了枚舉值UIViewAnimationOptionAllowUserInteraction
术裸,結果是只有在動畫在中間停止的附近時,點擊才會響應手勢亭枷,視圖變隨機色袭艺。
這是什么原因呢?
其實主要原因是叨粘,動畫執(zhí)行的過程中猾编,是layer在做動畫瘤睹,我們點擊的手勢其實已經透過本身傳遞給父視圖了,我們這個自定義view無法響應手勢答倡,解決方式就是重寫hitTest方法轰传,留住對手勢的點擊響應。
下面我們就改進一下瘪撇。
// 在自定義方法中重寫下面這個方法
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
CGPoint locationPoint = [self.layer convertPoint:point toLayer:self.layer.presentationLayer];
CALayer *layer = self.layer.presentationLayer;
if(CGRectContainsPoint(layer.bounds, locationPoint)){
return self;
}
if (!self.layer.presentationLayer) {
return [super hitTest:point withEvent:event];
}
return nil;
}
這樣點擊視圖获茬,就可以響應手勢。
問題效果
下面我們運行看一下效果倔既,
后記
未完恕曲,待續(xù)~~~