iOS動(dòng)畫(huà)(2):UIView動(dòng)畫(huà)

UIView動(dòng)畫(huà)在平常的使用場(chǎng)景中比較普遍独榴,UIView的屬性改變時(shí)使用UIView動(dòng)畫(huà)過(guò)渡會(huì)比較自然谍失,用起來(lái)也比較簡(jiǎn)單琼了。

UIViewAnimation谨究、UIViewAnimationWithBlocks恩袱、UIViewKeyframeAnimations三種實(shí)現(xiàn)方式。

1胶哲、UIViewAnimation

下面是UIViewAnimation的基本調(diào)用方法(方法已做備注):

@interface UIView(UIViewAnimation)

//開(kāi)始動(dòng)畫(huà)畔塔。傳遞的context值會(huì)傳遞給代理的start/did stop方法中。
+ (void)beginAnimations:(nullable NSString *)animationID context:(nullable void *)context; 

//和beginAnimations方法成對(duì)出現(xiàn)鸯屿。代表動(dòng)畫(huà)開(kāi)始和執(zhí)行澈吨,動(dòng)畫(huà)內(nèi)容放在兩個(gè)個(gè)方法中間。
+ (void)commitAnimations;          

// 設(shè)置動(dòng)畫(huà)代理碾盟,當(dāng)動(dòng)畫(huà)開(kāi)始或者結(jié)束時(shí)會(huì)發(fā)消息給代理對(duì)象棚辽。默認(rèn)是nil。
+ (void)setAnimationDelegate:(nullable id)delegate;        

//動(dòng)畫(huà)即將開(kāi)始時(shí)冰肴,執(zhí)行selector屈藐,并且把beginAnimations:context:中傳入的參數(shù)傳進(jìn)selector              
+ (void)setAnimationWillStartSelector:(nullable SEL)selector;              

 //動(dòng)畫(huà)即將結(jié)束時(shí)榔组,執(zhí)行selector,并且把beginAnimations:context:中傳入的參數(shù)傳進(jìn)selector     
+ (void)setAnimationDidStopSelector:(nullable SEL)selector;               

//動(dòng)畫(huà)的持續(xù)時(shí)間联逻,以秒為單位搓扯。默認(rèn)是0.2.
+ (void)setAnimationDuration:(NSTimeInterval)duration;              

//動(dòng)畫(huà)延遲。默認(rèn)是0包归。
+ (void)setAnimationDelay:(NSTimeInterval)delay;                  

//默認(rèn)是now. 
+ (void)setAnimationStartDate:(NSDate *)startDate;                

//動(dòng)畫(huà)的節(jié)奏控制锨推。默認(rèn)是UIViewAnimationCurveEaseInOut。
+ (void)setAnimationCurve:(UIViewAnimationCurve)curve;             

//動(dòng)畫(huà)重復(fù)次數(shù)公壤。默認(rèn)是0.
+ (void)setAnimationRepeatCount:(float)repeatCount;       

