OC UIView基礎

韋家冰發表於2017-12-13

基本屬性方法

@interface UIView : UIResponder <NSCoding, UIAppearance, UIAppearanceContainer, UIDynamicItem, UITraitEnvironment, UICoordinateSpace, UIFocusItem, CALayerDelegate>

@property(class, nonatomic, readonly) Class layerClass; // 預設是[CALayer class],過載這個方法,可以返回自定義的LayerClass.
//init方法
- (instancetype)initWithFrame:(CGRect)frame NS_DESIGNATED_INITIALIZER;
//NSCoding協議,例項化從序列化
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER;

// 預設YES,設定NO是使用者事件(觸控鍵)被忽略和從事件佇列中刪除
@property(nonatomic,getter=isUserInteractionEnabled) BOOL userInteractionEnabled;
// 標記tag,預設=0
@property(nonatomic)                                 NSInteger tag;
// 返回view的layer(非空)
@property(nonatomic,readonly,strong)                 CALayer  *layer;
// 可成為焦點,預設為no
@property(nonatomic,readonly) BOOL canBecomeFocused NS_AVAILABLE_IOS(9_0);
// 是否是焦點
@property (readonly, nonatomic, getter=isFocused) BOOL focused NS_AVAILABLE_IOS(9_0);
複製程式碼

佈局Geometry

@interface UIView(UIViewGeometry)

// 當前檢視的邊界,包括大小和原點,這裡是在父檢視的座標系下
@property(nonatomic) CGRect            frame;
// 當前檢視的邊界,包括大小和原點,這裡是在自己的座標系下
@property(nonatomic) CGRect            bounds;
// 當前檢視的中心,並制定是在父檢視的座標系下
@property(nonatomic) CGPoint           center;
// 形變屬性(平移/縮放/旋轉)--預設是CGAffineTransformIdentity。可以做成動畫
/*
  CGAffineTransform結構體,有六個值,分別是:
  CGFloat a, b, c, d;
  CGFloat tx, ty;
  */
@property(nonatomic) CGAffineTransform transform;
// 應用到當前檢視的比例Scale
@property(nonatomic) CGFloat           contentScaleFactor NS_AVAILABLE_IOS(4_0);

// 是否支援多點觸控,預設是NO
@property(nonatomic,getter=isMultipleTouchEnabled) BOOL multipleTouchEnabled ;
// 決定當前檢視是否是處理觸控事件的唯一物件,預設為NO
@property(nonatomic,getter=isExclusiveTouch) BOOL       exclusiveTouch ;

//點選鏈的處理判斷方法
- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event;

// 這個函式的用處是判斷當前的點選或者觸控事件的點是否在當前的View中
- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event;
// 把本檢視(呼叫者)下的point(第一引數)轉換為指定View(第二引數)的point(返回值)
- (CGPoint)convertPoint:(CGPoint)point toView:(nullable UIView *)view;
// 把指定View(第二引數)下的point(第一引數)轉化為本檢視(呼叫者)的point(返回值)
- (CGPoint)convertPoint:(CGPoint)point fromView:(nullable UIView *)view;
// 把本檢視(呼叫者)下的rect(第一引數)轉換為指定View(第二引數)的rect(返回值)
- (CGRect)convertRect:(CGRect)rect toView:(nullable UIView *)view;
// 把指定View(第二引數)下的rect(第一引數)轉化為本檢視(呼叫者)的rect(返回值)
- (CGRect)convertRect:(CGRect)rect fromView:(nullable UIView *)view;

