iOS基本功

OC--UIView基础

2017-03-14  本文已影响34人  啊哈呵

基本属性方法

@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];
                              }];
}
上一篇下一篇

猜你喜欢

热点阅读