//動(dòng)畫(huà)是否逆向運(yùn)行换可。如果是YES的話,動(dòng)畫(huà)會(huì)按照原來(lái)的運(yùn)動(dòng)軌跡逆向返回厦幅。默認(rèn)是NO沾鳄。
+ (void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses;   

//動(dòng)畫(huà)是否從當(dāng)前狀態(tài)開(kāi)始。默認(rèn)是NO确憨。如果為YES译荞,那么動(dòng)畫(huà)在運(yùn)行過(guò)程中當(dāng)前視圖的位置將會(huì)作為新的動(dòng)畫(huà)的開(kāi)始狀態(tài)。如果設(shè)置為NO休弃,新動(dòng)畫(huà)將使用視圖最後狀態(tài)的位置作為開(kāi)始狀態(tài)吞歼。
+ (void)setAnimationBeginsFromCurrentState:(BOOL)fromCurrentState;  

//設(shè)置view的過(guò)渡效果, transition是設(shè)定過(guò)渡類型, cache為YES時(shí)代表使用視圖緩存。
+ (void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView *)view cache:(BOOL)cache;  

//是否激活動(dòng)畫(huà)塔猾。如果是YES篙骡,就激活動(dòng)畫(huà),當(dāng)動(dòng)畫(huà)參數(shù)沒(méi)有被激活那么動(dòng)畫(huà)屬性的改變將被忽略桥帆。默認(rèn)是YES医增。
+ (void)setAnimationsEnabled:(BOOL)enabled;                        

#if UIKIT_DEFINE_AS_PROPERTIES
@property(class, nonatomic, readonly) BOOL areAnimationsEnabled;
#else
+ (BOOL)areAnimationsEnabled;
#endif
+ (void)performWithoutAnimation:(void (NS_NOESCAPE ^)(void))actionsWithoutAnimation NS_AVAILABLE_IOS(7_0);

#if UIKIT_DEFINE_AS_PROPERTIES
@property(class, nonatomic, readonly) NSTimeInterval inheritedAnimationDuration NS_AVAILABLE_IOS(9_0);
#else
+ (NSTimeInterval)inheritedAnimationDuration NS_AVAILABLE_IOS(9_0);
#endif

@end

UIViewAnimation使用示例:

    UIImage * image = [UIImage imageNamed:@"icon1"];
    
    [imageView setImage:image];
    
    //動(dòng)畫(huà)開(kāi)始前視圖狀態(tài)
    imageView.frame = CGRectMake(ScreenWidth/2-image.size.width/2, (ScreenHeight-image.size.height)/2,image.size.width,image.size.height);
    
    [UIView beginAnimations:nil context:nil];
    
    [UIView setAnimationDuration:1.0f];
    
    image = [UIImage imageNamed:@"icon2"];
    
    [imageView setImage:image];
    
    //視圖最終狀態(tài)
    imageView.frame = CGRectMake(ScreenWidth/2-25, ScreenHeight-50, 50, 50);
    
    [UIView commitAnimations];

2慎皱、UIViewAnimationWithBlocks

UIViewAnimationWithBlocks的方法函數(shù)如下:

@interface UIView(UIViewAnimationWithBlocks)

/**
block動(dòng)畫(huà)老虫,可以設(shè)置動(dòng)畫(huà)時(shí)長(zhǎng)、動(dòng)畫(huà)延遲茫多、動(dòng)畫(huà)選項(xiàng)祈匙、動(dòng)畫(huà)結(jié)束狀態(tài)、動(dòng)畫(huà)完成后最終狀態(tài)天揖,
可根據(jù)自己實(shí)際需要選擇下面3種實(shí)現(xiàn)方式
**/
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0);

+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0); // delay = 0.0, options = 0

+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations NS_AVAILABLE_IOS(4_0); // delay = 0.0, options = 0, completion = NULL

//視圖過(guò)渡動(dòng)畫(huà)
+ (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^ __nullable)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0);

//視圖間過(guò)渡動(dòng)畫(huà)
+ (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0); // toView added to fromView.superview, fromView removed from its superview

//彈簧動(dòng)畫(huà)
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay usingSpringWithDamping:(CGFloat)dampingRatio initialSpringVelocity:(CGFloat)velocity options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);

//刪除視圖動(dòng)畫(huà)
+ (void)performSystemAnimation:(UISystemAnimation)animation onViews:(NSArray<__kindof UIView *> *)views options:(UIViewAnimationOptions)options animations:(void (^ __nullable)(void))parallelAnimations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);

@end

主要分為簡(jiǎn)單的block動(dòng)畫(huà)夺欲、視圖過(guò)渡動(dòng)畫(huà)、視圖間過(guò)渡動(dòng)畫(huà)今膊、彈簧動(dòng)畫(huà)和刪除動(dòng)畫(huà)些阅。