// 這個屬性是決定當檢視大小邊界發生改變時,其子檢視是否也跟著自動調整大小,預設為YES
@property(nonatomic) BOOL               autoresizesSubviews;
// 決定當當前檢視的父檢視大小發生變化時,當前檢視該怎麼調整自己的size
@property(nonatomic) UIViewAutoresizing autoresizingMask;
//UIViewAutoresizing列舉值:
/*
  UIViewAutoresizingNone                 //檢視將不進行自動尺寸調整。
  UIViewAutoresizingFlexibleHeight       //檢視的高度將和父檢視的高度一起成比例變化。否則,檢視的高度將保持不變
  UIViewAutoresizingFlexibleWidth        //檢視的寬度將和父檢視的寬度一起成比例變化。否則,檢視的寬度將保持不變
  UIViewAutoresizingFlexibleLeftMargin   //檢視的左邊界將隨著父檢視寬度的變化而按比例進行調整。否則,檢視和其父檢視的左邊界的相對位置將保持不變。
  UIViewAutoresizingFlexibleRightMargin  //檢視的右邊界將隨著父檢視寬度的變化而按比例進行調整。否則,檢視和其父檢視的右邊界的相對位置將保持不變。
  UIViewAutoresizingFlexibleBottomMargin //檢視的底邊界將隨著父檢視高度的變化而按比例進行調整。否則,檢視和其父檢視的底邊界的相對位置將保持不變。
  UIViewAutoresizingFlexibleTopMargin    //檢視的上邊界將隨著父檢視高度的變化而按比例進行調整。否則,檢視和其父檢視的上邊界的相對位置將保持不變。
  
  */

//// 返回最符合其子檢視的大小。返回最佳尺寸,預設返回self.frame.size
- (CGSize)sizeThatFits:(CGSize)size;
//移動並調整子檢視的大小,先呼叫sizeThatFits:,然後設定view.size
- (void)sizeToFit;
@end
複製程式碼

層次結構 UIView(UIViewHierarchy)

@interface UIView(UIViewHierarchy)

// 獲取父檢視,只讀屬性
@property(nullable, nonatomic,readonly) UIView       *superview;    
// 當前檢視的所有子檢視,只讀屬性
@property(nonatomic,readonly,copy) NSArray<__kindof UIView *> *subviews;    
// 當前檢視上的UIWindow物件,只讀屬性
@property(nullable, nonatomic,readonly) UIWindow     *window;       

// 從父檢視移除
- (void)removeFromSuperview;        
// 在索引位置插入一個檢視
- (void)insertSubview:(UIView *)view atIndex:(NSInteger)index;      
// 用索引值交換兩個檢視
- (void)exchangeSubviewAtIndex:(NSInteger)index1 withSubviewAtIndex:(NSInteger)index2;      

// 向當前檢視上新增子檢視
- (void)addSubview:(UIView *)view;      
// 在某個檢視下插入一個檢視
- (void)insertSubview:(UIView *)view belowSubview:(UIView *)siblingSubview;   
// 在某個檢視上插入一個檢視  
- (void)insertSubview:(UIView *)view aboveSubview:(UIView *)siblingSubview;     

// 把這個View放到最前面
- (void)bringSubviewToFront:(UIView *)view;  
// 把這個View放到最後面   
- (void)sendSubviewToBack:(UIView *)view;       

// 告訴檢視新增子檢視
- (void)didAddSubview:(UIView *)subview;        
// 即將移除子檢視
- (void)willRemoveSubview:(UIView *)subview;        

// 在一個子檢視將要被新增到另一個檢視的時候傳送此訊息
- (void)willMoveToSuperview:(nullable UIView *)newSuperview;  
// 已經移除,父檢視改變      
- (void)didMoveToSuperview;     
// 在一個檢視(或者它的超檢視)將要被新增到window的時候傳送
- (void)willMoveToWindow:(nullable UIWindow *)newWindow;    
// 已經語出窗體物件    
- (void)didMoveToWindow;        


// 判定一個檢視是否在其父檢視的檢視層中(系統自動呼叫)
- (BOOL)isDescendantOfView:(UIView *)view;  
// 返回指定tag的View
- (nullable __kindof UIView *)viewWithTag:(NSInteger)tag; 

#pragma mark - 佈局
// 標記檢視需要重新佈局,會呼叫layoutSubviews
- (void)setNeedsLayout;  
// 當呼叫了setNeedsLayout並不會馬上呼叫layoutSubViews,這時會呼叫該方法,可以強制發生重新佈局   
- (void)layoutIfNeeded;     

#pragma mark - 系統自動呼叫(留給子類去實現)
/**
 *  控制元件的frame,約束髮生改變的時候就會呼叫,一般在這裡重寫佈局子控制元件的位置和尺寸
 *  重寫了這個方法後一定要呼叫[super layoutSubviews]
 */
