UIKit實(shí)現(xiàn)的動(dòng)畫

沒有時(shí)間延遲的動(dòng)畫

__weak typeof(self) weakSelf = self;
[UIView animateWithDuration:0.8f animations:^{
    //這里對(duì)視圖的屬性進(jìn)行修改
    weakSelf.imageView1.center = center1;
} completion:^(BOOL finished) {
    
}];

可以設(shè)置時(shí)間延遲的動(dòng)畫

[UIView animateWithDuration:0.8 delay:0.2 options:UIViewAnimationOptionRepeat|UIViewAnimationOptionAutoreverse animations:^{
    //這里對(duì)視圖的屬性進(jìn)行修改
    weakSelf.imageView2.center = center2;
} completion:^(BOOL finished) {
    
}];

Note:需要注意的是options參數(shù)的設(shè)置,會(huì)有不同的效果

類似彈簧效果的動(dòng)畫

[UIView animateWithDuration:0.8 delay:0.5 usingSpringWithDamping:0.3f initialSpringVelocity:0.0f options:0 animations:^{
    //這里對(duì)視圖的屬性進(jìn)行修改
    weakSelf.imageView2.center = center2;
} completion:^(BOOL finished) {
    
}];

對(duì)函數(shù)animateWithDuration: delay:usingSpringWithDamping: initialSpringVelocity: options: animations: completion:的解釋:

  • usingSpringWithDamping: 取值范圍在0.0~1.0, 取值越小,震蕩幅度越大
  • initialSpringVelocity:確定了在動(dòng)畫結(jié)束之前運(yùn)動(dòng)的速度。一般情況下都是設(shè)置為0。設(shè)值舉個(gè)例子來(lái)說(shuō),如果想要移動(dòng)的距離為200pt,移動(dòng)速度為100pt/s,就需要設(shè)置為0.5。

設(shè)置position會(huì)有彈簧效果,設(shè)置視圖的bounds或transform同樣也會(huì)有彈簧效果的。

__weak typeof(self) weakSelf = self;
CGRect bounds = self.button.bounds;
bounds.size.width += 100;
//    CGAffineTransform transform = CGAffineTransformMakeScale(1.3f, 1.0f);
[UIView animateWithDuration:2.0f delay:0 usingSpringWithDamping:0.2 initialSpringVelocity:0 options:0 animations:^{
    weakSelf.button.bounds = bounds;
//        weakSelf.button.transform = transform;
//        weakSelf.button.backgroundColor = [UIColor redColor];
} completion:^(BOOL finished) {
//        weakSelf.button.transform = CGAffineTransformIdentity;
}];

以上方式可以在改變視圖的屬性時(shí)產(chǎn)生動(dòng)畫,如果視圖添加或者移除的時(shí)候想要添加動(dòng)畫,就要用到下面的方式了


Transitions

Transitions是在應(yīng)用到視圖之前預(yù)先定義好的。在動(dòng)畫開始知道結(jié)束,這些預(yù)先定義的動(dòng)畫都是不可改變和停止的。使用該方式動(dòng)畫之前需要有一個(gè)容器視圖,所有添加到該容器中子視圖出現(xiàn)時(shí)動(dòng)畫會(huì)執(zhí)行。

add/remove一個(gè)視圖

利用方法transitionWithView: duration: options: animations: completion:來(lái)實(shí)現(xiàn)。解釋:

  • transitionWithView:可以理解為所要添加視圖的父視圖
#import "ViewController.h"

@interface ViewController ()

@property(nonatomic,strong) UIButton *button;//觸發(fā)事件
@property(nonatomic,strong) UIView *containerView;//視圖容器 
@property(nonatomic,strong) UIImageView *addImageView;//添加的視圖
@property(nonatomic,assign) BOOL show;//記錄是否已經(jīng)添加了視圖,默認(rèn)為NO

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    [self.view addSubview:self.containerView];
    [self.view addSubview:self.button];

}

#pragma mark - Action

//按鈕事件
- (void)btnClick:(id)sender
{
    self.addImageView.center = self.view.center;

    __weak typeof(self) weakSelf = self;

    [UIView transitionWithView:self.containerView duration:0.8 options:UIViewAnimationOptionCurveEaseOut|UIViewAnimationOptionTransitionFlipFromBottom animations:^{
    if (_show) {
        //已經(jīng)存在了,就移除
        [weakSelf.addImageView removeFromSuperview];
    }
    else{
        //不存在,就添加
        [weakSelf.containerView addSubview:weakSelf.addImageView];
    }
    _show = !_show;
    } completion:^(BOOL finished) {
    
    }];
}