注:彈簧動(dòng)畫(huà)參數(shù)dampingRatio、velocity分別是阻尼大小斑唬、形變速度市埋。
dampingRatio:實(shí)際指彈簧動(dòng)畫(huà)的摩擦力大小黎泣。值的范圍是0.0~1.0。當(dāng)阻尼大小越小代表阻力越小缤谎,反之則阻力越大抒倚,阻力越小彈簧動(dòng)畫(huà)的幅度就越大,越大彈簧幅度就越小坷澡,與現(xiàn)實(shí)中彈簧拉伸的道理是一樣的托呕。
velocity:指彈簧的變化的速度。速度越大频敛,變化越快项郊。

下面看下不同動(dòng)畫(huà)的代碼示例:

(1)簡(jiǎn)單的block動(dòng)畫(huà)
-(void)AnimationWithSimpleBlocks{
    
    UIImage * image = [UIImage imageNamed:@"heart"];
    
    [imageView setImage:image];
    
    imageView.frame = CGRectMake((ScreenWidth-image.size.width)/2, 150+(ScreenHeight-150-image.size.height)/2,image.size.width,image.size.height);
    
    [UIView animateWithDuration:1.0f delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
        //動(dòng)畫(huà)終點(diǎn)
        imageView.frame = CGRectMake((ScreenWidth-image.size.width)/2, 150+(ScreenHeight-150-image.size.height)/2, image.size.width+20, image.size.height+20);
        
    } completion:^(BOOL finished) {
        
        //view最終狀態(tài)(UIView會(huì)從動(dòng)畫(huà)結(jié)束狀態(tài)轉(zhuǎn)換到此處設(shè)定的狀態(tài),在轉(zhuǎn)換過(guò)程中沒(méi)有動(dòng)畫(huà)效果)
        imageView.frame = CGRectMake((ScreenWidth-image.size.width)/2,  150+(ScreenHeight-150-image.size.height)/2,image.size.width,image.size.height);
        
    }];

}

(2)視圖過(guò)渡動(dòng)畫(huà)示例:
-(void)AnimationWithTransitionBlocks{
    
    UIImage * image = [UIImage imageNamed:@"heart"];
    
    [imageView setImage:image];
    
    imageView.frame = CGRectMake(0, (ScreenHeight-image.size.height)/2,image.size.width,image.size.height);
    
    //帶有過(guò)渡效果
    [UIView transitionWithView:imageView duration:1.5f options:UIViewAnimationOptionTransitionFlipFromLeft animations:^{
        
        //動(dòng)畫(huà)終點(diǎn)
        imageView.frame = CGRectMake((ScreenWidth-image.size.width)/2, 150+(ScreenHeight-150-image.size.height)/2, image.size.width+20, image.size.height+20);

    } completion:^(BOOL finished) {
        
    }];
    
}


(3)視圖之間過(guò)渡動(dòng)畫(huà)代碼示例:
-(void)AnimationBetweenViews{
    UIView *view1 = [[UIView alloc]initWithFrame:self.view.frame];
    
    view1.backgroundColor = [UIColor yellowColor];
    
    UIView *view2 = [[UIView alloc]initWithFrame:self.view.frame];
    
    view2.backgroundColor = [UIColor orangeColor];
    
    [self.view addSubview:view1];
    
    [self.view addSubview:view2];
    
    [UIView transitionFromView:view1  toView:view2 duration:1.5f options:UIViewAnimationOptionTransitionFlipFromLeft completion:^(BOOL finished) {
        
        [view1 removeFromSuperview];
        
        [view2 removeFromSuperview];
        
    }];
}
(4)彈簧動(dòng)畫(huà)示例
-(void)SpringAnimation{
    
    UIImage * image = [UIImage imageNamed:@"heart"];
    
    [imageView setImage:image];
    
    imageView.frame = CGRectMake(0, 150+(ScreenHeight-150-image.size.height)/2,image.size.width,image.size.height);
    
    [UIView animateWithDuration:1.0f delay:0 usingSpringWithDamping:0.5 initialSpringVelocity:0.5 options:0 animations:^{
        
        //動(dòng)畫(huà)終點(diǎn)
        imageView.frame = CGRectMake((ScreenWidth-image.size.width)/2, 150+(ScreenHeight-150-image.size.height)/2, image.size.width+20, image.size.height+20);
        
    } completion:^(BOOL finished) {
        
        
    }];

}