- (void)layoutSubviews;    // 對子檢視佈局
/*
 
 layoutSubviews在以下情況下會被呼叫:
 1、init初始化不會觸發layoutSubviews ,  但 initWithFrame 進行初始化時,當rect的值不為CGRectZero時,也會觸發.
 2、addSubview會觸發layoutSubviews.
 3、設定view的Frame會觸發layoutSubviews,當然前提是frame的值設定前後發生了變化.
 4、滾動一個UIScrollView會觸發layoutSubviews.
 5、旋轉Screen會觸發父UIView上的layoutSubviews事件.
 6、改變一個UIView大小的時候也會觸發父UIView上的layoutSubviews事件.
 [1]、layoutSubviews對subviews重新佈局
 [2]、layoutSubviews方法呼叫先於drawRect
 [3]、setNeedsLayout在receiver標上一個需要被重新佈局的標記,在系統runloop的下一個週期自動呼叫layoutSubviews
 [4]、layoutIfNeeded方法如其名,UIKit會判斷該receiver是否需要layout
 [5]、layoutIfNeeded遍歷的不是superview鏈,應該是subviews鏈
 
 */


// 佈局檢視,距離父檢視的上左下右的距離
@property (nonatomic) UIEdgeInsets layoutMargins;   
// 這個屬性預設是NO,如果把它設為YES,layoutMargins會根據螢幕中相關View的佈局而改變
@property (nonatomic) BOOL preservesSuperviewLayoutMargins; 
// 在我們改變View的layoutMargins這個屬性時,會觸發這個方法。我們在自己的View裡面可以重寫這個方法來捕獲layoutMargins的變化。在大多數情況下,我們可以在這個方法裡觸發drawing和layout的Update
- (void)layoutMarginsDidChange;     

// 相對於View Layout Margins建立的約束,在其view的邊緣會留下一些空白的距離
@property(readonly,strong) UILayoutGuide *layoutMarginsGuide NS_AVAILABLE_IOS(9_0);


// 會根據size class來調整大小,這樣會在邊緣新增空白的距離,來跟適合閱讀
@property (nonatomic, readonly, strong) UILayoutGuide *readableContentGuide  NS_AVAILABLE_IOS(9_0);
//UILayoutGuide類定義了可以通過自動佈局互動的矩形區域。使用佈局指南來替換可能已建立的虛擬檢視,以在使用者介面中表示檢視間間距或封裝
//UILayoutGuide可以虛擬View幫助的事情都可以交給UILayoutGuide來做。它更輕量、更快速、更高效。UILayoutGuide並沒有真正的建立一個View,只是建立了一個矩形空間,只在進行auto layout時參與進來計算

@end

複製程式碼

繪製--UIView(UIViewRendering)

@interface UIView(UIViewRendering)
/**
 *  drawRect是對receiver的重繪
 *  setNeedDisplay在receiver標上一個需要被重新繪圖的標記,在下一個draw週期自動重繪,iphone device的重新整理頻率是60hz,也就是1/60秒後重繪
 */
// 渲染 重寫此方法 執行重繪
- (void)drawRect:(CGRect)rect;      

// 需要重新渲染  標記為需要重繪 一步呼叫drawRect
- (void)setNeedsDisplay;    
// 需要重新渲染某一塊區域
- (void)setNeedsDisplayInRect:(CGRect)rect;     

// 決定了子檢視的顯示範圍。具體來說,當取值為YES時,裁剪超出父檢視範圍的子檢視範圍
@property(nonatomic) BOOL clipsToBounds; 
// 設定背景顏色
@property(nullable, nonatomic,copy) UIColor *backgroundColor; 
// 透明度,0.0-1.0的數值,0為全透明,1為不透明 
@property(nonatomic) CGFloat alpha; 
// 是否透明,預設為YES==不透明
@property(nonatomic,getter=isOpaque) BOOL opaque; 
/*
 決定該訊息接收者(UIView instance)是否讓其檢視不透明,用處在於給繪圖系統提供一個效能優化開關。
 myView.opaque = NO;
 該值為YES, 那麼繪圖在繪製該檢視的時候把整個檢視當作不透明對待。優化繪圖過程並提升系統效能;為了效能方面的考量,預設被置為YES。
 該值為NO,,不去做優化操作。
 一個不透明檢視需要整個邊界裡面的內容都是不透明。基於這個原因,opaque設定為YES,要求對應的alpha必須為1.0。如果一個UIView例項opaque被設定為YES, 而同時它又沒有完全填充它的邊界(bounds),或者它包含了整個或部分的透明的內容檢視,那麼將會導致未知的結果。
 因此,如果檢視部分或全部支援透明,那麼你必須把opaque這個值設定為NO.
 */

