我在之前的一篇博客中《iOS UIView動畫詳解(Swift)》講解了使用Swift來實現UIView類下面提供的多種動畫效果,如位置動畫、旋轉動畫、縮放動畫、顏色動畫、透明度動畫等等。為了這個題目的完整性,今天我使用Objective-C來完全重寫以上的所有的動畫。項目案例已經上傳至:https://github.com/chenyufeng1991/iOS-UIView-Animation 中的Animation-OC文件夾下,另一個目錄下則是Swift實現的動畫。
(1)位置動畫
PositionAnimation可以實現View的移動,最簡單的就是X軸,Y軸的移動。這裡實現幾個小方塊的移動。
#import "PositionViewController.h" @interface PositionViewController () @property (weak, nonatomic) IBOutlet UIView *redSquare; @property (weak, nonatomic) IBOutlet UIView *greenSquare; @end @implementation PositionViewController - (void)viewDidLoad { [super viewDidLoad]; } - (void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:animated]; [UIView animateWithDuration:2 animations:^{ self.redSquare.frame = CGRectMake(self.redSquare.frame.origin.x, 400, self.redSquare.bounds.size.width, self.redSquare.bounds.size.height); self.greenSquare.frame = CGRectMake(200, 500, self.greenSquare.bounds.size.width, self.greenSquare.bounds.size.height); }]; } @end
透明度動畫可以讓某個View的透明度在0-1之間改變。透明度為0表示全透明,看不見了。透明度為1表示和正常情況下一樣。
#import "OpacityViewController.h" @interface OpacityViewController () @property (weak, nonatomic) IBOutlet UIView *redSquare; @end @implementation OpacityViewController - (void)viewDidLoad { [super viewDidLoad]; } - (void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:animated]; [UIView animateWithDuration:2 animations:^{ self.redSquare.alpha = 0.3; }]; } @end
縮放動畫可以讓一個View的大小發生改變,按比例的放大縮小。
#import "ScaleViewController.h" @interface ScaleViewController () @property (weak, nonatomic) IBOutlet UIView *redSquare; @end @implementation ScaleViewController - (void)viewDidLoad { [super viewDidLoad]; } - (void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:animated]; [UIView animateWithDuration:2 animations:^{ //寬高縮放比; self.redSquare.transform = CGAffineTransformMakeScale(2, 3); }]; } @end
顏色動畫可以讓一個View在一個時間間隔內發生顏色的漸變,進行顏色的過渡。
#import "ColorViewController.h" @interface ColorViewController () @property (weak, nonatomic) IBOutlet UIView *greenSquare; @end @implementation ColorViewController - (void)viewDidLoad { [super viewDidLoad]; } - (void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:animated]; [UIView animateWithDuration:2 animations:^{ //寬高縮放比; self.greenSquare.backgroundColor = [UIColor brownColor]; }]; } @end
(5)旋轉動畫
可以讓某個View繞圓點進行旋轉。
#import "RotationViewController.h" @interface RotationViewController () @property (weak, nonatomic) IBOutlet UIView *greenSquare;//旋轉一次; @property (weak, nonatomic) IBOutlet UIView *redSquare;//旋轉無數次; @end @implementation RotationViewController - (void)viewDidLoad { [super viewDidLoad]; } - (void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:animated]; [self spinGreenSquare]; [self spinRedSquare]; } - (void)spinGreenSquare{ [UIView animateWithDuration:2 animations:^{ self.greenSquare.transform = CGAffineTransformRotate(self.greenSquare.transform, M_PI);//一個PI,180度; } completion:^(BOOL finished) { }]; } - (void)spinRedSquare{ [UIView animateWithDuration:1 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{ self.redSquare.transform = CGAffineTransformRotate(self.redSquare.transform, 360);//一個PI,180度; } completion:^(BOOL finished) { [self spinRedSquare]; }]; } @end
該動畫可以讓某個動畫過程反復執行。
#import "RepeatViewController.h" @interface RepeatViewController () @property (weak, nonatomic) IBOutlet UIView *greenSquare; @property (weak, nonatomic) IBOutlet UIView *redSquare; @end @implementation RepeatViewController - (void)viewDidLoad { [super viewDidLoad]; } - (void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:animated]; [UIView animateWithDuration:2 delay:0 options:UIViewAnimationOptionRepeat animations:^{ self.greenSquare.frame = CGRectMake(250, self.greenSquare.frame.origin.y, self.greenSquare.frame.size.width, self.greenSquare.frame.size.height); } completion:^(BOOL finished) { }]; [UIView animateWithDuration:2 delay:0 options:UIViewAnimationOptionRepeat|UIViewAnimationOptionAutoreverse animations:^{ self.redSquare.frame = CGRectMake(250, self.redSquare.frame.origin.y, self.redSquare.frame.size.width, self.redSquare.frame.size.height); } completion:^(BOOL finished) { }]; } @end
這裡主要使用了貝塞爾曲線的效果來改變View動畫的速率效果。大家可以實踐一下。
#import "EasingViewController.h" @interface EasingViewController () @property (weak, nonatomic) IBOutlet UIView *greenSquare; @property (weak, nonatomic) IBOutlet UIView *redSquare; @end @implementation EasingViewController - (void)viewDidLoad { [super viewDidLoad]; } - (void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:animated]; //主要是設置options這個參數; [UIView animateWithDuration:2 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{ self.greenSquare.frame = CGRectMake(250, self.greenSquare.frame.origin.y, self.greenSquare.frame.size.width, self.greenSquare.frame.size.height); } completion:nil]; [UIView animateWithDuration:2 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{ self.redSquare.frame = CGRectMake(250, self.redSquare.frame.origin.y, self.redSquare.frame.size.width, self.redSquare.frame.size.height); } completion:nil]; } @end
該動畫執行過程中類似彈簧的真實效果,你可以設置彈簧的阻尼和初始速度來達到非常逼真的彈簧抖動。
#import "SpringViewController.h" @interface SpringViewController () @property (weak, nonatomic) IBOutlet UIView *greenSquare; @property (weak, nonatomic) IBOutlet UIView *redSquare; @end @implementation SpringViewController - (void)viewDidLoad { [super viewDidLoad]; } - (void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:animated]; //通過設置參數即可改變不同的狀態; [UIView animateWithDuration:2 delay:0.5 usingSpringWithDamping:0.2 initialSpringVelocity:0 options:UIViewAnimationOptionTransitionNone animations:^{ self.greenSquare.frame = CGRectMake(250, self.greenSquare.frame.origin.y, self.greenSquare.frame.size.width, self.greenSquare.frame.size.height); } completion:nil]; [UIView animateWithDuration:2 delay:0.5 usingSpringWithDamping:0.2 initialSpringVelocity:1 options:UIViewAnimationOptionTransitionNone animations:^{ self.redSquare.frame = CGRectMake(250, self.redSquare.frame.origin.y, self.redSquare.frame.size.width, self.redSquare.frame.size.height); } completion:nil]; } @end
在我們實際的需求中,我們可能需要讓圖片在移動旋轉之前就處於左轉90度、右轉90度、旋轉180度的狀態,然後在此基礎上再進行其他的動畫。實現如下:
#import "ImageRotationViewController.h" #define kScreenWidth [[UIScreen mainScreen] bounds].size.width #define kScreenHeight [[UIScreen mainScreen] bounds].size.height /** * 在該示例中對UIImage進行旋轉,注意不是對UIImageView旋轉,這可以滿足更多自定義的需求; */ @interface ImageRotationViewController () @end @implementation ImageRotationViewController - (void)viewDidLoad { [super viewDidLoad]; /** UIImageOrientationUp, // default orientation UIImageOrientationDown, // 180 deg rotation UIImageOrientationLeft, // 90 deg CCW UIImageOrientationRight, // 90 deg CW UIImageOrientationUpMirrored, // as above but image mirrored along other axis. horizontal flip UIImageOrientationDownMirrored, // horizontal flip UIImageOrientationLeftMirrored, // vertical flip UIImageOrientationRightMirrored, // vertical flip */ UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, kScreenHeight / 2, 80, kScreenWidth)]; UIImage *image = [UIImage imageNamed:@"1"]; /** * 以下方法讓一張圖片一開始就處於旋轉狀態,而不是正放的狀態;注意是對UIImage的操作,而不是對UIimageView控件的操作;最後再把image放入控件即可。 */ UIImage *imageRotate = [UIImage imageWithCGImage:image.CGImage scale:1 orientation:UIImageOrientationLeft]; [imageView setImage:imageRotate]; [self.view addSubview:imageView]; [UIView animateWithDuration:2 animations:^{ imageView.transform = CGAffineTransformRotate(imageView.transform, M_PI_2); imageView.frame = CGRectMake(0, 64, kScreenWidth, 80); }]; } @end