運(yùn)行結(jié)果如下:

UIView Block動(dòng)畫(huà).gif

注:UIView的簡(jiǎn)單動(dòng)畫(huà)可以通過(guò)這兩種方式來(lái)實(shí)現(xiàn)斟赚,如果是比較復(fù)雜的動(dòng)畫(huà)的話使用CAKeyframeAnimations實(shí)現(xiàn)會(huì)更方便呆抑。

3、CAKeyframeAnimations

CAKeyframeAnimations函數(shù)如下:

@interface UIView (UIViewKeyframeAnimations)

//設(shè)定動(dòng)畫(huà)時(shí)長(zhǎng)汁展、動(dòng)畫(huà)延遲鹊碍、關(guān)鍵幀選項(xiàng)、關(guān)鍵幀
+ (void)animateKeyframesWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewKeyframeAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);

//添加關(guān)鍵幀動(dòng)畫(huà)的開(kāi)始時(shí)間食绿、幀動(dòng)畫(huà)在整個(gè)動(dòng)畫(huà)的比例
+ (void)addKeyframeWithRelativeStartTime:(double)frameStartTime relativeDuration:(double)frameDuration animations:(void (^)(void))animations NS_AVAILABLE_IOS(7_0); // start time and duration are values between 0.0 and 1.0 specifying time and duration relative to the overall time of the keyframe animation

@end

代碼示例:

-(void)menuClick:(UIButton *)btn{
    
    CGRect rect = CGRectMake(ScreenWidth/3-50, 275,0,0);

    if (open) {
        
        [UIView animateKeyframesWithDuration:duration delay:0 options:UIViewKeyframeAnimationOptionCalculationModeLinear animations:^{
            
            for (int i=0; i<iconArr.count; i++) {
                
                [UIView addKeyframeWithRelativeStartTime:i*1.0/iconArr.count relativeDuration:1.0/iconArr.count animations:^{
                    
                    UIImageView * functionBtn = (UIImageView *)[self.view viewWithTag:100+i];
                    
                    functionBtn.frame = rect;
                    
                }];
                
            }
            
            open = NO;
            
        } completion:nil];
        
    }
    else{
        
        UIImage * icon1 = [UIImage imageNamed:@"functionIcon1"];
        
        CGRect rect1 = CGRectMake(ScreenWidth/3, 130,50,50);
        
        CGRect rect2 = CGRectMake(ScreenWidth/3+80, 210,50,50);
        
        CGRect rect3 = CGRectMake(ScreenWidth/3+80, 290,50,50);
        
        CGRect rect4 = CGRectMake(ScreenWidth/3, 370,50,50);
        
        iconArr = @[icon1,icon1,icon1,icon1];
        
        NSArray * rectArr = @[[NSValue valueWithCGRect:rect1],[NSValue valueWithCGRect:rect2],[NSValue valueWithCGRect:rect3],[NSValue valueWithCGRect:rect4]];
        
        for (int i=0; i<4; i++) {
            
            UIImageView * functionBtn = (UIImageView *)[self.view viewWithTag:100+i];
            
            if (!functionBtn) {
                
                functionBtn = [[UIImageView alloc]initWithImage:[iconArr objectAtIndex:i]];
                
                functionBtn.tag = 100+i;
                
                functionBtn.frame = rect;
                
                [self.view addSubview:functionBtn];
            }
            
        }
        
        
        [UIView animateKeyframesWithDuration:duration delay:0 options:UIViewKeyframeAnimationOptionCalculationModeLinear animations:^{
            
            for (int i=0; i<iconArr.count; i++) {
                
                [UIView addKeyframeWithRelativeStartTime:i*1.0/iconArr.count relativeDuration:1.0/iconArr.count animations:^{
                    
                    UIImageView * functionBtn = (UIImageView *)[self.view viewWithTag:100+i];
                    
                    functionBtn.frame = [[rectArr objectAtIndex:i] CGRectValue];
                    
                }];
                
                
            }
        
            open = YES;

        } completion:nil];
        
    }

}
    