// 決定在子檢視重畫之前是否先清理檢視以前的內容
@property(nonatomic) BOOL clearsContextBeforeDrawing; 
// 是否隱藏,預設為NO
@property(nonatomic,getter=isHidden) BOOL hidden;   
// 決定當檢視邊界變時呈現檢視                  
@property(nonatomic) UIViewContentMode contentMode; 
//設定圖片的顯示方式
typedef NS_ENUM(NSInteger, UIViewContentMode) {
    UIViewContentModeScaleToFill,         // 填充  根據檢視的比例去拉伸圖片內容
    UIViewContentModeScaleAspectFit,      // 縮放填充   保持圖片內容的縱橫比例,來適應檢視的大小
    UIViewContentModeScaleAspectFill,     // 用圖片內容來填充檢視的大小,多餘的部分可以被修剪掉來填充整個檢視邊界
    UIViewContentModeRedraw,              // 重繪邊界   這個選項是單檢視的尺寸位置發生變化的時候通過呼叫setNeedsDisplay方法來重新顯示
    UIViewContentModeCenter,              // 保持圖片原比例,居中
    UIViewContentModeTop,                 // 保持圖片原比例,居上
    UIViewContentModeBottom,              // 保持圖片原比例,居下
    UIViewContentModeLeft,                // 保持圖片原比例,居左
    UIViewContentModeRight,               // 保持圖片原比例,居右
    UIViewContentModeTopLeft,             // 保持圖片原比例,居左上
    UIViewContentModeTopRight,            // 保持圖片原比例,居右上
    UIViewContentModeBottomLeft,          // 保持圖片原比例,居左下
    UIViewContentModeBottomRight,         // 保持圖片原比例,居右下
};
// 用於制定那部分是可拉伸的,取值在0.0~1.0之間
@property(nonatomic) CGRect contentStretch; 
/*
 [imageView setContentStretch:CGRectMake(150.0/300.0, 100.0/200.0, 10.0/300.0, 10.0/200.0)];
 
    image.png的大小是 200  x  150 ;
    mageView的frame是(0,0,300,200);
    150.0/300.0表示x軸上,前150個畫素不進行拉伸。
    100.0/200.0表示y軸上,前100個畫素不進行拉伸。
    10.0/300.0表示x軸上150後的10個畫素(151-160)進行拉伸,直到image.png鋪滿imageView。
    10.0/200.0表示y軸上100後的10個畫素(101-110)進行拉伸,直到image.png鋪滿imageView。
 */


@property(nullable, nonatomic,strong) UIView *maskView;  // 模具檢視
@property(null_resettable, nonatomic, strong) UIColor *tintColor; // 檢視控制元件的顏色
@property(nonatomic) UIViewTintAdjustmentMode tintAdjustmentMode; // 檢視的色彩模式
/*
 列舉值:
    UIViewTintAdjustmentModeAutomatic,      //自動的
    UIViewTintAdjustmentModeNormal,         //正常的
    UIViewTintAdjustmentModeDimmed,         //暗淡的
 */

- (void)tintColorDidChange;     // 檢視顏色屬性發生變化時,由系統呼叫


@end
複製程式碼

手勢-- UIView (UIViewGestureRecognizers)

@interface UIView (UIViewGestureRecognizers)

@property(nullable, nonatomic,copy) NSArray<__kindof UIGestureRecognizer *> *gestureRecognizers;    // 訪問手勢集合
- (void)addGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer;       // 新增手勢
- (void)removeGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer;        // 移除手勢
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer;      // 通過返回值決定是否識別此手勢
@end
複製程式碼

#####動畫相關--UIView(UIViewAnimationWithBlocks)