#pragma mark - Getter
//按鈕
- (UIButton *)button
{
    if (!_button) {
        _button = [UIButton buttonWithType:UIButtonTypeCustom];
        _button.bounds = CGRectMake(0, 0, 100, 30);
        _button.center = CGPointMake(CGRectGetMidX(self.view.frame), 100);
        [_button setTitle:@"點(diǎn)擊我" forState:UIControlStateNormal];
        _button.backgroundColor = [UIColor redColor];
        [_button addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];
    }
    return _button;
}

//容器視圖
- (UIView *)containerView
{
    if (!_containerView) {
        _containerView = [[UIView alloc]initWithFrame:self.view.bounds];
    }
    return _containerView;
}

//所添加的視圖
- (UIImageView *)addImageView
{
    if (!_addImageView) {
        _addImageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"banner"]];
        _addImageView.bounds = CGRectMake(0, 0, 283, 49);
        _addImageView.contentMode = UIViewContentModeScaleAspectFill;
    }
    return _addImageView;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end
Hide/Show 一個(gè)視圖

同樣也是利用方法transitionWithView: duration: options: animations: completion:來(lái)實(shí)現(xiàn)。只不過(guò)是通過(guò)修改該視圖的hidden屬性來(lái)實(shí)現(xiàn)。

  • transitionWithView:所要操作的視圖

嘗試不同options參數(shù),會(huì)有不同的驚喜。

先看效果

show/hide
#import "ViewController.h"

@interface ViewController ()

@property(nonatomic,strong) UIButton *button;//觸發(fā)事件
@property(nonatomic,strong) NSMutableArray *titlesArray;//存放Messages
@property(nonatomic,strong) UIImageView *addImageView;//添加的視圖
@property(nonatomic,strong) UILabel *titleLabel;//顯示Message的Label

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    [self.view addSubview:self.containerView];
    [self.view addSubview:self.button];
    [self.view addSubview:self.addImageView];
    [self.addImageView addSubview:self.titleLabel];
    self.addImageView.hidden = YES;

    [self.titlesArray addObjectsFromArray:@[@"人生若只如初見",@"何事悲風(fēng)秋畫扇",@"等閑變卻故人心",@"卻道故人心易變"]];
}

#pragma mark - Action

/*!
 *  @author Yooeee
 *
 *  @brief  按鈕事件
 *
 *  @param sender 按鈕
 */
- (void)btnClick:(id)sender
{
    self.addImageView.center = self.view.center;
    [self showMessage:0];
}

#pragma mark - Private Methods

/*!
 *  @author Yooeee
 *
 *  @brief  顯示視圖
 *
 *  @param index 顯示第幾個(gè)文字
 */
- (void)showMessage:(NSInteger)index
{
    NSAssert(index < self.titlesArray.count, @"數(shù)組越界了");

    self.titleLabel.text = self.titlesArray[index];

    __weak typeof(self) weakSelf = self;

    [UIView transitionWithView:self.addImageView duration:0.8f options:UIViewAnimationOptionCurveEaseOut|UIViewAnimationOptionTransitionFlipFromBottom animations:^{
    weakSelf.addImageView.hidden = NO;
} completion:^(BOOL finished) {
    //動(dòng)畫結(jié)束之后,為方便看效果,延遲兩秒執(zhí)行移除動(dòng)畫
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        //判定一下數(shù)組
        if (index < weakSelf.titlesArray.count) {
            //隱藏執(zhí)行下一個(gè)動(dòng)畫
            [self hideMessage:index];
        }
        else{
            //做些其他的操作
            NSLog(@"執(zhí)行完了");
        }
    });
}];
}

/*!
 *  @author Yooeee
 *
 *  @brief  隱藏視圖
 *
 *  @param index 隱藏第幾個(gè)文字
 */
- (void)hideMessage:(NSInteger)index
{
__weak typeof(self) weakSelf = self;

[UIView transitionWithView:self.addImageView duration:0.8f options:0 animations:^{
    CGPoint center = weakSelf.addImageView.center;
    center.x += weakSelf.view.frame.size.width;
    weakSelf.addImageView.center = center;
} completion:^(BOOL finished) {
    weakSelf.addImageView.hidden = YES;
    weakSelf.addImageView.center = weakSelf.view.center;
    
    //判定一下數(shù)組
    if (index < weakSelf.titlesArray.count - 1) {
        [self showMessage:index+1];
    }
    else{
        //從頭開始執(zhí)行
        [self showMessage:0];
    }
    
}];
}

#pragma mark - Getter

