慢慢吞吞的学iOS开发,也总算是有了一点进展,UI基础都过了一遍,今天回顾一下之前学的东西,做个总结
//枚举
//UIview的动画形成
typedef NS_ENUM(NSInteger, UIViewAnimationCurve) {
UIViewAnimationCurveEaseInOut, // slow at beginning and end 开头结尾慢
UIViewAnimationCurveEaseIn, // slow at beginning
UIViewAnimationCurveEaseOut, // slow at end
UIViewAnimationCurveLinear
};
typedef NS_ENUM(NSInteger, UIViewContentMode) {
UIViewContentModeScaleToFill,
UIViewContentModeScaleAspectFit, // contents scaled to fit with fixed aspect. remainder is transparent 内容按比例适应view
UIViewContentModeScaleAspectFill, // contents scaled to fill with fixed aspect. some portion of content may be clipped. 内容填充view,按内容比例,不会改变内容比例
UIViewContentModeRedraw, // redraw on bounds change (calls -setNeedsDisplay)
UIViewContentModeCenter, // contents remain same size. positioned adjusted.
UIViewContentModeTop,
UIViewContentModeBottom,
UIViewContentModeLeft,
UIViewContentModeRight,
UIViewContentModeTopLeft,
UIViewContentModeTopRight,
UIViewContentModeBottomLeft,
UIViewContentModeBottomRight,
};
//注意以上几个常量,凡是没有带Scale的,当图片尺寸超过 ImageView尺寸时,只有部分显示在ImageView中。UIViewContentModeScaleToFill属性会导致图片变形。UIViewContentModeScaleAspectFit会保证图片比例不变,而且全部显示在ImageView中,这意味着ImageView会有部分空白。UIViewContentModeScaleAspectFill也会证图片比例不变,但是是填充整个ImageView的,可能只有部分图片显示出来
@interface UIView(UIViewHierarchy) @property(nonatomic,readonly) UIView *superview; @property(nonatomic,readonly,copy) NSArray *subviews; @property(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; - (void)bringSubviewToFront:(UIView *)view; - (void)sendSubviewToBack:(UIView *)view; // Allows you to perform layout before the drawing cycle happens. -layoutIfNeeded forces layout early - (void)setNeedsLayout; - (void)layoutIfNeeded; - (void)layoutSubviews; // override point. called by layoutIfNeeded automatically. As of iOS 6.0, when constraints-based layout is used the base implementation applies the constraints-based layout, otherwise it does nothing. @end
刷新子对象布局
-layoutSubviews方法:这个方法,默认没有做任何事情,需要子类进行重写
-setNeedsLayout方法: 标记为需要重新布局,异步调用layoutIfNeeded刷新布局,不立即刷新,但layoutSubviews一定会被调用
-layoutIfNeeded方法:如果,有需要刷新的标记,立即调用layoutSubviews进行布局(如果没有标记,不会调用layoutSubviews)
如果要立即刷新,要先调用[view setNeedsLayout],把标记设为需要布局,然后马上调用[view layoutIfNeeded],实现布局
在视图第一次显示之前,标记总是“需要刷新”的,可以直接调用[view layoutIfNeeded]
@interface UIView(UIViewRendering) - (void)drawRect:(CGRect)rect; - (void)setNeedsDisplay; - (void)setNeedsDisplayInRect:(CGRect)rect; @property(nonatomic) BOOL clipsToBounds; // When YES, content and subviews are clipped to the bounds of the view. Default is NO. @property(nonatomic,copy) UIColor *backgroundColor UI_APPEARANCE_SELECTOR; // default is nil. Can be useful with the appearance proxy on custom UIView subclasses. @property(nonatomic) CGFloat alpha; // animatable. default is 1.0 @property(nonatomic,getter=isOpaque) BOOL opaque; // default is YES. opaque views must fill their entire bounds or the results are undefined. the active CGContext in drawRect: will not have been cleared and may have non-zeroed pixels @end
重绘
-drawRect:(CGRect)rect方法:重写此方法,执行重绘任务
-setNeedsDisplay方法:标记为需要重绘,异步调用drawRect
-setNeedsDisplayInRect:(CGRect)invalidRect方法:标记为需要局部重绘
layoutSubviews对subviews重新布局
layoutSubviews方法调用先于drawRect
setNeedsLayout在receiver标上一个需要被重新布局的标记,在系统runloop的下一个周期自动调用layoutSubviews
layoutIfNeeded方法如其名,UIKit会判断该receiver是否需要layout.根据Apple官方文档,layoutIfNeeded方法应该是这样的
layoutIfNeeded遍历的不是superview链,应该是subviews链
drawRect是对receiver的重绘,能获得context
setNeedDisplay在receiver标上一个需要被重新绘图的标记,在下一个draw周期自动重绘,iphone device的刷新频率是60hz,也就是1/60秒后重绘
UIView的setNeedsDisplay和setNeedsLayout方法。首先两个方法都是异步执行的。setNeedsDisplay会调用自动调用drawRect方法,这样可以拿到UIGraphicsGetCurrentContext,就可以画画了。而setNeedsLayout会默认调用layoutSubViews,就可以处理子视图中的一些数据。
综上两个方法都是异步执行的,layoutSubviews方便数据计算,drawRect方便视图重绘。
*************************Animation*********************
UIview的动画
@interface UIView(UIViewAnimation) + (void)beginAnimations:(NSString *)animationID context:(void *)context; // additional context info passed to will start/did stop selectors. begin/commit can be nested + (void)commitAnimations; // starts up any animations when the top level animation is commited // no getters. if called outside animation block, these setters have no effect. + (void)setAnimationDelegate:(id)delegate; // default = nil + (void)setAnimationWillStartSelector:(SEL)selector; // default = NULL. -animationWillStart:(NSString *)animationID context:(void *)context + (void)setAnimationDidStopSelector:(SEL)selector; // default = NULL. -animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context + (void)setAnimationDuration:(NSTimeInterval)duration; // default = 0.2 + (void)setAnimationDelay:(NSTimeInterval)delay; // default = 0.0 + (void)setAnimationStartDate:(NSDate *)startDate; // default = now ([NSDate date]) + (void)setAnimationCurve:(UIViewAnimationCurve)curve; // default = UIViewAnimationCurveEaseInOut + (void)setAnimationRepeatCount:(float)repeatCount; // default = 0.0. May be fractional + (void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses; // default = NO. used if repeat count is non-zero + (void)setAnimationBeginsFromCurrentState:(BOOL)fromCurrentState; // default = NO. If YES, the current view position is always used for new animations -- allowing animations to "pile up" on each other. Otherwise, the last end state is used for the animation (the default). + (void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView *)view cache:(BOOL)cache; // current limitation - only one per begin/commit block + (void)setAnimationsEnabled:(BOOL)enabled; // ignore any attribute changes while set. + (BOOL)areAnimationsEnabled; + (void)performWithoutAnimation:(void (^)(void))actionsWithoutAnimation NS_AVAILABLE_IOS(7_0); @end
例子:(头尾式)在viewDidload中调用
//UIView动画 - (void)test1{ //1.UIView动画 [UIView beginAnimations:nil context:nil]; //设置时间 [UIView setAnimationDuration:2]; //监听动画的完成 [UIView setAnimationDelegate:self]; [UIView setAnimationDidStopSelector:@selector(stop)]; //实现动画代码 self.imageView.center = CGPointMake(250, 250); //提交动画 [UIView commitAnimations]; } - (void)stop{ NSLog(@"%s",__func__); }
UIView动画的第二种方法:block
//2.UIView的block动画 - (void)test2{ [UIView animateWithDuration:2 animations:^{ self.imageView.center = CGPointMake(250, 250); } completion:^(BOOL finished) { NSLog(@"动画完成"); }]; }
UIView的转场动画使用:
//3.UIView的转场动画 - (void)test3{ [UIView transitionWithView:self.imageView duration:3 options:UIViewAnimationOptionTransitionFlipFromBottom animations:^{ self.imageView.image = [UIImage imageNamed:@"fc1f4134970a304e9a8f631ed0c8a786c8175ca1"]; } completion:^(BOOL finished) { NSLog(@"完成翻页"); }];//翻页效果:从底部进入 }