typedef NS_OPTIONS(NSUInteger, UIViewAnimationOptions) {

    //1.常規動畫屬性設定(可以同時選擇多個進行設定)
    UIViewAnimationOptionLayoutSubviews            = 1 <<  0,//動畫過程中保證子檢視跟隨運動
    UIViewAnimationOptionAllowUserInteraction      = 1 <<  1, // 動畫過程中允許使用者互動
    UIViewAnimationOptionBeginFromCurrentState     = 1 <<  2, // 所有檢視從當前狀態開始執行
    UIViewAnimationOptionRepeat                    = 1 <<  3, // 重複執行動畫
    UIViewAnimationOptionAutoreverse               = 1 <<  4, // 如果重複,動畫執行到結束點後仍然以動畫方式回到初始點
    UIViewAnimationOptionOverrideInheritedDuration = 1 <<  5, // 忽略巢狀動畫時間設定
    UIViewAnimationOptionOverrideInheritedCurve    = 1 <<  6, // 忽略巢狀動畫速度設定
    UIViewAnimationOptionAllowAnimatedContent      = 1 <<  7, // 動畫過程中重繪檢視(注意僅僅適用於轉場動畫)
    UIViewAnimationOptionShowHideTransitionViews   = 1 <<  8, // 檢視切換時直接隱藏舊檢視、顯示新檢視,而不是將舊檢視從父檢視移除(僅僅適用於轉場動畫)
    UIViewAnimationOptionOverrideInheritedOptions  = 1 <<  9, // 不繼承父動畫設定或動畫型別
    
    //2.動畫速度控制(單選)
    UIViewAnimationOptionCurveEaseInOut            = 0 << 16, // 開始慢-中間塊-結束慢
    UIViewAnimationOptionCurveEaseIn               = 1 << 16, // 開始慢-結束快
    UIViewAnimationOptionCurveEaseOut              = 2 << 16, // 開始快-結束慢
    UIViewAnimationOptionCurveLinear               = 3 << 16, // 線性
    
    //3.轉場型別(單選)
    UIViewAnimationOptionTransitionNone            = 0 << 20, // 沒有轉場動畫效果
    UIViewAnimationOptionTransitionFlipFromLeft    = 1 << 20, // 從左側翻轉效果
    UIViewAnimationOptionTransitionFlipFromRight   = 2 << 20, // 從右側翻轉效果
    UIViewAnimationOptionTransitionCurlUp          = 3 << 20, // 向後翻頁的動畫過渡效果
    UIViewAnimationOptionTransitionCurlDown        = 4 << 20, // 向前翻頁的動畫過渡效果
    UIViewAnimationOptionTransitionCrossDissolve   = 5 << 20, // 舊檢視溶解消失顯示下一個新檢視的效果
    UIViewAnimationOptionTransitionFlipFromTop     = 6 << 20, // 從上方翻轉效果
    UIViewAnimationOptionTransitionFlipFromBottom  = 7 << 20, // 從底部翻轉效果
};
複製程式碼
@interface UIView(UIViewAnimationWithBlocks)

/**
 view的一些動畫一般使用這個就夠了
 @param duration 動畫時長
 @param delay 延時執行時間
 @param options 動畫型別
 @param animations 動畫最後的狀態block
 @param completion 動畫執行完成的block
 */
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion ;
// delay = 0.0, options = 0
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion ;
// delay = 0.0, options = 0, completion = NULL
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations;

/**
 Spring Animation彈簧動畫 系統操作很多這種動畫
 @param dampingRatio 0.0f-1.0f,數值越小「彈簧」的振動效果越明顯
 @param velocity 初始的速度,數值越大一開始移動越快
 */
+ (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);


/**
 轉場動畫
 @param view 需要進行轉場動畫的檢視
 */
+ (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);


/**
 轉場動畫
 // 新增toView到父檢視
 [fromView.superview addSubview:toView];
 // 把fromView從父檢視中移除
 [fromView.superview removeFromSuperview];
 */