運(yùn)行效果:

UIView關(guān)鍵幀.gif
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末侈咕,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子器紧,更是在濱河造成了極大的恐慌耀销,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,576評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件铲汪,死亡現(xiàn)場(chǎng)離奇詭異熊尉,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)掌腰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)狰住,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人齿梁,你說(shuō)我怎么就攤上這事催植。” “怎么了勺择?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,017評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵创南,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我省核,道長(zhǎng)稿辙,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,626評(píng)論 1 296
  • 正文 為了忘掉前任气忠,我火速辦了婚禮邻储,結(jié)果婚禮上未桥,老公的妹妹穿的比我還像新娘。我一直安慰自己芥备,他們只是感情好冬耿,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,625評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著萌壳,像睡著了一般亦镶。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上袱瓮,一...
    開(kāi)封第一講書(shū)人閱讀 52,255評(píng)論 1 308
  • 那天缤骨,我揣著相機(jī)與錄音,去河邊找鬼尺借。 笑死绊起,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的燎斩。 我是一名探鬼主播虱歪,決...
    沈念sama閱讀 40,825評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼栅表!你這毒婦竟也來(lái)了笋鄙?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,729評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤怪瓶,失蹤者是張志新(化名)和其女友劉穎萧落,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體洗贰,經(jīng)...
    沈念sama閱讀 46,271評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡找岖,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,363評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了敛滋。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片许布。...
    茶點(diǎn)故事閱讀 40,498評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖矛缨,靈堂內(nèi)的尸體忽然破棺而出爹脾,到底是詐尸還是另有隱情帖旨,我是刑警寧澤箕昭,帶...
    沈念sama閱讀 36,183評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站解阅,受9級(jí)特大地震影響落竹,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜货抄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,867評(píng)論 3 333
  • 文/蒙蒙 一述召、第九天 我趴在偏房一處隱蔽的房頂上張望朱转。 院中可真熱鬧,春花似錦积暖、人聲如沸藤为。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,338評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)缅疟。三九已至,卻和暖如春遍愿,著一層夾襖步出監(jiān)牢的瞬間存淫,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,458評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工沼填, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留桅咆,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,906評(píng)論 3 376
  • 正文 我出身青樓坞笙,卻偏偏與公主長(zhǎng)得像岩饼,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子薛夜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,507評(píng)論 2 359

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

  • UIKit直接將動(dòng)畫(huà)集成到UIView類中忌愚,當(dāng)內(nèi)部的一些屬性發(fā)生改變時(shí),UIView將為這些改變提供動(dòng)畫(huà)支持却邓。 U...
    白水灬煮一切閱讀 1,442評(píng)論 0 0
  • 在iOS中隨處都可以看到絢麗的動(dòng)畫(huà)效果硕糊,實(shí)現(xiàn)這些動(dòng)畫(huà)的過(guò)程并不復(fù)雜,今天將帶大家一窺ios動(dòng)畫(huà)全貌腊徙。在這里你可以看...
    每天刷兩次牙閱讀 8,514評(píng)論 6 30
  • 在iOS中隨處都可以看到絢麗的動(dòng)畫(huà)效果简十,實(shí)現(xiàn)這些動(dòng)畫(huà)的過(guò)程并不復(fù)雜,今天將帶大家一窺iOS動(dòng)畫(huà)全貌撬腾。在這里你可以看...
    F麥子閱讀 5,115評(píng)論 5 13
  • 前言: UIVIew Animation 是 iOS 提供的最基礎(chǔ)的一組用于實(shí)現(xiàn) UIView 動(dòng)畫(huà)的類庫(kù)螟蝙。在 U...
    謝謝生活閱讀 3,289評(píng)論 0 5
  • 先看看CAAnimation動(dòng)畫(huà)的繼承結(jié)構(gòu) CAAnimation{ CAPropertyAnimation { ...
    時(shí)間不會(huì)倒著走閱讀 1,656評(píng)論 0 1