/*!
 *  @author Yooeee
 *
 *  @brief  觸發(fā)事件開始
 *
 *  @return button
 */
- (UIButton *)button
{
if (!_button) {
    _button = [UIButton buttonWithType:UIButtonTypeCustom];
    _button.bounds = CGRectMake(0, 0, 100, 30);
    _button.center = CGPointMake(CGRectGetMidX(self.view.frame), 100);
    [_button setTitle:@"點(diǎn)擊我" forState:UIControlStateNormal];
    _button.backgroundColor = [UIColor redColor];
    [_button addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];
}
return _button;
}

/*!
 *  @author Yooeee
 *
 *  @brief  文本信息
 */
- (NSMutableArray *)titlesArray
{
if (!_titlesArray) {
    _titlesArray = [[NSMutableArray alloc]init];
}
return _titlesArray;
}

/*!
 *  @author Yooeee
 *
 *  @brief  創(chuàng)建添加的視圖
 *
 *  @return 視圖
 */
- (UIImageView *)addImageView
{
if (!_addImageView) {
    _addImageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"banner"]];
    _addImageView.bounds = CGRectMake(0, 0, 283, 49);
    _addImageView.contentMode = UIViewContentModeScaleAspectFill;
}
return _addImageView;
}

/*!
 *  @author Yooeee
 *
 *  @brief  展現(xiàn)文本信息的Label
 *
 *  @return label
 */
- (UILabel *)titleLabel
{
if (!_titleLabel) {
    _titleLabel = [[UILabel alloc]initWithFrame:self.addImageView.bounds];
    _titleLabel.textAlignment = NSTextAlignmentCenter;
}
return _titleLabel;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

視圖的替換

利用方法transitionFromView: toView: duration: options: completion:來(lái)實(shí)現(xiàn),是將toView添加到fromView的superview上,并且將fromView 從他的superview上移除。解釋:

  • transitionFromView: 被替換的視圖

  • toView: 替換的視圖

    [UIView transitionFromView:_fromImageView toView:_toImageView duration:0.8f options:UIViewAnimationOptionTransitionCurlDown completion:^(BOOL finished) {
    
    }];
    

需要注意的是執(zhí)行動(dòng)畫的時(shí)候,整個(gè)superview都會(huì)執(zhí)行該動(dòng)畫。

利用輔助視圖的方式來(lái)實(shí)現(xiàn)動(dòng)畫

注意這種方法,可以利用輔助視圖來(lái)實(shí)現(xiàn)我們所需要的效果。
效果:


代碼如下:
/*!
* @author Yooeee
*
* @brief 動(dòng)態(tài)的切換文字
*
* @param label 所要改變文字的Label
* @param text 改變的文字
*/
- (void)cube:(UILabel *)label text:(NSString *)text
{
//輔助視圖,用來(lái)實(shí)現(xiàn)效果
UILabel *aLabel = [[UILabel alloc]initWithFrame:label.frame];
aLabel.text = text;
aLabel.textAlignment = label.textAlignment;
aLabel.font = label.font;

    CGFloat offset = label.frame.size.height/2.0f;
    aLabel.transform = CGAffineTransformConcat(CGAffineTransformMakeScale(1.0, 0.1), CGAffineTransformMakeTranslation(0.0, offset));

    [label.superview addSubview:aLabel];

    [UIView animateWithDuration:0.5 delay:0.0 options:UIViewAnimationOptionCurveEaseOut animations:^{
        aLabel.transform = CGAffineTransformIdentity;
        label.transform = CGAffineTransformConcat(CGAffineTransformMakeScale(1.0, 0.1), CGAffineTransformMakeTranslation(0.0, -offset));
} completion:^(BOOL finished) {
    label.text = text;
    label.transform = CGAffineTransformIdentity;
    
    [aLabel removeFromSuperview];
}];
}

漸隱效果

主要是修改option的參數(shù)取值
先看效果:


Lunch.gif
[UIView transitionWithView:_fadeImageView duration:1.5 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
    _fadeImageView.image = [UIImage imageNamed:@"image2"];
} completion:^(BOOL finished) {
    
}];

Keyframe Animations的實(shí)現(xiàn)