+ (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

//在一組檢視上執行指定的系統動畫,並可以並行自定義的動畫
//其中parallelAnimations就是與系統動畫並行的自定義動畫--只有UISystemAnimationDelete
+ (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);

複製程式碼

簡單使用

[UIView animateWithDuration:3.0 animations:^{
        //直接寫最後的view狀態
    } completion:^(BOOL finished) {
        //動畫結束
    }];
複製程式碼

關鍵幀動畫--UIView (UIViewKeyframeAnimations)


typedef NS_OPTIONS(NSUInteger, UIViewKeyframeAnimationOptions) {
    UIViewKeyframeAnimationOptionLayoutSubviews            = UIViewAnimationOptionLayoutSubviews,//動畫過程中保證子檢視跟隨運動
    UIViewKeyframeAnimationOptionAllowUserInteraction      = UIViewAnimationOptionAllowUserInteraction, // 動畫過程中允許使用者互動
    UIViewKeyframeAnimationOptionBeginFromCurrentState     = UIViewAnimationOptionBeginFromCurrentState, // 所有檢視從當前狀態開始執行
    UIViewKeyframeAnimationOptionRepeat                    = UIViewAnimationOptionRepeat, // 重複執行動畫
    UIViewKeyframeAnimationOptionAutoreverse               = UIViewAnimationOptionAutoreverse, // 如果重複,動畫執行到結束點後仍然以動畫方式回到初始點
    UIViewKeyframeAnimationOptionOverrideInheritedDuration = UIViewAnimationOptionOverrideInheritedDuration, // 忽略巢狀動畫時間設定
    UIViewKeyframeAnimationOptionOverrideInheritedOptions  = UIViewAnimationOptionOverrideInheritedOptions, // 不繼承父動畫設定或動畫型別
    
    UIViewKeyframeAnimationOptionCalculationModeLinear     = 0 << 10, // default線性
    UIViewKeyframeAnimationOptionCalculationModeDiscrete   = 1 << 10, // 離散的
    UIViewKeyframeAnimationOptionCalculationModePaced      = 2 << 10, // 均勻執行運算模式
    UIViewKeyframeAnimationOptionCalculationModeCubic      = 3 << 10, // 平滑運算模式
    UIViewKeyframeAnimationOptionCalculationModeCubicPaced = 4 << 10  // 平滑均勻運算模式
};

@interface UIView (UIViewKeyframeAnimations)

/**
 關鍵幀動畫
 */
+ (void)animateKeyframesWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewKeyframeAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion ;

/**
 add幀動畫
 @param frameStartTime 倍數從0到1,假設一個動畫持續的時間是2秒,設定frameStartTime為0.5,那麼後面設定的動畫,將會在整體動畫執行1秒後開始執行
 @param frameDuration  也是一個倍數,都是相對總的duration來設定
 */
+ (void)addKeyframeWithRelativeStartTime:(double)frameStartTime relativeDuration:(double)frameDuration animations:(void (^)(void))animations ;
複製程式碼

簡單使用

- (void)runAnimateKeyframes {
    /**
     *  relativeDuration  動畫在什麼時候開始
     *  relativeStartTime 動畫所持續的時間
     */
    [UIView animateKeyframesWithDuration:6.f
                                   delay:0.0
                                 options:UIViewKeyframeAnimationOptionCalculationModeLinear
                              animations:^{
                                  
                                  //第一個幀動畫
                                  [UIView addKeyframeWithRelativeStartTime:0.0   // 相對於6秒所開始的時間(第0秒開始動畫)
                                                          relativeDuration:1/3.0 // 相對於6秒動畫的持續時間(動畫持續2秒)
                                                                animations:^{
                                                                    self.view.backgroundColor = [UIColor redColor];
                                                                }];
                                  //第二個幀動畫
                                  [UIView addKeyframeWithRelativeStartTime:1/3.0 // 相對於6秒所開始的時間(第2秒開始動畫)
                                                          relativeDuration:1/3.0 // 相對於6秒動畫的持續時間(動畫持續2秒)
                                                                animations:^{
                                                                    self.view.backgroundColor = [UIColor yellowColor];
                                                             }];
                                  //第三個幀動畫
                                  [UIView addKeyframeWithRelativeStartTime:2/3.0 // 相對於6秒所開始的時間(第4秒開始動畫)
                                                          relativeDuration:1/3.0 // 相對於6秒動畫的持續時間(動畫持續2秒)
                                                                animations:^{
                                                                    self.view.backgroundColor = [UIColor greenColor];                                                                }];
                                  
                              }
                              completion:^(BOOL finished) {
                                  //重複,可以設定options=UIViewKeyframeAnimationOptionRepeat
                                  [self runAnimateKeyframes];
                              }];
}
複製程式碼

相關文章