有時(shí)候我們需要實(shí)現(xiàn)多個(gè)連續(xù)的動(dòng)畫,或許我們可以在 completion中來(lái)實(shí)現(xiàn)多個(gè)動(dòng)畫的連續(xù),但是我們卻可以有更好的選擇,那就是 Keyframe Animations(幀動(dòng)畫)。
這里我們需要用到方法animateKeyframesWithDuration: delay: options: animations: completion:

  • animateKeyframesWithDuration:所有動(dòng)畫完成的總時(shí)間
  • delay:延遲執(zhí)行時(shí)間
  • options:一些設(shè)置,他是枚舉類型 UIViewKeyFrameAnimationOptions,不是UIViewAnimationOptions,這個(gè)一定要注意。
  • animations:我們的動(dòng)畫就添加到這里面
  • completion:這個(gè)動(dòng)畫執(zhí)行完成后會(huì)執(zhí)行這里

使用方法addKeyframeWithRelativeStartTime: relativeDuration: animations:來(lái)添加各個(gè)時(shí)間段內(nèi)的動(dòng)畫。

  • startTime 指相對(duì)于全部動(dòng)畫時(shí)間的開始時(shí)間。比如總時(shí)間為10s,設(shè)值為0.3,則此動(dòng)畫就是第3秒開始。取值都在0~1.0之間。
  • duration 指相對(duì)于全部動(dòng)畫時(shí)間的持續(xù)時(shí)間。比如總時(shí)間為10秒,設(shè)置為0.4,則此動(dòng)畫所持續(xù)的時(shí)間就是4秒。取值都在0~1.0之間。

舉個(gè)例子:實(shí)現(xiàn)效果先看

飛機(jī)起飛

實(shí)現(xiàn)代碼
- (void)planeDepart
{
CGPoint originCenter = _planeImageView.center;

[UIView animateKeyframesWithDuration:1.5 delay:2.0 options:0 animations:^{
    //在這里添加動(dòng)畫
    
    [UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.25 animations:^{
        CGPoint center = self.planeImageView.center;
        center.x += 80.0f;
        center.y -=10.0f;
        self.planeImageView.center = center;
    }];
    
    [UIView addKeyframeWithRelativeStartTime:0.1 relativeDuration:0.4 animations:^{
        self.planeImageView.transform = CGAffineTransformMakeRotation(-M_PI_4/2);
    }];
    
    [UIView addKeyframeWithRelativeStartTime:0.25 relativeDuration:0.25 animations:^{
        CGPoint center = self.planeImageView.center;
        center.x += 100.0f;
        center.y -= 50.0f;
        self.planeImageView.center = center;
        self.planeImageView.alpha = 0.0;
    }];
    
    [UIView addKeyframeWithRelativeStartTime:0.51 relativeDuration:0.01 animations:^{
        self.planeImageView.transform = CGAffineTransformIdentity;
        self.planeImageView.center = CGPointMake(0, originCenter.y);
    }];
    
    [UIView addKeyframeWithRelativeStartTime:0.55 relativeDuration:0.45 animations:^{
        self.planeImageView.alpha = 1.0;
        self.planeImageView.center = originCenter;
    }];
    
} completion:^(BOOL finished) {
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        //兩秒之后重復(fù)執(zhí)行動(dòng)畫
        [self planeDepart];
    });
}];
}

上個(gè)源代碼吧 Plane

說(shuō)明:

  • 各個(gè)幀動(dòng)畫之間的時(shí)間點(diǎn)是可以重疊的。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 先看看CAAnimation動(dòng)畫的繼承結(jié)構(gòu) CAAnimation{ CAPropertyAnimation { ...
    時(shí)間不會(huì)倒著走閱讀 1,694評(píng)論 0 1
  • 在iOS實(shí)際開發(fā)中常用的動(dòng)畫無(wú)非是以下四種:UIView動(dòng)畫,核心動(dòng)畫,幀動(dòng)畫,自定義轉(zhuǎn)場(chǎng)動(dòng)畫。 1.UIView...
    請(qǐng)叫我周小帥閱讀 3,169評(píng)論 1 23
  • 前言的前言 唐巧前輩在微信公眾號(hào)「iOSDevTips」以及其博客上推送了我的文章后,我的 Github 各項(xiàng)指標(biāo)...
    VincentHK閱讀 5,440評(píng)論 3 44
  • 在iOS中隨處都可以看到絢麗的動(dòng)畫效果,實(shí)現(xiàn)這些動(dòng)畫的過(guò)程并不復(fù)雜,今天將帶大家一窺ios動(dòng)畫全貌。在這里你可以看...
    每天刷兩次牙閱讀 8,573評(píng)論 6 30
  • 在iOS中隨處都可以看到絢麗的動(dòng)畫效果,實(shí)現(xiàn)這些動(dòng)畫的過(guò)程并不復(fù)雜,今天將帶大家一窺iOS動(dòng)畫全貌。在這里你可以看...
    F麥子閱讀 5,147評(píng)論 5 13