uiview_uiviewcontroller - CSDN
精华内容
参与话题
  • ios开发 之 UIView详解

    千次阅读 2017-06-19 17:00:17
    ios开发之UIView详解。

    ONNULL


    UIView详解

    //
    //  UIView.h
    //  ZMHeaderFile
    //
    //  Created by ZengZhiming on 2017/5/22.
    //  Copyright © 2017年 菜鸟基地. All rights reserved.
    //
    //  详解 UIResponder.h
    //  Version iOS 10.3
    //
    
    #import <Foundation/Foundation.h>
    #import <QuartzCore/QuartzCore.h>
    #import <UIKit/UIResponder.h>
    #import <UIKit/UIInterface.h>
    #import <UIKit/UIKitDefines.h>
    #import <UIKit/UIAppearance.h>
    #import <UIKit/UIDynamicBehavior.h>
    #import <UIKit/NSLayoutConstraint.h>
    #import <UIKit/UITraitCollection.h>
    #import <UIKit/UIFocus.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    /** 动画的曲线枚举 */
    typedef NS_ENUM(NSInteger, UIViewAnimationCurve) {
        UIViewAnimationCurveEaseInOut,  //!< 慢进慢出(默认值).
        UIViewAnimationCurveEaseIn,     //!< 慢进.
        UIViewAnimationCurveEaseOut,    //!< 慢出.
        UIViewAnimationCurveLinear,     //!< 匀速.
    };
    
    //!< UIView内容填充模式.
    typedef NS_ENUM(NSInteger, UIViewContentMode) {
        UIViewContentModeScaleToFill,       //!< 缩放内容到合适比例大小.
        UIViewContentModeScaleAspectFit,    //!< 缩放内容到合适的大小,边界多余部分透明.
        UIViewContentModeScaleAspectFill,   //!< 缩放内容填充到指定大小,边界多余的部分省略.
        UIViewContentModeRedraw,            //!< 重绘视图边界 (需调用 -setNeedsDisplay).
        UIViewContentModeCenter,            //!< 视图保持等比缩放.
        UIViewContentModeTop,               //!< 视图顶部对齐.
        UIViewContentModeBottom,            //!< 视图底部对齐.
        UIViewContentModeLeft,              //!< 视图左侧对齐.
        UIViewContentModeRight,             //!< 视图右侧对齐.
        UIViewContentModeTopLeft,           //!< 视图左上角对齐.
        UIViewContentModeTopRight,          //!< 视图右上角对齐.
        UIViewContentModeBottomLeft,        //!< 视图左下角对齐.
        UIViewContentModeBottomRight,       //!< 视图右下角对齐.
    };
    
    /** UIView动画过渡效果 */
    typedef NS_ENUM(NSInteger, UIViewAnimationTransition) {
        UIViewAnimationTransitionNone,          //!< 无效果.
        UIViewAnimationTransitionFlipFromLeft,  //!< 沿视图垂直中心轴左到右移动.
        UIViewAnimationTransitionFlipFromRight, //!< 沿视图垂直中心轴右到左移动.
        UIViewAnimationTransitionCurlUp,        //!< 由底部向上卷起.
        UIViewAnimationTransitionCurlDown,      //!< 由顶部向下展开.
    };
    
    /** 自动调整大小方式 */
    typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
        UIViewAutoresizingNone                 = 0,     //!< 不自动调整.
        UIViewAutoresizingFlexibleLeftMargin   = 1 << 0,//!< 自动调整与superView左边的距离,保证与superView右边的距离不变.
        UIViewAutoresizingFlexibleWidth        = 1 << 1,//!< 自动调整自己的宽度,保证与superView左边和右边的距离不变.
        UIViewAutoresizingFlexibleRightMargin  = 1 << 2,//!< 自动调整与superView的右边距离,保证与superView左边的距离不变.
        UIViewAutoresizingFlexibleTopMargin    = 1 << 3,//!< 自动调整与superView顶部的距离,保证与superView底部的距离不变.
        UIViewAutoresizingFlexibleHeight       = 1 << 4,//!< 自动调整自己的高度,保证与superView顶部和底部的距离不变.
        UIViewAutoresizingFlexibleBottomMargin = 1 << 5 //!< 自动调整与superView底部的距离,也就是说,与superView顶部的距离不变.
    };
    
    /** UIView动画选项 */
    typedef NS_OPTIONS(NSUInteger, UIViewAnimationOptions) {
        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, //!< 不继承父动画设置或动画类型.
        
        UIViewAnimationOptionCurveEaseInOut            = 0 << 16, //!< 动画先缓慢,然后逐渐加速.
        UIViewAnimationOptionCurveEaseIn               = 1 << 16, //!< 动画逐渐变慢.
        UIViewAnimationOptionCurveEaseOut              = 2 << 16, //!< 动画逐渐加速.
        UIViewAnimationOptionCurveLinear               = 3 << 16, //!< 动画匀速执行,默认值.
        
        UIViewAnimationOptionTransitionNone            = 0 << 20, //!< 没有转场动画效果.
        UIViewAnimationOptionTransitionFlipFromLeft    = 1 << 20, //!< 从左侧翻转效果.
        UIViewAnimationOptionTransitionFlipFromRight   = 2 << 20, //!< 从右侧翻转效果.
        UIViewAnimationOptionTransitionCurlUp          = 3 << 20, //!< 向后翻页的动画过渡效果.
        UIViewAnimationOptionTransitionCurlDown        = 4 << 20, //!< 向前翻页的动画过渡效果.
        UIViewAnimationOptionTransitionCrossDissolve   = 5 << 20, //!< 旧视图溶解消失显示下一个新视图的效果.
        UIViewAnimationOptionTransitionFlipFromTop     = 6 << 20, //!< 从上方翻转效果.
        UIViewAnimationOptionTransitionFlipFromBottom  = 7 << 20, //!< 从底部翻转效果.
        
        UIViewAnimationOptionPreferredFramesPerSecondDefault     = 0 << 24, //!< 默认的帧每秒.
        UIViewAnimationOptionPreferredFramesPerSecond60          = 3 << 24, //!< 60帧每秒的帧速率.
        UIViewAnimationOptionPreferredFramesPerSecond30          = 7 << 24, //!< 30帧每秒的帧速率.
        
    } NS_ENUM_AVAILABLE_IOS(4_0);
    
    typedef NS_OPTIONS(NSUInteger, UIViewKeyframeAnimationOptions) {
        UIViewKeyframeAnimationOptionLayoutSubviews            = UIViewAnimationOptionLayoutSubviews, //!< 动画过程中保证子视图跟随运动.
        UIViewKeyframeAnimationOptionAllowUserInteraction      = UIViewAnimationOptionAllowUserInteraction, //!< 动画过程中允许用户交互.
        UIViewKeyframeAnimationOptionBeginFromCurrentState     = UIViewAnimationOptionBeginFromCurrentState, //!< 所有视图从当前状态开始运行.
        UIViewKeyframeAnimationOptionRepeat                    = UIViewAnimationOptionRepeat, //!< 重复运行动画.
        UIViewKeyframeAnimationOptionAutoreverse               = UIViewAnimationOptionAutoreverse, //!< 动画运行到结束点后仍然以动画方式回到初始点.
        UIViewKeyframeAnimationOptionOverrideInheritedDuration = UIViewAnimationOptionOverrideInheritedDuration, //!< 忽略嵌套动画时间设置.
        UIViewKeyframeAnimationOptionOverrideInheritedOptions  = UIViewAnimationOptionOverrideInheritedOptions, //!< 不继承父动画设置或动画类型.
        
        UIViewKeyframeAnimationOptionCalculationModeLinear     = 0 << 10, //!< 连续运算模式, 默认.
        UIViewKeyframeAnimationOptionCalculationModeDiscrete   = 1 << 10, //!< 离散运算模式.
        UIViewKeyframeAnimationOptionCalculationModePaced      = 2 << 10, //!< 均匀执行运算模式.
        UIViewKeyframeAnimationOptionCalculationModeCubic      = 3 << 10, //!< 平滑运算模式.
        UIViewKeyframeAnimationOptionCalculationModeCubicPaced = 4 << 10  //!< 平滑均匀运算模式.
    } NS_ENUM_AVAILABLE_IOS(7_0);
    
    typedef NS_ENUM(NSUInteger, UISystemAnimation) {
        UISystemAnimationDelete,    //!< 系统删除动画
    } NS_ENUM_AVAILABLE_IOS(7_0);
    
    typedef NS_ENUM(NSInteger, UIViewTintAdjustmentMode) {
        UIViewTintAdjustmentModeAutomatic,  //!< 自动的,与父视图相同.
        
        UIViewTintAdjustmentModeNormal,     //!< 未经修改的.
        UIViewTintAdjustmentModeDimmed,     //!< 饱和、暗淡的原始色.
    } NS_ENUM_AVAILABLE_IOS(7_0);
    
    typedef NS_ENUM(NSInteger, UISemanticContentAttribute) {
        UISemanticContentAttributeUnspecified = 0,  //!< 未指定,默认值
        UISemanticContentAttributePlayback,         //!< 打开/ RW / FF等播放控制按钮
        UISemanticContentAttributeSpatial,          //!< 控制导致某种形式的定向改变UI中,如分段控制文本对齐方式或在游戏中方向键
        UISemanticContentAttributeForceLeftToRight, //!< 视图总是从左向右布局.
        UISemanticContentAttributeForceRightToLeft  //!< 视图总是从右向左布局.
    } NS_ENUM_AVAILABLE_IOS(9_0);
    
    @protocol UICoordinateSpace <NSObject>
    
    /** 将像素point由point所在视图转换到目标视图view中,返回在目标视图view中的像素值 */
    - (CGPoint)convertPoint:(CGPoint)point toCoordinateSpace:(id <UICoordinateSpace>)coordinateSpace NS_AVAILABLE_IOS(8_0);
    /** 将像素point由point所在视图转换到目标视图view中,返回在目标视图view中的像素值 */
    - (CGPoint)convertPoint:(CGPoint)point fromCoordinateSpace:(id <UICoordinateSpace>)coordinateSpace NS_AVAILABLE_IOS(8_0);
    /** 将rect由rect所在视图转换到目标视图view中,返回在目标视图view中的rect */
    - (CGRect)convertRect:(CGRect)rect toCoordinateSpace:(id <UICoordinateSpace>)coordinateSpace NS_AVAILABLE_IOS(8_0);
    /** 将rect从view中转换到当前视图中,返回在当前视图中的rect */
    - (CGRect)convertRect:(CGRect)rect fromCoordinateSpace:(id <UICoordinateSpace>)coordinateSpace NS_AVAILABLE_IOS(8_0);
    
    /** 获取bounds */
    @property (readonly, nonatomic) CGRect bounds NS_AVAILABLE_IOS(8_0);
    
    @end
    
    @class UIBezierPath, UIEvent, UIWindow, UIViewController, UIColor, UIGestureRecognizer, UIMotionEffect, CALayer, UILayoutGuide;
    
    NS_CLASS_AVAILABLE_IOS(2_0) @interface UIView : UIResponder <NSCoding, UIAppearance, UIAppearanceContainer, UIDynamicItem, UITraitEnvironment, UICoordinateSpace, UIFocusItem, CALayerDelegate>
    
    /** 返回主layer所使用的类 */
    #if UIKIT_DEFINE_AS_PROPERTIES
    @property(class, nonatomic, readonly) Class layerClass;
    #else
    + (Class)layerClass;
    #endif
    
    /** 通过Frame初始化UI对象 */
    - (instancetype)initWithFrame:(CGRect)frame NS_DESIGNATED_INITIALIZER;
    /** 用于xib初始化 */
    - (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER;
    
    /** 设置用户交互,默认YES允许用户交互 */
    @property(nonatomic,getter=isUserInteractionEnabled) BOOL userInteractionEnabled;
    /** 控件标记(父控件可以通过tag找到对应的子控件),默认为0 */
    @property(nonatomic)                                 NSInteger tag;
    /** 视图图层(可以用来设置圆角效果/阴影效果) */
    @property(nonatomic,readonly,strong)                 CALayer  *layer;
    
    /** 返回是否可以成为焦点, 默认NO */
    #if UIKIT_DEFINE_AS_PROPERTIES
    @property(nonatomic,readonly) BOOL canBecomeFocused NS_AVAILABLE_IOS(9_0);
    #else
    - (BOOL)canBecomeFocused NS_AVAILABLE_IOS(9_0);
    #endif
    /** 是否可以被聚焦 */
    @property (readonly, nonatomic, getter=isFocused) BOOL focused NS_AVAILABLE_IOS(9_0);
    
    /** 左右滑动翻转效果 */
    @property (nonatomic) UISemanticContentAttribute semanticContentAttribute NS_AVAILABLE_IOS(9_0);
    
    /** 获取视图的方向 */
    + (UIUserInterfaceLayoutDirection)userInterfaceLayoutDirectionForSemanticContentAttribute:(UISemanticContentAttribute)attribute NS_AVAILABLE_IOS(9_0);
    
    /** 获取相对于指定视图的界面方向 */
    + (UIUserInterfaceLayoutDirection)userInterfaceLayoutDirectionForSemanticContentAttribute:(UISemanticContentAttribute)semanticContentAttribute relativeToLayoutDirection:(UIUserInterfaceLayoutDirection)layoutDirection NS_AVAILABLE_IOS(10_0);
    
    /** 返回即时内容的布局的方向 */
    @property (readonly, nonatomic) UIUserInterfaceLayoutDirection effectiveUserInterfaceLayoutDirection NS_AVAILABLE_IOS(10_0);
    
    @end
    
    @interface UIView(UIViewGeometry)
    
    /** 位置和尺寸(以父控件的左上角为坐标原点(0, 0)) */
    @property(nonatomic) CGRect            frame;
    
    /** 位置和尺寸(以自己的左上角为坐标原点(0, 0)) */
    @property(nonatomic) CGRect            bounds;
    /** 中心点(以父控件的左上角为坐标原点(0, 0)) */
    @property(nonatomic) CGPoint           center;
    /** 变形属性(平移\缩放\旋转) */
    @property(nonatomic) CGAffineTransform transform;
    /** 视图内容的缩放比例 */
    @property(nonatomic) CGFloat           contentScaleFactor NS_AVAILABLE_IOS(4_0);
    
    /** 是否支持多点触摸,默认NO */
    @property(nonatomic,getter=isMultipleTouchEnabled) BOOL multipleTouchEnabled __TVOS_PROHIBITED;
    /** 是否独占整个Touch事件,默认NO */
    @property(nonatomic,getter=isExclusiveTouch) BOOL       exclusiveTouch __TVOS_PROHIBITED;
    
    /** 在指定点上点击测试指定事件 */
    - (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event;
    /** 判断当前的点击或者触摸事件的点是否在当前的view中,默认返回YES */
    - (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event;
    
    /** 将像素point由point所在视图转换到目标视图view中,返回在目标视图view中的像素值 */
    - (CGPoint)convertPoint:(CGPoint)point toView:(nullable UIView *)view;
    /** 将像素point由point所在视图转换到目标视图view中,返回在目标视图view中的像素值 */
    - (CGPoint)convertPoint:(CGPoint)point fromView:(nullable UIView *)view;
    /** 将rect由rect所在视图转换到目标视图view中,返回在目标视图view中的rect */
    - (CGRect)convertRect:(CGRect)rect toView:(nullable UIView *)view;
    /** 将rect从view中转换到当前视图中,返回在当前视图中的rect */
    - (CGRect)convertRect:(CGRect)rect fromView:(nullable UIView *)view;
    
    /** 自动调整子视图尺寸,默认YES则会根据autoresizingMask属性自动调整子视图尺寸 */
    @property(nonatomic) BOOL               autoresizesSubviews;
    /** 自动调整子视图与父视图的位置,默认UIViewAutoresizingNone */
    @property(nonatomic) UIViewAutoresizing autoresizingMask;
    
    /** 返回“最佳”大小适合给定的大小 */
    - (CGSize)sizeThatFits:(CGSize)size;
    /** 调整为刚好合适子视图大小 */
    - (void)sizeToFit;
    
    @end
    
    @interface UIView(UIViewHierarchy)
    
    /** 获取父视图 */
    @property(nullable, nonatomic,readonly) UIView       *superview;
    /** 获取所有子视图 */
    @property(nonatomic,readonly,copy) NSArray<__kindof UIView *> *subviews;
    /** 获取视图所在的Window */
    @property(nullable, nonatomic,readonly) UIWindow     *window;
    
    /** 从父视图中移除控件 */
    - (void)removeFromSuperview;
    /** 插入子视图(将子视图插入到subviews数组中index这个位置) */
    - (void)insertSubview:(UIView *)view atIndex:(NSInteger)index;
    /** 交换subviews数组中所存放子视图的位置 */
    - (void)exchangeSubviewAtIndex:(NSInteger)index1 withSubviewAtIndex:(NSInteger)index2;
    
    /** 添加子视图(新添加的视图在subviews数组的后面, 显示在最上面) */
    - (void)addSubview:(UIView *)view;
    /** 插入子视图(将子视图插到siblingSubview之下) */
    - (void)insertSubview:(UIView *)view belowSubview:(UIView *)siblingSubview;
    /** 插入子视图(将子视图插到siblingSubview之上) */
    - (void)insertSubview:(UIView *)view aboveSubview:(UIView *)siblingSubview;
    
    /** 将子视图拉到最上面来显示 */
    - (void)bringSubviewToFront:(UIView *)view;
    /** 将子视图拉到最下面来显示 */
    - (void)sendSubviewToBack:(UIView *)view;
    
    ##pragma mark - 系统自动调用(留给子类去实现)
    /** 添加自视图完成后调用 */
    - (void)didAddSubview:(UIView *)subview;
    /** 将要移除自视图时调用 */
    - (void)willRemoveSubview:(UIView *)subview;
    
    /** 将要移动到新父视图时调用 */
    - (void)willMoveToSuperview:(nullable UIView *)newSuperview;
    /** 移动到新父视图完成后调用 */
    - (void)didMoveToSuperview;
    /** 将要移动到新Window时调用 */
    - (void)willMoveToWindow:(nullable UIWindow *)newWindow;
    /** 移动到新Window完成后调用 */
    - (void)didMoveToWindow;
    
    /** 判断view是否为子类 */
    - (BOOL)isDescendantOfView:(UIView *)view;
    /** 通过tag获得对应的子视图 */
    - (nullable __kindof UIView *)viewWithTag:(NSInteger)tag;
    
    /** 对现在有布局有调整更改后,使用这个方法进行更新 */
    - (void)setNeedsLayout;
    /** 强制进行更新layout */
    - (void)layoutIfNeeded;
    
    /** 控件的frame发生改变的时候就会调用,一般在这里重写布局子控件的位置和尺寸 */
    - (void)layoutSubviews;
    
    /** 设置view之间的间距,该属性只对autolayout布局有效 */
    @property (nonatomic) UIEdgeInsets layoutMargins NS_AVAILABLE_IOS(8_0);
    /** 是否将当前视图的间距和父视图相同,默认是NO */
    @property (nonatomic) BOOL preservesSuperviewLayoutMargins NS_AVAILABLE_IOS(8_0);
    /** 改变view的layoutMargins这个属性时,会触发这个方法 */
    - (void)layoutMarginsDidChange NS_AVAILABLE_IOS(8_0);
    
    /** 视图间距引导 */
    @property(readonly,strong) UILayoutGuide *layoutMarginsGuide NS_AVAILABLE_IOS(9_0);
    
    /** 获取此区域的内的布局引导 */
    @property (nonatomic, readonly, strong) UILayoutGuide *readableContentGuide  NS_AVAILABLE_IOS(9_0);
    @end
    
    @interface UIView(UIViewRendering)
    
    /** 重写drawRect方法,在可以这里进行绘图操作。*/
    - (void)drawRect:(CGRect)rect;
    
    /** 标记整个视图的边界矩形需要重绘, 调用这个方法会自动调用drawRect方法 */
    - (void)setNeedsDisplay;
    /** 标记在指定区域内的视图的边界需要重绘, 调用这个方法会自动调用drawRect方法 */
    - (void)setNeedsDisplayInRect:(CGRect)rect;
    
    /** 是否裁剪超出Bounds范围的子控件,默认NO */
    @property(nonatomic)                 BOOL              clipsToBounds;
    /** 设置背景颜色,默认nil */
    @property(nullable, nonatomic,copy)  UIColor          *backgroundColor UI_APPEARANCE_SELECTOR;
    /** 设置透明度(范围0.0~1.0),默认1.0 */
    @property(nonatomic)                 CGFloat           alpha;
    /** 设置是否不透明,默认YES不透明 */
    @property(nonatomic,getter=isOpaque) BOOL              opaque;
    /** 视图重绘前是否先清理以前的内容,默认YES */
    @property(nonatomic)                 BOOL              clearsContextBeforeDrawing;
    /** 设置是否隐藏,默认NO不隐藏 */
    @property(nonatomic,getter=isHidden) BOOL              hidden;
    /** 内容显示的模式,默认UIViewContentModeScaleToFill */
    @property(nonatomic)                 UIViewContentMode contentMode;
    /** 拉伸属性,如图片拉伸 */
    @property(nonatomic)                 CGRect            contentStretch NS_DEPRECATED_IOS(3_0,6_0) __TVOS_PROHIBITED;
    
    /** 蒙板view */
    @property(nullable, nonatomic,strong)          UIView           *maskView NS_AVAILABLE_IOS(8_0);
    
    /** 改变应用程序的外观的颜色。默认为nil */
    @property(null_resettable, nonatomic, strong) UIColor *tintColor NS_AVAILABLE_IOS(7_0);
    
    /** 可以使tintColor变暗,因此整个视图层次变暗 */
    @property(nonatomic) UIViewTintAdjustmentMode tintAdjustmentMode NS_AVAILABLE_IOS(7_0);
    
    /** 覆盖这个方法的目的是为了当tintColor改变的时候自定义一些行为 */
    - (void)tintColorDidChange NS_AVAILABLE_IOS(7_0);
    
    @end
    
    @interface UIView(UIViewAnimation)
    
    /** 开始动画 */
    + (void)beginAnimations:(nullable NSString *)animationID context:(nullable void *)context;
    /** 提交动画 */
    + (void)commitAnimations;
    
    /** 设置动画代理, 默认nil */
    + (void)setAnimationDelegate:(nullable id)delegate;
    /** 动画将要开始时执行方法(必须要先设置动画代理), 默认NULL */
    + (void)setAnimationWillStartSelector:(nullable SEL)selector;
    /** 动画已结束时执行方法(必须要先设置动画代理), 默认NULL */
    + (void)setAnimationDidStopSelector:(nullable SEL)selector;
    /** 设置动画时长, 默认0.2秒 */
    + (void)setAnimationDuration:(NSTimeInterval)duration;
    /** 动画延迟执行时间, 默认0.0秒 */
    + (void)setAnimationDelay:(NSTimeInterval)delay;
    /** 设置在动画块内部动画属性改变的开始时间, 默认now ([NSDate date]) */
    + (void)setAnimationStartDate:(NSDate *)startDate;
    /** 设置动画曲线, 默认UIViewAnimationCurveEaseInOut */
    + (void)setAnimationCurve:(UIViewAnimationCurve)curve;
    /** 动画的重复播放次数, 默认0 */
    + (void)setAnimationRepeatCount:(float)repeatCount;
    /** 设置是否自定翻转当前的动画效果, 默认NO */
    + (void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses;
    /** 设置动画从当前状态开始播放, 默认NO */
    + (void)setAnimationBeginsFromCurrentState:(BOOL)fromCurrentState;
    
    /** 在动画块中为视图设置过渡动画 */
    + (void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView *)view cache:(BOOL)cache;
    
    /** 设置是否激活动画 */
    + (void)setAnimationsEnabled:(BOOL)enabled;
    /** 返回一个布尔值表示动画是否结束 */
    #if UIKIT_DEFINE_AS_PROPERTIES
    @property(class, nonatomic, readonly) BOOL areAnimationsEnabled;
    #else
    + (BOOL)areAnimationsEnabled;
    #endif
    /** 先检查动画当前是否启用,然后禁止动画,执行block内的方法,最后重新启用动画,而且这个方法不会阻塞基于CoreAnimation的动画 */
    + (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
    
    @interface UIView(UIViewAnimationWithBlocks)
    
    /** 用于对一个或多个视图的改变的持续时间、延时、选项动画完成时的操作 */
    + (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);
    
    /** 用于对一个或多个视图的改变的持续时间、选项动画完成时的操作,默认:delay = 0.0, options = 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, completion = NULL */
    + (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations NS_AVAILABLE_IOS(4_0);
    
    /** 使用与物理弹簧运动相对应的定时曲线执行视图动画 */
    + (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);
    
    /** 为指定的容器视图创建转换动画 */
    + (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);
    
    /** 使用给定的参数在指定视图之间创建转换动画 */
    + (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
    
    /** 在一个或多个视图上执行指定的系统提供的动画,以及定义的可选并行动画 */
    + (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
    
    /** UIView的关键帧动画 */
    @interface UIView (UIViewKeyframeAnimations)
    
    /** 创建一个动画块对象,可用于为当前视图设置基于关键帧的动画 */
    + (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);
    /** 添加指定开始时间、持续时间的关键帧动画(起始和持续时间是0.0和1.0之间的值) */
    + (void)addKeyframeWithRelativeStartTime:(double)frameStartTime relativeDuration:(double)frameDuration animations:(void (^)(void))animations NS_AVAILABLE_IOS(7_0);
    
    @end
    
    @interface UIView (UIViewGestureRecognizers)
    
    /** 当前视图所附加的所有手势识别器 */
    @property(nullable, nonatomic,copy) NSArray<__kindof UIGestureRecognizer *> *gestureRecognizers NS_AVAILABLE_IOS(3_2);
    
    /** 添加一个手势识别器 */
    - (void)addGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer NS_AVAILABLE_IOS(3_2);
    /** 移除一个手势识别器 */
    - (void)removeGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer NS_AVAILABLE_IOS(3_2);
    
    /** 开始一个手势识别器 */
    - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer NS_AVAILABLE_IOS(6_0);
    
    @end
    
    @interface UIView (UIViewMotionEffects)
    
    /** 添加运动效果,当倾斜设备时视图稍微改变其位置 */
    - (void)addMotionEffect:(UIMotionEffect *)effect NS_AVAILABLE_IOS(7_0);
    
    /** 移除运动效果 */
    - (void)removeMotionEffect:(UIMotionEffect *)effect NS_AVAILABLE_IOS(7_0);
    
    /** 所有添加的运动效果 */
    @property (copy, nonatomic) NSArray<__kindof UIMotionEffect *> *motionEffects NS_AVAILABLE_IOS(7_0);
    
    @end
    
    
    typedef NS_ENUM(NSInteger, UILayoutConstraintAxis) {
        UILayoutConstraintAxisHorizontal = 0,   //!< 水平约束.
        UILayoutConstraintAxisVertical = 1      //!< 竖直约束.
    };
    
    
    @interface UIView (UIConstraintBasedLayoutInstallingConstraints)
    
    /** 获取所有约束 */
    @property(nonatomic,readonly) NSArray<__kindof NSLayoutConstraint *> *constraints NS_AVAILABLE_IOS(6_0);
    
    /** 添加一个约束 */
    - (void)addConstraint:(NSLayoutConstraint *)constraint NS_AVAILABLE_IOS(6_0);
    /** 添加多个约束 */
    - (void)addConstraints:(NSArray<__kindof NSLayoutConstraint *> *)constraints NS_AVAILABLE_IOS(6_0);
    /** 移除一个约束 */
    - (void)removeConstraint:(NSLayoutConstraint *)constraint NS_AVAILABLE_IOS(6_0);
    /** 移除多个约束 */
    - (void)removeConstraints:(NSArray<__kindof NSLayoutConstraint *> *)constraints NS_AVAILABLE_IOS(6_0);
    @end
    
    
    @interface UIView (UIConstraintBasedLayoutCoreMethods)
    /** 更新视图和其子视图的约束 */
    - (void)updateConstraintsIfNeeded NS_AVAILABLE_IOS(6_0);
    /** 为视图更新约束,可以重写这个方法来设置当前view局部的布局约束 */
    - (void)updateConstraints NS_AVAILABLE_IOS(6_0) NS_REQUIRES_SUPER;
    /** 视图的约束是否需要更新 */
    - (BOOL)needsUpdateConstraints NS_AVAILABLE_IOS(6_0);
    /** 设置视图的约束需要更新,调用这个方法,系统会调用updateConstraints去更新布局 */
    - (void)setNeedsUpdateConstraints NS_AVAILABLE_IOS(6_0);
    @end
    
    
    @interface UIView (UIConstraintBasedCompatibility)
    
    /** 是否启用自动布局约束,默认YES. IB默认是NO */
    @property(nonatomic) BOOL translatesAutoresizingMaskIntoConstraints NS_AVAILABLE_IOS(6_0);
    
    /** 是否使用约束布局 */
    #if UIKIT_DEFINE_AS_PROPERTIES
    @property(class, nonatomic, readonly) BOOL requiresConstraintBasedLayout NS_AVAILABLE_IOS(6_0);
    #else
    + (BOOL)requiresConstraintBasedLayout NS_AVAILABLE_IOS(6_0);
    #endif
    
    @end
    
    
    @interface UIView (UIConstraintBasedLayoutLayering)
    
    /** 返回给定框架的视图的对齐矩阵 */
    - (CGRect)alignmentRectForFrame:(CGRect)frame NS_AVAILABLE_IOS(6_0);
    /** 返回给定对齐矩形的视图的frame */
    - (CGRect)frameForAlignmentRect:(CGRect)alignmentRect NS_AVAILABLE_IOS(6_0);
    
    /** 返回从视图的frame上定义的对齐矩阵的边框 */
    #if UIKIT_DEFINE_AS_PROPERTIES
    @property(nonatomic, readonly) UIEdgeInsets alignmentRectInsets NS_AVAILABLE_IOS(6_0);
    #else
    - (UIEdgeInsets)alignmentRectInsets NS_AVAILABLE_IOS(6_0);
    #endif
    
    /** 返回满足基线约束条件的视图 */
    - (UIView *)viewForBaselineLayout NS_DEPRECATED_IOS(6_0, 9_0, "Override -viewForFirstBaselineLayout or -viewForLastBaselineLayout as appropriate, instead") __TVOS_PROHIBITED;
    
    /** 返回用于满足第一基线约束的视图 */
    @property(readonly,strong) UIView *viewForFirstBaselineLayout NS_AVAILABLE_IOS(9_0);
    
    /** 返回用于满足上次基线约束的视图 */
    @property(readonly,strong) UIView *viewForLastBaselineLayout NS_AVAILABLE_IOS(9_0);
    
    
    UIKIT_EXTERN const CGFloat UIViewNoIntrinsicMetric NS_AVAILABLE_IOS(6_0); // -1
    /** 返回接收对象的原本大小 */
    #if UIKIT_DEFINE_AS_PROPERTIES
    @property(nonatomic, readonly) CGSize intrinsicContentSize NS_AVAILABLE_IOS(6_0);
    #else
    - (CGSize)intrinsicContentSize NS_AVAILABLE_IOS(6_0);
    #endif
    /** 废除视图原本内容的size */
    - (void)invalidateIntrinsicContentSize NS_AVAILABLE_IOS(6_0);
    
    /** 设置当视图要变大时,视图的压缩改变方式,返回一个优先权(确定view有多大的优先级阻止自己变大) */
    - (UILayoutPriority)contentHuggingPriorityForAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);
    /** 设置放先权 */
    - (void)setContentHuggingPriority:(UILayoutPriority)priority forAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);
    
    /** 设置当视图要变小时,视图的压缩改变方式,是水平缩小还是垂直缩小,并返回一个优先权(确定有多大的优先级阻止自己变小) */
    - (UILayoutPriority)contentCompressionResistancePriorityForAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);
    /** 设置优先权 */
    - (void)setContentCompressionResistancePriority:(UILayoutPriority)priority forAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);
    @end
    
    // Size To Fit
    
    UIKIT_EXTERN const CGSize UILayoutFittingCompressedSize NS_AVAILABLE_IOS(6_0);
    UIKIT_EXTERN const CGSize UILayoutFittingExpandedSize NS_AVAILABLE_IOS(6_0);
    
    @interface UIView (UIConstraintBasedLayoutFittingSize)
    /** 返回满足持有约束的视图的size */
    - (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize NS_AVAILABLE_IOS(6_0);
    /** 返回满足它所包含的约束的视图的大小 */
    - (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize withHorizontalFittingPriority:(UILayoutPriority)horizontalFittingPriority verticalFittingPriority:(UILayoutPriority)verticalFittingPriority NS_AVAILABLE_IOS(8_0);
    @end
    
    @interface UIView (UILayoutGuideSupport)
    
    /** 此视图拥有布局向导对象的数组 */
    @property(nonatomic,readonly,copy) NSArray<__kindof UILayoutGuide *> *layoutGuides NS_AVAILABLE_IOS(9_0);
    
    /** 向视图中添加布局向导 */
    - (void)addLayoutGuide:(UILayoutGuide *)layoutGuide NS_AVAILABLE_IOS(9_0);
    
    /** 向视图中添加布局向导 */
    - (void)removeLayoutGuide:(UILayoutGuide *)layoutGuide NS_AVAILABLE_IOS(9_0);
    @end
    
    @class NSLayoutXAxisAnchor,NSLayoutYAxisAnchor,NSLayoutDimension;
    @interface UIView (UIViewLayoutConstraintCreation)
    /** 布局视图的前缘框的布局锚点 */
    @property(readonly, strong) NSLayoutXAxisAnchor *leadingAnchor NS_AVAILABLE_IOS(9_0);
    /** 布局视图的后缘边框的布局锚点 */
    @property(readonly, strong) NSLayoutXAxisAnchor *trailingAnchor NS_AVAILABLE_IOS(9_0);
    /** 布局视图的左边框的布局锚点 */
    @property(readonly, strong) NSLayoutXAxisAnchor *leftAnchor NS_AVAILABLE_IOS(9_0);
    /** 布局视图的右边框的布局锚点 */
    @property(readonly, strong) NSLayoutXAxisAnchor *rightAnchor NS_AVAILABLE_IOS(9_0);
    /** 布局视图的顶边框的布局锚点 */
    @property(readonly, strong) NSLayoutYAxisAnchor *topAnchor NS_AVAILABLE_IOS(9_0);
    /** 布局视图的底边框的布局锚点 */
    @property(readonly, strong) NSLayoutYAxisAnchor *bottomAnchor NS_AVAILABLE_IOS(9_0);
    /** 布局视图的宽度 */
    @property(readonly, strong) NSLayoutDimension *widthAnchor NS_AVAILABLE_IOS(9_0);
    /** 布局视图的高度 */
    @property(readonly, strong) NSLayoutDimension *heightAnchor NS_AVAILABLE_IOS(9_0);
    /** 布局视图的水平中心轴 */
    @property(readonly, strong) NSLayoutXAxisAnchor *centerXAnchor NS_AVAILABLE_IOS(9_0);
    /** 布局视图的垂直中心轴 */
    @property(readonly, strong) NSLayoutYAxisAnchor *centerYAnchor NS_AVAILABLE_IOS(9_0);
    /** 一个代表对视图中的文本的最高线基线布置锚 */
    @property(readonly, strong) NSLayoutYAxisAnchor *firstBaselineAnchor NS_AVAILABLE_IOS(9_0);
    /** 一个代表对视图中的文本的最低线基线布置锚 */
    @property(readonly, strong) NSLayoutYAxisAnchor *lastBaselineAnchor NS_AVAILABLE_IOS(9_0);
    
    @end
    
    @interface UIView (UIConstraintBasedLayoutDebugging)
    
    /** 获得实体在不同方向上所有的布局约束 */
    - (NSArray<__kindof NSLayoutConstraint *> *)constraintsAffectingLayoutForAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);
    
    /** 可以知道当前视图的布局是否会有歧义 */
    #if UIKIT_DEFINE_AS_PROPERTIES
    @property(nonatomic, readonly) BOOL hasAmbiguousLayout NS_AVAILABLE_IOS(6_0);
    #else
    - (BOOL)hasAmbiguousLayout NS_AVAILABLE_IOS(6_0);
    #endif
    
    /** 这个方法会随机改变视图的layout到另外一个有效的layout。这样我们就可以很清楚的看到哪一个layout导致了整体的布局约束出现了错误,或者我们应该增加更多的布局约束 */
    - (void)exerciseAmbiguityInLayout NS_AVAILABLE_IOS(6_0);
    @end
    
    /** 约束调试,只在DEBUG环境下被调用 */
    @interface UILayoutGuide (UIConstraintBasedLayoutDebugging)
    
    /** 获得实体在不同方向上所有的布局约束 */
    - (NSArray<__kindof NSLayoutConstraint *> *)constraintsAffectingLayoutForAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(10_0);
    
    /** 可以知道当前视图的布局是否会有歧义 */
    #if UIKIT_DEFINE_AS_PROPERTIES
    @property(nonatomic, readonly) BOOL hasAmbiguousLayout NS_AVAILABLE_IOS(10_0);
    #else
    - (BOOL)hasAmbiguousLayout NS_AVAILABLE_IOS(10_0);
    #endif
    @end
    
    #pragma mark - View状态保存恢复
    @interface UIView (UIStateRestoration)
    /** 标示是否支持保存,恢复视图状态信息 */
    @property (nullable, nonatomic, copy) NSString *restorationIdentifier NS_AVAILABLE_IOS(6_0);
    /** 保存视图状态相关的信息 */
    - (void) encodeRestorableStateWithCoder:(NSCoder *)coder NS_AVAILABLE_IOS(6_0);
    /** 恢复和保持视图状态相关信息 */
    - (void) decodeRestorableStateWithCoder:(NSCoder *)coder NS_AVAILABLE_IOS(6_0);
    @end
    
    #pragma mark - View快照
    @interface UIView (UISnapshotting)
    /** 将当前显示的view截取成一个新的view */
    - (nullable UIView *)snapshotViewAfterScreenUpdates:(BOOL)afterUpdates NS_AVAILABLE_IOS(7_0);
    /** 缩放一个view默认是从中心点进行缩放的 */
    - (nullable UIView *)resizableSnapshotViewFromRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates withCapInsets:(UIEdgeInsets)capInsets NS_AVAILABLE_IOS(7_0);
    /** 屏幕快照 */
    - (BOOL)drawViewHierarchyInRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates NS_AVAILABLE_IOS(7_0);
    @end
    
    NS_ASSUME_NONNULL_END
    



    ONNULL





    展开全文
  • UIView详解

    千次阅读 2018-07-01 15:53:55
    UIView表示屏幕上的一块矩形区域,它在App中占有绝对重要的地位,因为IOS中几乎所有可视化控件都是UIView的子类。负责渲染区域的内容,并且响应该区域内发生的触摸事件UIView的功能 1.管理矩形区域里的内容2.处理...

    UIView表示屏幕上的一块矩形区域,它在App中占有绝对重要的地位,因为IOS中几乎所有可视化控件都是UIView的子类。负责渲染区域的内容,并且响应该区域内发生的触摸事件


    UIView的功能 1.管理矩形区域里的内容2.处理矩形区域中的事件3.子视图的管理 4.还能实现动画  UIView的子类也具有这些功能


    下图就是视图的内层次

                                            

    1)三个结构体 CGPoint、CGSize、CGRect

    1.  CGPoint

    struct CGPoint {  
      CGFloat x;  
      CGFloat y;  
    };  

    typedef struct CGPoint CGPoint;  
    看到这个想必你已经懂了,不再解释。

    2.CGSize

    struct CGSize {  
      CGFloat width;  
      CGFloat height;  
    };  

    typedef struct CGSize CGSize;  
    不解释。

    3.CGRect

    struct CGRect {  
      CGPoint origin;  //偏移是相对父视图的  
      CGSize size;  
    };  
    typedef struct CGRect CGRect;  
    同样 不解释。

    这三个结构体均在一个头文件里:CGGeometry.h

    2)视图的最基本属性

    frame和center都是相对于父视图的,bounds是相对于自身的


    frame   是CGRect  frame的origin是相对于父视图的左上角原点(0,0)的位置,改变视图的frame会改变center

    center  是CGPoint  指的就是整个视图的中心点,改变视图的center也会改变frame

    bounds 是CGRect  是告诉子视图本视图的原点位置(通俗的说就是,子视图的frame的origin与父视图的bounds的origin的差,就是子视图相对于父视图左上角的位置,如果结果为负,则子视图在父视图外)

    通过addSubview:这个方法添加子类,不管谁添加它,只要越晚添加,视图就在越上层

    移除父视图也会把它得子视图移除

    frame和bounds是UIView中的两个属性(property)。

    frame指的是:该view在父view坐标系统中的位置和大小。(参照点是父亲的坐标系统)

    bounds指的是:该view在本身坐标系统中 的位置和大小。(参照点是本身坐标系统)

    -(CGRect)frame{
    returnCGRectMake(self.frame.origin.x,self.frame.origin.y,self.frame.size.width,self.frame.size.height);
    }
    
    -(CGRect)bounds{
    returnCGRectMake(0,0,self.frame.size.width,self.frame.size.height);
    }



    3)几个基本界面元素:window(窗口)、视图(view)

    1.UIView

    下面来认识一下UIView类,这个类继承自UIResponder,看这个名字我们就知道它是负责显示的画布,如果说把window比作画框的话。我们就是不断地在画框上移除、更换或者叠加画布,或者在画布上叠加其他画布,大小当然 由绘画者来决定了。有了画布,我们就可以在上面任意施为了。很多简单的东西我会把库里面的内容贴出来,如果东西太多贴出来就不太好,朋友们自己去库文件里面看吧。这个类在UIView.h里面。下面我们先学习一些基础的东西,其他的东东会在以后慢慢展开。
     
    UIView* myView =[[ UIView alloc]initWithFrame:CGRectMake(0.0,0.0,200.0,400.0)];     //这里创建了一块画布,定义了相对于父窗口的位置, 以及大小。  

    我们可以把这块画布加到其他画布上,具体方法后面会讲到。我们还可以在这块画布上画上其它好玩的东东,具体情形后面会一一讲解。



    2.UIWindow

    UIWindow继承自UIView,关于这一点可能有点逻辑障碍,画框怎么继承自画布呢?不要过于去专牛角尖,画框的形状不就是跟画布一样吗?拿一块画布然后用一些方法把它加强,是不是可以当一个画框用呢?这也是为什么 一个view可以直接加到另一个view上去的原因了。
    看一下系统的初始化过程(在application didFinishLauchingWithOptions里面):

    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];  
    self.window.backgroundColor = [UIColor grayColor];       //给window设置一个背景色  
     
    [self.window makeKeyAndVisible];     //让window显示出来  


    3.UIScreen类代表了屏幕,通过这个类我们可以获取一些想要的东东

    CGRect screenBounds = [ [UIScreen mainScreen]bounds];    //返回的是带有状态栏的Rect 
    CGRect viewBounds = [ [UIScreen mainScreen]applicationFrame];    //不包含状态栏的Rect  
     
    //screenBounds 与 viewBounds 均是相对于设备屏幕来说的  
    //所以 screenBounds.origin.x== 0.0 ;   screenBounds.oringin.y = 0.0;     
    screenBounds.size.width == 320;  screenBounds.size.height == 480(或者其他分辨率有所差异)  
    //所以 screenBounds.origin.x== 0.0 ;   screenBounds.oringin.y = 20.0;(因为状态栏的高度是20像素)   screenBounds.size.width == 320;  screenBounds.size.height == 480  
    //取得StatusBar的位置和大小  
    [self.view addSubview:theToolbar];  
    CGRect statusBarRect = [[UIApplication sharedApplication]statusBarFrame];  
      
    NSLog(@\"%@\", NSStringFromCGRect(statusBarRect));

    4.实战演练



    没结束我会用一个综合的 例子来总结我的学习成果,彻底理解所学,我觉得既然选择写代码,就要理解原理,否则只知其然不知其所以然是不能做一个好的程序员的。
    新建一个工程选择Empty Application   名字为LW1
2)在application didFinishLaunchingWithOptions里面,你会发现系统已经建好一个画框了,我们现在就用系统帮我们建好的画框,你当然也可以自己建一个画框,不过没这个必要了,忘了讲了,一个应用程序只能有一个画框。

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions  
    {  
     
        self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];//系统帮你建画框  
     
         
     
        //自己测试一下 bounds与aplicationFrame的区别  
        CGRect bound = [[UIScreen mainScreen]bounds];  
        NSLog(@"boundwidth:%f    boundheight:%f ",bound.size.width, bound.size.height);  
        NSLog(@"boundx:%f    boundy:%f ",bound.origin.x, bound.origin.y);  
          
        CGRect appBound = [[UIScreen mainScreen]applicationFrame];  
        NSLog(@"appBoundwidth:%f appBoundheight:%f "  
               ,appBound.size.width,appBound.size.height);  
        NSLog(@"appBoundx:%f    appBoundy:%f ",appBound.origin.x, appBound.origin.y);  
      
        //画第一块画布然涂成蓝色,大小是320 X 100  
        CGRect CGone = CGRectMake(0.0, 0.0, 320, 100);//画个矩形,初始化位置与大小  
     
        UIView *v_one = [[UIView alloc]initWithFrame:CGone];//初始化view  
     
        v_one.backgroundColor = [UIColor blueColor];// 涂成蓝色  
     
        [self.window addSubview:v_one];//直接加到画框上  
          
     
        //第二块注意它的位置  
        CGRect CGtwo = CGRectMake(0.0, 100, 160, 100);//画个矩形、初始化位置与大小  
     
        UIView *v_two = [[UIView alloc]initWithFrame:CGtwo];//初始化view  
        v_two.backgroundColor = [UIColor redColor];//涂成红色  
     
        [self.window addSubview:v_two];//叠加到画框  
     
        //第三块注意他的位置  
        CGRect CGthree = CGRectMake(160, 100, 160, 100);
        UIView *v_three = [[UIView alloc]initWithFrame:CGthree];
        v_three.backgroundColor = [UIColor greenColor];
        [self.window addSubview:v_three];
     
        //第四块注意它的位置  
        CGRect CGfour = CGRectMake(0.0, 260, 320, 200);
        UIView *v_four = [[UIView alloc]initWithFrame:CGfour];
        v_four.backgroundColor = [UIColor orangeColor]; 
                [self.window addSubview:v_four];//  
       //第五块,计算一下它的位置,看看它的效果,  
        //你可以让试一下把这段代码移到第一快初始化的上面试试,会有意想不到的效果  
        CGRect CGfive = CGRectMake(100, 150, 160, 200);  
        UIView *v_five = [[UIView alloc]initWithFrame:CGfive];  
        v_five.backgroundColor = [UIColor yellowColor];  
        [self.window addSubview:v_five];  
        self.window.backgroundColor = [UIColor grayColor];
        [self.window makeKeyAndVisible];
     
        //最后记得release  
       [v_one  release];  
       [v_two  release];  
       [v_three  release];  
       [v_four  release];  
       [v_five  release];  
        return YES;  
    }  


    4)UIView的方法

    一个 UIView 里面可以包含许多的 Subview(其他的 UIView),而这些 Subview 彼此之间是有所谓的阶层关系,这有点类似绘图软体中图层的概念,下面程式码示演示了几个在管理图层(Subview)上常用的方法,其程式码如下。
     
    1.首先是大家最常使用的新增和移除Subview。
     
    [Subview removeFromSuperview];     //将Subview从当前的UIView中移除 
    [UIView addSubview:Subview];     //替UIView增加一个Subview  

    2.在UIView中将Subview往前或是往后移动一个图层,往前移动会覆盖住较后层的 Subview,而往后移动则会被较上层的Subview所覆盖。
     
    [UIView bringSubviewToFront:Subview];       //将Subview往前移动一个图层(与它的前一个图层对调位置)//将Subview往前移动一个图层(与它的前一个图层对调位置)
    [UIView sendSubviewToBack:Subview];      //将Subview往后移动一个图层(与它的后一个图层对调位置)
      
    3.在UIView中使用索引Index交换两的Subview彼此的图层层级。

    [UIView exchangeSubviewAtIndex:indexA withSubviewAtIndex:indexB];    //交换两个图层  
     
    4.使用Subview的变数名称取得它在UIView中的索引值(Index )。
    NSInteger index = [[UIView subviews] indexOfObject:Subview名称];       //取得Index  
     
    5.替Subview加上NSInteger 的註记(Tag)好让之后它们分辨彼此。
      
    [Subview setTag:NSInteger];       //加上标记
    [UIView viewWithTag:NSInteger];  //通过标记得到view 返回值为UIView
     
    6.最后是取得UIView中所有的Subview,呼叫此方法会传回一个 NSArray,并以由后往前的顺序列出这些 Subview,下图中是列出范例图片里Root中所有的Subview。
     
    [UIView subviews] ;        //取的UIView下的所有Subview 
    展开全文
  • UIView,UIViewController的使用

    千次阅读 2018-11-01 19:56:41
    UIView,UIViewController的使用 上节回顾 上节课讲解了UIButton,UITextField的使用,并且综合前面讲解的UILabel的做了一个简易的登录界面。 本节内容 UIView的介绍与使用 UIViewController的介绍与使用 控件之间的...

    UIView,UIViewController的使用

    上节回顾

    上节课讲解了UIButton,UITextField的使用,并且综合前面讲解的UILabel的做了一个简易的登录界面。

    本节内容

    1. UIView的介绍与使用
    2. UIViewController的介绍与使用
    3. 控件之间的继承关系

    UIView

    UIView表示屏幕上的一块矩形区域,它在App中占有绝对重要的地位,因为iOS中几乎所有可视化控件都是UIView的子类。负责渲染区域的内容,并且响应该区域内发生的触摸事件。

    所以我们以上介绍的几个控件都是UIView的子类。我们先介绍UIView的三个结构体CGPoint,CGRect,CGSize。

    1. CGPoint
    struct CGPoint {  
      CGFloat x;  
      CGFloat y;  
    };  
    typedef struct CGPoint CGPoint;  
    

    CGPoint确定了view的起始坐标。
    UIView的坐标是从屏幕的左上角开始,如图所示
    UIView的坐标系

    1. CGSize
    struct CGSize {  
      CGFloat width;  
      CGFloat height;  
    };  
    typedef struct CGSize CGSize;  
    

    CGSize确定view的长宽。

    1. CGRect
    struct CGRect {  
      CGPoint origin;  //偏移是相对父视图的  
      CGSize size;  
    }; 
    typedef struct CGRect CGRect
    

    CGRect确定了整个视图位置和大小。就像前面讲到的UIButton中的初始化

        UIButton *btn1 = [[UIButton alloc]initWithFrame:CGRectMake(50, 200, 100, 20)];
    

    这里的frame就是使用CGRect确定的。
    然后是UIView的一些基本属性

    1. frame
    //描述当前视图在父视图中的位置和大小
    @property(nonatomic) CGRect frame;
    
    1. bounds
    //描述当前视图在其自身坐标系统中的位置和大小
    @property(nonatomic) CGRect bounds;
    

    bounds是CGRect是告诉子视图本视图的原点位置(通俗的说就是,子视图的frame的origin与父视图的bounds的origin的差,就是子视图相对于父视图左上角的位置,如果结果为负,则子视图在父视图外)

    1. center
    //描述当前视图中心点在父视图中的位置
    @property(nonatomic)CGPoint center;
    

    改变frame会改变center。同理改变center也会改变frame。
    frame和center都是相对于父视图的,bounds是相对于自身的。

    //形变属性(平移\缩放\旋转)
    @property(nonatomic)CGAffineTransform  transform;
    
    //YES:支持多触点
    @property(nonatomic,getter=isMultipleTouchEnabled)BOOL multipleTouchEnabled; //default is NO
    
    //YES:超出控件边框范围的内容都剪掉
    @property(nonatomic)BOOL clipsToBounds;
    
    //YES:超出控件边框范围的内容都剪掉
    @property(nonatomic)BOOL clipsToBounds;
    
    //背景色
    @property(nonatomic,copy)UIColor *backgroundColor;
    //default is nil;
    
    //YES:不透明 NO:透明
    @property(nonatomic,getter=isOpaque)BOOL  opaque;
    //default is YES
    
    //YES:隐藏  NO:显示
    @property(nonatomic,getter=isHidden)BOOL  hidden;
    
    //内容模式
    @property(nonatomic) UIViewContentMode contentMode
    //default is UIViewContentModeScaleToFill
    

    UIView中含有的元素

    在这里插入图片描述
    图层关系

    1. UIWindow

    UIWindow是UIView的子类,它相当于一个画板,UIView则是一块画布,UIView在UIWindow上,其他的控件就相当于一幅画中的各个元素(object)。
    我们在一个应用起始时需要创建一个window来防止我们的UIView
    window的初始化方法(在application didFinishLauchingWithOptions里面):

    self.window = [[[UIWindow alloc] 
    initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
    self.window.backgroundColor = [UIColor blueColor];
    //给window设置一个背景色
    [self.window makeKeyAndVisible];
    //让window显示出来
    
    1. UIScreen
      UIScreen意如其名,它代表了屏幕,通过它我们可以获取一些我们想要的东西,比如整个屏幕的范围等等。

    UIView的常用方法

    1. addSubview: 添加一个子视图并让它在最上面显示出来。
     (void)addSubview:(UIView *)view 
    //添加一个子视图到接收者并让它在最上面显示出来
    

    比如我们之前用到的

    [self.view addSubview:btn];
    
    1. bringSubviewToFront: 把指定的子视图移动到顶层
      (void)bringSubviewToFront:(UIView *)view 
    //把指定的子视图移动到顶层 
    //将view往前移动一个图层(与它的前一个图层对调位置)
    
    1. initWithFrame: 初始化并返回一个新的拥有特定帧矩形的视图对象
    (id)initWithFrame:(CGRect)aRect 
    /*参数:
    aRect 一个帧矩形用来创建视图对象。原始的帧在它的父视图的坐标系中。设置这个属性用来改变中心和边界属性。 
    返回值: 一个初始化的视图对象,如果没有被创建那就返回nil */
    
    1. insertSubview:atIndex: 插入视图到指定的索引
    - (void)insertSubview:(UIView *)view atIndex:(NSInteger)index 
    参数: 
    view 插入的视图,这个值不能是nil 
    index 子视图索引从0开始并且不能大于子视图的数量 
    
    
    1. sizeToFit 调整大小并移动接收者视图大小所以他包含了他的子视图
     (void)sizeToFit 
    

    以上是在UIView中常用的方法与属性。其他见开发者文档。

    UIViewController

    UIViewController是视图控制器,它由控制器+view组成。
    它能够完成一下功能:

    1. 控制视图的代码逻辑,并拥有自己的视图
    2. 控制器与控制器之间的通信
    3. 视图与Model之间的传值
    4. 添加子控制器
    5. 展示界面信息
    6. 添加子控件

    使用步骤

    1. 初始化
    2. 将view加载到视图中
    3. 加载完view后添加子视图或控件
    4. layout布局调整
    5. 各个控件或子视图的操作逻辑添加
    6. 销毁或调入下一界面
    - (void)viewDidLoad {
        NSLog(@"%s,视图已经加载出来了",__func__);
        [super viewDidLoad];
    }
    
    

    我们在应用中所有的子视图或子控件的逻辑都要在视图加载完后才能实现,所以我们常用的方法就是viewDidLoad.

    控件间的继承关系

    首先说一下继承

    1. 使用继承可以实现代码的复用,减少代码冗余;
    2. Objective-C中一个类可以继承另一个类;
    3. 被继承的类称为父类或超类(基类);
    4. 继承的类称为子类或派生类;(孩子类);
    5. 子类可以直接拥有父类中所有允许子类继承的属性和方法;
    6. 继承关系是可以传递的)子类除了可以调用父类的方法,也可以调用父类的父类的方法,也就是说继承可以确保某个父类型之下的所有类都会有父类型所持有的全部方法;
    7. 子类可以有自己的成员变量、属性和方法;
    8. (单一继承性)Objective-C不支持多重继承。

    继承的使用
    继承的标识为英文的“:”冒号(),使用继承可以定义一个具有父类所有功能(成员和方法)的新类,它继承了父类的功能。
    方法的重写
    编写子类时,某些方法(从父类继承过来)需要自己的代码实现;
    子类允许重写父类的方法,在调用子类对象的重写方法时,就会调用重写后的方法;
    父类中被子类所重写的方法则在调用子类方法时被忽略;
    super的使用
    如果在子类中 需要调用父类的功能,可以借助super关键字;
    子类中使用super发送消息时,实际上是告诉子类调用父类的方法;
    如果父类没有定义该方法,则继续在继承链上查找,直到找到为止;
    如果查到NSobject为止仍然未找到,则报错;
    重写方法时经常会使用super关键字调用父类的方法。
    控件的继承关系:
    继承关系

    总结

    本次的内容较多,首先我们分析了UIView的作用与用法,接着我们分析了UIViewConreoller的用法。最后我们讲了控件间的继承关系及继承的作用与特点。

    下节预告

    UIImage与UIImageView的使用

    展开全文
  • UIView的理解

    千次阅读 2013-05-28 15:37:08
    UIView是开发中使用得最多的控件了,深入的理解很有必要。 UIView是组成画面的基本元素,UIView是拥有位置属性以及一定尺寸的四边形,一般有背景色。 UIView也可以包含字符串或者图片等内容。例如UILabel就是包含...

    UIView是开发中使用得最多的控件了,深入的理解很有必要。

    UIView是组成画面的基本元素,UIView是拥有位置属性以及一定尺寸的四边形,一般有背景色。

    UIView也可以包含字符串或者图片等内容。例如UILabel就是包含字符串的UIView,而UIImageView是包含图片的UIView。

    最重要的一点就是UIView可以拥有UIView类型的子元素,这样就可以轻易地在UIView上追加UIView,创建各样的画面。

    在iphone应用程序中,应用程序的UIWindow也是UIView的子类,也就是说,所有的画面都是在UIView中追加各种UIView而组成的。


    先来看看UIView的定义:

    NS_CLASS_AVAILABLE_IOS(2_0)@interface UIView :UIResponder<NSCoding,UIAppearance, UIAppearanceContainer> {

      @package

        CALayer        *_layer;

        id              _tapInfo;

        id              _gestureInfo;

        NSMutableArray *_gestureRecognizers;

        NSArray        *_subviewCache;

        float           _charge;

        NSInteger       _tag;

        UIViewController *_viewDelegate;

        NSString         *_backgroundColorSystemColorName;

        struct {

            unsigned int userInteractionDisabled:1;

            unsigned int implementsDrawRect:1;

            unsigned int implementsDidScroll:1;

            unsigned int implementsMouseTracking:1;

            unsigned int hasBackgroundColor:1;

            unsigned int isOpaque:1;

            unsigned int becomeFirstResponderWhenCapable:1;

            unsigned int interceptMouseEvent:1;

            unsigned int deallocating:1;

            unsigned int debugFlash:1;

            unsigned int debugSkippedSetNeedsDisplay:1;

            unsigned int debugScheduledDisplayIsRequired:1;

            unsigned int isInAWindow:1;

            unsigned int isAncestorOfFirstResponder:1;

            unsigned int dontAutoresizeSubviews:1;

            unsigned int autoresizeMask:6;

            unsigned int patternBackground:1;

            unsigned int fixedBackgroundPattern:1;

            unsigned int dontAnimate:1;

            unsigned int superLayerIsView:1;

            unsigned int layerKitPatternDrawing:1;

            unsigned int multipleTouchEnabled:1;

            unsigned int exclusiveTouch:1;

            unsigned int hasViewController:1;

            unsigned int needsDidAppearOrDisappear:1;

            unsigned int gesturesEnabled:1;

            unsigned int deliversTouchesForGesturesToSuperview:1;

            unsigned int chargeEnabled:1;

            unsigned int skipsSubviewEnumeration:1;

            unsigned int needsDisplayOnBoundsChange:1;

            unsigned int hasTiledLayer:1;

            unsigned int hasLargeContent:1;

            unsigned int unused:1;

            unsigned int traversalMark:1;

            unsigned int appearanceIsInvalid:1;

            unsigned int monitorsSubtree:1;

            unsigned int layoutEngineIsOverridden:1;

            unsigned int constraintsAreClean:1;

            unsigned int subviewLayoutConstraintsAreClean:1;

            unsigned int potentiallyHasDanglyConstraints:1;

            unsigned int doesNotTranslateAutoresizingMaskIntoConstraints:1;

            unsigned int autolayoutIsClean:1;

            unsigned int subviewsAutolayoutIsClean:1;

            unsigned int layoutFlushingDisabled:1;

            unsigned int layingOutFromConstraints:1;

            unsigned int wantsAutolayout:1;

            unsigned int subviewWantsAutolayout:1;

            unsigned int isApplyingValuesFromEngine:1;

            unsigned int isInAutolayout:1;

            unsigned int isUpdatingAutoresizingConstraints:1;

            unsigned int isUpdatingConstraints:1;

            unsigned int stayHiddenAwaitingReuse:1;

            unsigned int stayHiddenAfterReuse:1;

            unsigned int skippedLayoutWhileHiddenForReuse:1;

        } _viewFlags;

    }

    + (Class)layerClass;   // default is [CALayer class]. Used when creating the underlying layer for the view.

    - (id)initWithFrame:(CGRect)frame;   // default initializer


    @property(nonatomic,getter=isUserInteractionEnabled)BOOL userInteractionEnabled; // default is YES. if set to NO, user events (touch, keys) are ignored and removed from the event queue.

    @property(nonatomic)                                NSInteger tag;                // default is 0

    @property(nonatomic,readonly,retain)                 CALayer  *layer;             // returns view's layer. Will always return a non-nil value. view is layer's delegate

    @end


    1,父类是UIResponder,说明所有的UIView都具有响应器的特性。

    2,有一个对象    CALayer        *_layer;

    先看看定义:

    @interface CALayer : NSObject <NSCoding, CAMediaTiming>

    {

    @private

      struct _CALayerIvars {

        int32_t refcount;

        uint32_t magic;

        void *layer;

    #if TARGET_OS_MAC && !TARGET_RT_64_BIT

        void *unused1[8];

    #endif

      } _attr;

    }

    UIView之所以能够显示出来,其实全部是靠CALayer的显示。

    当UIView需要显示的时候,会调用drawRect:方法进行绘图,并且会将所有内容绘制在自己的层上(CALayer上),系统将层拷贝到屏幕上,完成UIView的显示。

    通过操作这个CALayer对象,可以很方便的调整UIView的一些界面属性,比如:阴影,圆角大小,旋转等等。

    viewT.layer.cornerRadius = 10;//设置半径
    viewT.layer.borderWidth = 10;//设置边框的宽度,当然可以不要
    viewT.layer.borderColor = [[UIColor redColor] CGColor];//设置边框的颜色
    viewT.layer.masksToBounds = YES;//设为NO去试试

    maskToBounds属性决定子图层是否相对于父图层裁剪

    CALayer可以添加层,跟UIView一样,UIView可以添加子视图,那么怎么选择是食用UIView还是UILayer来实现呢?

    对比CALayer,UIView多了一个事件的处理功能,因为UIView是UIResponder的子类,如果有交互必须使用UIView,CALayer效率上很高。


    3,UIView的setNeedsDisplay和setNeedsLayout方法

      1、在Mac OS中NSWindow的父类是NSResponder,而在i OS 中UIWindow 的父类是UIVIew。程序一般只有一个窗口但是会又很多视图。

      2、UIView的作用:描画和动画,视图负责对其所属的矩形区域描画、布局和子视图管理、事件处理、可以接收触摸事件、事件信息的载体、等等。

      3、UIViewController 负责创建其管理的视图及在低内存的时候将他们从内存中移除。还为标准的系统行为进行响应。

      4、layOutSubViews 可以在自己定制的视图中重载这个方法,用来调整子视图的尺寸和位置。

      5、UIView的setNeedsDisplay和setNeedsLayout方法。首先两个方法都是异步执行的。setNeedsDisplay会调用自动调用drawRect方法,这样可以拿到UIGraphicsGetCurrentContext,就可以画画了。而setNeedsLayout会默认调用layoutSubViews,就可以处理子视图中的一些数据。

    综上所述:setNeedsDisplay方便绘图,而layoutSubViews方便出来数据

    setNeedDisplay告知视图它发生了改变,需要重新绘制自身,就相当于刷新界面.


    4,initWithFram:(CGRect)frame方法用来初始化一个UIView,传入CGRect当参数


    5,可以看出UIView经常使用的属性没有定义在类里面,那肯定是定义在类别里面了:

    @interface UIView(UIViewGeometry)

    @property(nonatomic)CGRect            frame;

    @property(nonatomic)CGRect            bounds;     // default bounds is zero origin, frame size. animatable

    @property(nonatomic)CGPoint           center;   

    。。。

    @end

    可以看到UIView常用的属性在这个类别里面。

    注意:虽然ios6.0的时候增加了一个新功能,如果在类定义的时候声明属性之后,会自动生成一个以下划线开头的成员变量,但是对于类别是无效的。

    类别只能添加方法,不能添加成员变量的。所以这里添加的属性只不过是UIView的getter/setter方法而已,并没有_frame或者_bounds这种成员变量。

    只有view.frame 类似的点方法。返回的是一个CGRect的结构体

    struct CGRect {

      CGPoint origin;

      CGSize size;

    };

    typedef struct CGRect CGRect;

    这个结构体的值可能是存放在CALayer对象的void *unused1[8];指针数组中的某个指针指向的数据里。(仅猜测)


    6,UIView一些常用方法:

    @interface UIView(UIViewHierarchy)

    @property(nonatomic,readonly)UIView       *superview;

    @property(nonatomic,readonly,copy)NSArray *subviews;

    @property(nonatomic,readonly)UIWindow     *window;

    - (void)addSubview:(UIView *)view;

    - (void)removeFromSuperview;

    - (void)insertSubview:(UIView *)view atIndex:(NSInteger)index;

    - (void)exchangeSubviewAtIndex:(NSInteger)index1 withSubviewAtIndex:(NSInteger)index2;

    - (void)bringSubviewToFront:(UIView *)view;

    - (void)sendSubviewToBack:(UIView *)view;

    - (void)didAddSubview:(UIView *)subview;

    - (void)willRemoveSubview:(UIView *)subview;

    - (BOOL)isDescendantOfView:(UIView *)view; // returns YES for self.

    - (UIView *)viewWithTag:(NSInteger)tag;    // recursive search. includes self

    // Allows you to perform layout before the drawing cycle happens. -layoutIfNeeded forces layout early

    - (void)setNeedsLayout;

    - (void)layoutIfNeeded;

    - (void)layoutSubviews; 

    @end


    @interface UIView(UIViewRendering)

    - (void)drawRect:(CGRect)rect;

    - (void)setNeedsDisplay;

    - (void)setNeedsDisplayInRect:(CGRect)rect;

    @property(nonatomic,getter=isHidden)BOOL              hidden;        

    @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;            // default is nil

    @property(nonatomic)                CGFloat           alpha;   

    @property(nonatomic)                 CGRect            contentStretch 

    @end


    @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;  

    + (void)setAnimationDuration:(NSTimeInterval)duration;             // default = 0.2

    + (void)setAnimationDelay:(NSTimeInterval)delay;     

    @end


    @interface UIView(UIViewAnimationWithBlocks)

    + (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completionNS_AVAILABLE_IOS(4_0);

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

    @end


    @interface UIView (UIViewGestureRecognizers)//为UIView添加手势

    @property(nonatomic,copy) NSArray *gestureRecognizersNS_AVAILABLE_IOS(3_2);

    - (void)addGestureRecognizer:(UIGestureRecognizer*)gestureRecognizerNS_AVAILABLE_IOS(3_2);

    - (void)removeGestureRecognizer:(UIGestureRecognizer*)gestureRecognizerNS_AVAILABLE_IOS(3_2);

    @end

    只是摘录了一部分常用的。




    以下内容 为官方文档翻译(来源于网络),如果你英文还可以,请看英文地址:英文地址

         曾经有人这么说过,在iphone里你看到的,摸到的,都是UIView,所以UIView在iphone开发里具有非常重要的作用。那么UIView我们到底知道多少呢。请看看下面的问题,
    如果这些你都知道,那么本文章的内容就请绕道,如果你还不太清楚,我想看了下面的内容,你就明白了。
    1。bounds和frame分别表示什么?
    2。ContentMode里UIViewContentModeScaleToFill代表什么?
    3。contentStretch 里的指定UIView里缩放区域是如何计算的?
    4。UIVIew里的哪些属性变化可以用动画来呈现?
    5。UIKit的坐标系和Core Graphics的坐标系的差别是什么?

     

         视图和窗口展示了应用的用户界面,同时负责界面的交互。UIKit和其他系统框架提供了很多视图,你可以就地使用而几乎不需要修改。当你需要展示的内容与标准视图允许的有很大的差别时,你也可以定义自己的视图。

    不管你是使用系统的视图还是创建自己的视图,你需要理解UIView和UIWindow类所提供的基本结构。这些类提供了复杂的方法来管理视图的布局和展示。理解这些方法的工作非常重要,使你在应用发生改变时可以确认视图有合适的行为。

     视图架构 fundamentals 

    大部分你想要可视化操作都是由视图对象-即UIView类的实例-来进行的。一个视图对象定义了一个屏幕上的一个矩形区域,同时处理该区域的绘制和触屏事件。一个视图也可以作为其他视图的父视图,同时决定着这些子视图的位置和大小。UIView类做了大量的工作去管理这些内部视图的关系,但是需要的时候你也可以定制默认的行为。

    视图与Core Animation层联合起来处理着视图内容的解释和动画过渡。每个UIKit框架里的视图都被一个层对象支持(通常是一个CALayer类的实例),它管理管理着后台的视图存储和处理视图相关的动画。然而,当你需要对视图的解释和动画行为有更多的控制权时,你可以使用层。

    为了理解视图和层之间的关系,我们可以借助于一些例子。图1-1显示了ViewTransitions样例程序的视图层次及其对底层Core Animation层的关系。应用中的视图包括了一个window(同时也是一个视图),一个通用的表现得像一个容器视图的UIView对象,一个图像视图,一个控制显示用的工具条,和一个工具条按钮(它本身不是一个视图但是在内部管理着一个视图)。(注意这个应用包含了一个额外的图像视图,它是用来实现动画的)。为了简化,同时因为这个视图通常是被隐藏的,所以没把它包含在下面的图中。每个视图都有一个相应的层对象,它可以通过视图礶r属性被访问。(因为工具条按钮不是一个视图,你不能直接访问它的层对象。)在它们的层对象之后是Core Animation的解释对象,最后是用来管理屏幕上的位的硬件缓存。 

    Figure 1-1 View architecture

     

     

    使用Core Animation的层对象有很重要的性能意义。一个视图对象的绘制代码需要尽量的少被调用,当它被调用时,其绘制结果会被Core Animation缓存起来并在往后可以被尽可能的重用。重用已经解释过的内容消除了通常需要更新视图的开销昂贵的绘制周期。内容的重用在动画中特别重要,我们可以使用已有的内容,这样比创建新的内容开销更小。

     

    视图层次和子视图管理

     

    除了提供自己的内容之外,一个视图也可以表现得像一个容器。当一个视图包含其他视图时,就在两个视图之间创建了一个父子关系。在这个关系中孩子视图被当作子视图,父视图被当作超视图。创建这样一个关系对应用的可视化和行为都有重要的意义。

    在视觉上,子视图隐藏了父视图的内容。如果子视图是完全不透明的,那么子视图所占据的区域就完全的隐藏了父视图的相应区域。如果子视图是部分透明的,那么两个视图在显示在屏幕上之前就混合在一起了。每个父视图都用一个有序的数组存储着它的子视图,存储的顺序会影响到每个子视图的显示效果。如果两个兄弟子视图重叠在一起,后来被加入的那个(或者说是排在子视图数组后面的那个)出现在另一个上面。

    父子视图关系也影响着一些视图行为。改变父视图的尺寸会连带着改变子视图的尺寸和位置。在这种情况下,你可以通过合适的配置视图来重定义子视图的尺寸。其他会影响到子视图的改变包括隐藏父视图,改变父视图的alpha值,或者转换父视图。

    视图层次的安排也会决定着应用如何去响应事件。在一个具体的视图内部发生的触摸事件通常会被直接发送到该视图去处理。然而,如果该视图没有处理,它会将该事件传递给它的父视图,在响应者链中以此类推。具体视图可能也会传递事件给一个干预响应者对象,像视图控制器。如果没有对象处理这个事件,它最终会到达应用对象,此时通常就被丢弃了。

    获取更多关于如何创建视图层次,查看 creating and managing a view hierarchy

     

    视图绘制周期

     

    UIView类使用一个点播绘制模型来展示内容。当一个视图第一次出现在屏幕前,系统会要求它绘制自己的内容。在该流程中,系统会创建一个快照,这个快照是出现在屏幕中的视图内容的可见部分。如果你从来没有改变视图的内容,这个视图的绘制代码可能永远不会再被调用。这个快照图像在大部分涉及到视图的操作中被重用。

    如果你确实改变了视图内容,也不会直接的重新绘制视图内容。相反,使用setNeedsDisplay或者setNeedsDisplayInRect:方法废止该视图,同时让系统在稍候重画内容。系统等待当前运行循环结束,然后开始绘制操作。这个延迟给了你一个机会来废止多个视图,从你的层次中增加或者删除视图,隐藏,重设大小和重定位视图。所有你做的改变会稍候在同一时间反应。

    注意:改变一个视图的几何结构不会自动引起系统重画内容。视图的contentMode属性决定了改变几何结构应该如果解释。大部分内容模式在视图的边界内拉伸或者重定位了已有快照,它不会重新创建一个新的快照。获取更多关于内容模式如果影响视图的绘制周期,查看 content modes 

     

    当绘制视图内容的时候到了时,真正的绘制流程会根据视图及其配置改变。系统视图通常会实现私有的绘制方法来解释它们的视图,(那些相同的系统视图经常开发接口,好让你可以用来配置视图的真正表现。)对于定制的UIView子类,你通常可以覆盖drawRect:方法并使用该方法来绘制你的视图内容。也有其他方法来提供视图内容,像直接在底部的层设置内容,但是覆盖drawRect:时最通用的技术

     

    内容模式

     

    视图的内容模式控制着视图如何回收内容来响应视图几何结构的变化,也控制着是否需要回收内容。当一个视图第一次显示时,它通常会解释内容,其结果会被底层的层级树捕获为一张位图。在那之后,改变视图的几何结构不会导致重新创建位图。相反,视图中contentMode属性的值决定着这张位图是否该被拉伸,以适应新的边界或者只是简单的被放到角落或者视图的边界。

     

    视图的内容模式在你进行如下操作时被应用:

     

    改变视图frame或者bounds矩形的宽度或者高度时。

     

    赋值给视图的transform属性,新的转换包括一个放缩因子。

     

    大部分视图的contentMode值是UIViewContentModeScaleToFiill,它使视图的内容被放缩到适合新框架的值。Figure 1-2展示了使用其他可用的内容模式的结果。正如你在图中所看到的那样,不是所有的内容模式都可以填充视图的范围,可以的模式可能会扭曲内容。

     

    内容模式很好的支持了视图的内容回收,但是当你想视图在放缩和重设尺寸的操作中重绘你也可以用UIViewContentModeRedraw内容模式。设置这个值绘强制系统调用视图的drawRect:方法来响应几何结构的变化。通常来讲,你应该尽可能的避免使用这个模式,同时你不应该在标准的系统视图中使用这个模式。

     

    获取更多骨干与可用的内容模式,查看UIView Class Reference

     

    Figure 1-2

     

     

    拉伸视图

     

    你可以指定视图的某部分为可拉伸的,以便当视图的尺寸改变时只有可拉伸的部分被影响到。可拉伸的部分通常给按钮或者其他的部分为重复模式的视图。由你指定的可拉伸区域允许沿着两条或者其中一条轴拉伸。当然,当一个视图沿着两条轴拉伸的时候,视图的边界必须也定义了一个重复的模式来避免任何的扭曲。Figure1-3展示了这种扭曲在视图里是怎么表现自己的。每个视图里的原始像素的颜色都自我复制,以便可以填充更大视图的相应区域。

     

    Figure 1-3 拉伸一个按钮的背景

     

     

    你可以用contentStretch属性来定义一个视图的可拉伸区域。这个属性的值一个边的值被标准化为0.0到1.0之间的矩形。当拉伸这个视图时,系统将视图的当前边界值和放缩因子乘以标准值,以便决定哪些像素需要被拉伸。使用标准值可以减轻每次改变视图的边界值都更新contentStretch属性的需要。

     

    视图的内容模式也在决定如何视图的可拉伸区域的使用中扮演着重要的角色。只有当内容模式可能绘引起视图内容放缩的时候可拉伸区域才会被使用。这意味这你的可拉伸视图只被UIViewContentModeScaleToFill, UIViewContentModeScaleAspectFit和UIViewContentModeScaleAspectFill内容模式。如果你指定了一个将内容弹到边界或者角落的内容模式(这样就没有真正的放缩内容),这个视图会忽视可拉伸区域。

     

    注意:当需要创建一个可拉伸UIImage对象作为视图的背景时,使用contentStretch属性是推荐的。可拉伸视图完全被Core Animation层处理,这样性能通常更好。

     

    嵌入式动画支持

     

    使用层对象来支持视图的其中一个利益是你可以轻松的用动画处理视图相关的改变。动画是与用户进行信息交流的一个有用的方法,而且应该总是在进行应用设计的过程中考虑使用动画。UIView类的很多属性是动画化的-也就是,可以半自动的从一个值动画的变化到另一个值。为了实现这样一个动画,你需要做的只是:

    1 告诉UIKit你想要实现一个动画

    2 改变这个属性的值

    在一个UIView对象中有以下的动画化属性:

    frame - 你可以使用这个来动画的改变视图的尺寸和位置

    bounds - 使用这个可以动画的改变视图的尺寸

    center - 使用这个可以动画的改变视图的位置

    transform - 使用这个可以翻转或者放缩视图

    alpha - 使用这个可以改变视图的透明度

    backgroundColor - 使用这个可以改变视图的背景颜色

    contentStretch - 使用这个可以改变视图内容如何拉伸

     

    动画的一个很重要的地方是用于从一组视图到另一组视图的过渡。通常来说,会用一个视图控制器来管理关系到用户界面的主要变更的动画。例如,涉及到从高层到底层信息的导航的界面,通常会使用一个导航控制器来管理视图的过渡,这些视图显示了数据的每一个连续层面。然而,你也可以使用动画来创建两组视图的过渡,而不是视图控制器。当你想用一个系统提供的视图控制器无法支持的导航方案时你可能会这样做。

     

    除了用UIKit类可以创建动画外,你也可以用Core Animation层来创建动画。在更低层你有更多的在时间或者动画属性上的控制权。

     

    获取更多关于如何创建一个基于视图的动画,查看 Animations

    获取更多关于使用Core Animation创建动画的信息,查看Core Animation Programming Guide和Core Animation Cookbook.

     

    视图几何结构和坐标系统

     

     

    UIKit的默认坐标系统把原点设置在左上角,两条轴往下和右扩展。做标志被表示为浮点数,这样允许内容的精确布局和定位而不管底层的屏幕。Figure1-4展示了相对于屏幕的坐标系统。除了屏幕坐标系统窗口和视图也定义了它们自己的本地坐标系统,这样允许你指定相对于视图或者窗口原点的坐标而不是屏幕。

    Figure 1-4 UIKit中的坐标系统 

    因为每个视图和窗口都定义了它自己的本地坐标系统,你需要留意在任何时间内是哪个坐标系统在起作用。每次绘制或者改变一个视图都是基于一个坐标系统的。在某些绘制中会基于视图本身的坐标系统。在某些几何结构变更中是基于父视图的坐标系统的。UIWindow和UIView类都包含了帮助你从一个坐标系统转换到另一个的方法。

    重要:一些iOS技术定义了默认的坐标系统,它们的原点和方向与UIKit的不同。;例如,Core Graphics和OpenGL ES的坐标系统是原点在可视区域的左下角,而y轴往上递增。当绘制或者创建内容时,你的代码应该考虑到一些不同并且适应坐标值。

      frame, bounds和center属性之间的关系

    视图对象使用frame, bounds和center属性来跟踪它的尺寸和位置:

    frame属性包含了frame矩形,指定了在父视图坐标系统中该视图的尺寸和位置。

    center属性包含了在父视图坐标系统中的已知中心点。

    bounds属性包含了边界矩形,指定了在视图本地坐标系统中视图的尺寸。

    主要使用center和frame属性来控制当前视图的几何结构。例如,当在运行时构建你的视图层次或者改变视图的尺寸或者位置时你可以使用这些属性。如果你只是要改变视图的位置,那么推荐使用center属性。center属性的值永远是可用的,即使添加了放缩或者转换因子到视图的转换矩阵当中。但是对于frame属性却不是,当视图的转换矩形不等于原始矩阵时它被当作时无效的。

     

    在绘制的过程中主要使用bounds属性。这个边界矩阵在视图的本地坐标系统被解释。这个矩形的默认原点是(0, 0),它的尺寸也适应frame矩形的尺寸。任何绘制在这个矩形当中的东西都是该视图的可视内容的一部分。如果你改变了bounds矩形的原点,任何你绘制在新矩形的东西都会变成该视图可视内容的一部分。

    Figure1-5展示了一个图像视图的frame和bounds矩形之间的关系。图中,图像视图的右上角被定位在父视图坐标系统的(40, 40),它的矩形尺寸为240x380。对于bounds矩形,原点是(0, 0),矩形尺寸也是240x380。

    Figure 1-5 视图frame和bounds之间的关系

     

     

    即使你可以独立的改变frame,bounds和center属性,其中一个改变还是会影响到另外两个属性:

    当你设置了frame属性,bounds属性的尺寸值也改变来适应frame矩形的新尺寸。center属性也会改变为新frame矩形的中心值。

    当你设置了center属性,frame的原点也会相应的改变。

    当你设置了bounds属性,frame属性会改变以适应bounds矩形的新尺寸。

    视图的框架默认不会被它的父视图框架裁剪。这样的化,任何放置在父视图外的子视图都会被完整的解释。你可以改变这种行为,改变父视图的clipsToBounds属性就可以。不管子视图是否在视觉上被裁剪,触屏事件总是发生在目标视图父视图的bounds矩形。换句话说,如果触摸位于父视图外的那部分视图,那么该事件不会被发送到该视图。

    坐标系统转换矩阵

    坐标系统转换矩阵给改变视图(或者是它的视图)提供了一个轻松和简易的方法。一个仿射转换是一个数学矩阵,它指定了在坐标系统中的点是怎么被映射到另一个坐标系统中的点。你可以对整个视图应用仿射转换,以基于其父视图来改变视图的尺寸,位置或者朝向。你也可以在你的绘制代码中应用仿射转换,以对已解释内容的独立部分实现相同的操控。如何应用仿射转换是基于这样的上下文的:

    为了修改整个视图,可以修改视图transform属性的仿射转换值。

    为了在视图中的drawRect:方法中修改内容的指定部分,可以修改与当前图形上下文相关的仿射转换。

    当你想实现动画时,通常可以修改视图的transform属性值。例如,你可以使用这个属性来制作一个视图围绕中心点翻转的动画。你不应该在其父视图的坐标空间中用这个属性来永久的改变你的视图,像修改它的位置和尺寸。对于这种类型的改变,你可以修改视图的frame矩形。

    注意:当修改视图的transform属性值时,所有的转换都是基于视图的中心点来实现的。

    在视图的drawRect:方法中,你可以使用仿射转换来定位或者翻转你想要绘制的项目。相对于在视图某些部位中修正对象的位置,我们更倾向于相对于一个固定点去创建对象,通常是(0, 0),同时在绘制之前使用转换来定位对象。这样的话,如果在视图中对象的位置改变了,你要做的只是修改转换矩阵,这样比为对象重新创建新的位置性能更好开销更低。你可以通过使用CGContextGetCTM方法来获取关于图形上下文的仿射转换,同时可以用Core Graphics的相关方法在绘制中来设置或者修改这个转换矩阵。

    当前转换矩阵(CTM)是一个在任何时候都被使用的仿射矩阵。当操控整个视图的几何结构时,CTM就是视图transform属性的值。在drawRect:方法中,CTM是关于图形上下文的仿射矩阵。

    每个子视图的坐标系统都是构建在其祖先的坐标系统之上的。所以当你修改一个视图的transform属性,这个改变会影响到视图及其所有的子视图。然而,这些改变只会影响到屏幕上视图的最终解释。因为每个视图都负责绘制自己的内容和对自己的子视图进行布局,所以在绘制和布局的过程中它可以忽略父视图的转换。

    Figure1- 6描述了在解释的时候,两个不同的转换因子是如何在视觉上组合起来的。在视图的drawRect:方法中,对一个形状应用一个45度的转换因子会使该形状翻转指定的角度。另外加上一个45度的转换因子会导致整个形状翻转90度。这个形状对于绘制它的视图来讲仍然只是翻转了45度,但是视图自己的转换让它看起来像使翻转了90度。

    Figure 1-6 翻转一个视图和它的内容

     

     

    重要:如果一个视图的transform属性不是其定义时转换矩阵,那么视图的frame属性是未定义的而且必须被忽略。当对视图应用转换时,你必须使用视图的bounds和center属性来获取视图的位置和尺寸。子视图的frame矩形仍然是有效的,因为它们与视图的bounds相关。

     

    获取更多关于在运行时修改视图的transform属性,查看 “Translating, Scaling, and Rotating Views.”获取更多如何在绘制过程中使用转换来定位内容,查看 Drawing and Printing Guide for iOS.

     

    点与像素

    在iOS中,所有的坐标值和距离都被指定为使用浮点数,其单元值称为点。点的数量随着设备的不同而不同,而且彼此不相关。要明白关于点的最主要一点是它们提供了一个绘制用的固定框架。

    Table 1-1 列出了不同iOS设备的分辨率(点度量)。前为宽后为长。只要你依照这些屏幕的尺寸来设计用户界面,你的视图就回被相应的设备正确显示。

     

    Table 1-1 

     

     

    Device                                            Screen dimensions (in points)

    iPhone and iPod touch                      320 x 480

    iPad                                               768 x 1024

     

     

    每一种使用基于点度量系统的设备都定义了一个用户坐标空间。这是几乎在你所有的代码都会用到的标准坐标空间。例如,当你要操控视图的几何结构或者调用Core Graphics方法来绘制内容时会用到点和用户坐标空间。即使有时用户坐标空间里的坐标时直接映射到设备屏幕的像素,你还是永远不应该假设这是永远不变的。相反,你应该记住:一个点并不一定对应着屏幕上的一个像素

    在设备层面,所有由你指定的视图上的坐标在某些点上必须被转化成像素。然而,从用户坐标空间上的点到设备坐标空间上的像素通常由系统来处理。UIKit和Core Graphics都主要使用基于向量的绘制模型,所有的坐标值都被指定为使用点。这样,如果你用Core Graphics画了一条曲线,你会用一些值来指定这条曲线,而不管底层屏幕使用怎样的解决方法。

    当你需要处理图像或者其他基于像素的技术,像OpenGL ES时,iOS会帮你管理这些像素。对于存储为应用程序的束中的资源的静态图像文件,iOS定义了一些约定,可以指定不同像素密度的图像,也可以在加载图像时最大限度的适应当前屏幕的解决方案。视图也提供了关于当前放缩因子的信息,以便你可以适当的调整任何基于像素的绘制代码来适应有更高级解决方案的屏幕。在不同屏幕的解决方案中处理基于像素内容的技术可以在"Supporting High-Resolution Screens"和"Drawing and Printing Guide for iOS"找到描述。 

     

    视图的运行时交互模型 

     

    当用户和界面进行交互时,或者由代码程序性的改变一些东西时,一系列复杂的事件就会发生在UIKit的内部来处理这些交互。在这个系列中的某些点,UIKit唤出你的视图类,同时给它们一个机会去响应程序的行为。理解这些唤出点对于理解视图在哪里融入系统很重要。Figure 1-7 展示了这些事件的基本序列,从用户触屏开始到图形系统更新屏幕内容来响应结束。同样的事件序列也会发生在任何程序性启动的动作。

    Figure 1-7 UIKit 与视图对象进行交互

     

     

    以下的步骤分解了图1-7中的事件序列,既解释了在每一步发生了什么,也解释了应用如何响应

    1 用户触屏

    2 硬件报告触摸事件给UIKit框架

    3 UIKit框架将触摸事件打包成UIEvent对象,同时分发给适合的视图。(对于UIKit框架如何提交事件给视图的详细解释,查看 Event Handing Guide for iOS)

    4 视图中的事件处理代码可能进行以下的动作来响应:

    改变视图或者其子视图的属性(frame, bounds, alpha, 等等)

    调用setNeedsLayout方法以标记该视图(或者它的子视图)为需要进行布局更新

    调用setNeedsDisplay或者setNeedsDisplayInRect:方法以标记该视图(或者它的子视图)需要进行重画

    通知一个控制器关于一些数据的更新

    当然,哪些事情要做,哪些方法要被调用是由视图来决定的。

    5 如果一个视图的几何结构改变了,UIKit会根据以下几条规则来更新它的子视图:

    a 如果自动重设尺寸的规则在发生作用,UIKit会根据这些规则来调整视图。获取更多关于自动重设尺寸规则如何工作,查看"Handling Layout Changes Automatically Using Autoresizing Rules."

    b 如果视图实现了layoutSubviews方法,UIKit会调用它。你可以在你的定制视图中覆盖这个方法同时用它来调整任何子视图的位置和大小。例如,一个提供了巨大滚动区域的视图会需要使用几个子视图作为“瓦块”而不是创建一个不太可能放进内存的巨大视图。在这个方法的实现中,视图会隐藏任何屏幕外的子视图,或者重定位它们然后用来绘制新的可视内容。作为这个流程的一部分,视图的布局代码也可以废止任何需要被重画的视图。

    6 如果任何视图的任何部分被标记为需要重画,UIKit会要求视图重画自身。

    对于显式的定义了drawRect:方法的定制视图,UIKit会调用这个方法。这方法的实现应该尽快重画视图的指定区域,并且不应该再做其他事。不要在这个点上做额外的布局,也不要改变应用的数据模型。提供这个方法仅仅是为了更新视图的可视内容。

    标准的系统视图通常不会实现drawRect:方法,但是也会在这个时候管理它们的绘制。

     

    7 任何已经更新的视图会与应用余下的可视内容组合在一起,同时被发送到图形硬件去显示。

    8 图形硬件将已解释内容转化到屏幕上。

     

    注意:上面的更新模型主要应用于使用标准系统视图和绘制技术的应用。使用OpenGL ES来绘制的应用通常会配置一个单一的全屏视图和直接绘制相关的OpenGL图像上下文。你的视图还是应该处理触屏事件,但是它是全屏的,毋需给子视图布局或者实现drawRect:方法。获取更多关于使用OpenGL ES的信息,查看 OpenGL ES Programming Guide for iOS.

     

    给定之前的一系列步骤,将自己的定制视图整合进去的方法包括:

    事件处理方法:

    touchesBegan:withEvent:

    touchesMoved:withEvent:

    touchesEnded:withEvent:

    touchesCancelled:withEvent:

    layoutSubviews方法

    drawRect:方法

    这些是视图的最常用的覆盖方法,但是你可能不需要覆盖全部。如果你使用手势识别来处理事件,你不需要覆盖事件处理方法。相似的,如果你的视图没有包含子视图或者它的尺寸不会改变,那就没有理由去覆盖layoutSubviews方法。最后,只有当视图内容会在运行时改变,同时你要用UIKit或者Core Graphics等本地技术来绘制时才需要用到drawRect。

     

    要记住这些是主要的整合点,但是不仅仅只有这些。UIView类中有些方法是专门设计来给子类覆盖的。你应该到UIView Class Reference中查看这些方法的描述,以便在定制时清楚哪些方法适合给你覆盖。

     

    有效使用视图的提示

     

    当你需要绘制一些标准系统视图不能提供的内容时,定制视图是很有用的。但是你要负责保证视图的性能要足够的高。UIKit会尽可能的优化视图相关的行为,也会帮助你提高性能。然而,考虑一些提示可以帮助到UIKit。 

    重要:在调整绘制代码之前,你应该一直收集与你视图当前性能有关的数据。估量当前性能让你可以确定是否真的有问题,同时如果真的有问题,它也提供一个基线,让你在未来的优化中可以比较。

    视图不会总是有一个相应的视图控制器

    在应用中,视图和视图控制器之间的一对一关系是很少见的。视图控制器的工作是管理一个视图层次,而视图层次经常是包含了多个视图,它们都有自包含特性。对于iPhone应用,每个视图层次通常都填满了整个屏幕,尽管对于iPad应用来说不是。 

    当你设计用户界面的时候,考虑到视图控制器的所扮演的角色是很重要的。视图控制器提供了很多重要的行为,像协调视图的展示,协调视图的剔除,释放内存以响应低内存警告,还有翻转视图以响应界面的方向变更。逃避这些行为会导致应用发生错误。

    获取更多关于视图控制器的信息,查看 View Controller Programming Guide for iOS 

    最小化定制的绘画

    尽管定制的绘画有时是需要的,但是你也应该尽量避免它。真正需要定制绘画的时候是已有的视图类无法提供足够的表现和能力时。任何时候你的内容都应该可以被组装到其他视图,最好结果时组合那些视图对象到定制的视图层次 

    利用内容模式 

    内容模式可以最小化重画视图要花费的时间。默认的,视图使用UIViewContentModeScaleToFill 内容模式,这个模式会放缩视图的已有内容来填充视图的frame矩形。需要时你可以改变这个模式来调整你的内容,但是应该避免使用UIViewContentModeRedraw内容模式。不管哪个内容模式发生作用,你都可以调用setNeedsDisplay或者setNeedsDisplayInRect:方法来强制视图重画它的内容

    可能的话将视图声明为不透明

    UIKit使用opaque属性来决定它是否可以优化组合操作。将一个定制视图的这个属性设置为YES会告诉UIKit不需要解释任何在该视图后的内容。这样可以为你的绘制代码提高性能并且是推荐的。当然,如果你将这个属性设置为YES,你的视图一定要用不透明的内容完全填充它的bounds矩形。

    滚动时调整视图的绘制行为

    滚动会导致数个视图在短时间内更新。如果视图的绘制代码没有被适当的调整,滚动的性能会非常的缓慢。相对于总是保证视图内容的平庸,我们更倾向于考虑滚动操作开始时改变视图行为。例如,你可以暂时减少已解释的内容,或者在滚动的时候改变内容模式。当滚动停止时,你可以将视图返回到前一状态,同时需要时更新内容。 

    不要嵌入子视图来定制控制 

    尽管在技术上增加子视图到标准系统控制对象-继承自UIControl的类-是可行的,你还是永远不应该用这种方法来定制它们。控制对象支持定制,它们有显式并且良好归档的接口。例如,UIButton类包含了设置标题和背景图片的方法。使用已定义好的定制点意味着你的代码总是会正确的工作。不用这些方法,而嵌入一个定制的图像视图或者标签到按钮中去会导致应用出现未预期的结果。



    展开全文
  • UIView

    2019-11-07 15:20:09
    版权声明:本文为延成原创文章,转载请标明出处 ... UIView *cView=[[UIView alloc]init]; cView.frame=CGRectMake(100, 100, 100, 200); cView.backgroundColor=[UIColor magentaColor]; cV...
  • UIVIew是iOS中的视图对象,显示在屏幕上的所有对象的基础类,所有显示在屏幕上的对象都是一定都继承于UIView。 屏幕上能看到的对象都是UIView的子类,UIView是一个矩形对象,有背景颜色, 可以显示, 有层级关系...
  • UIView生命周期

    千次阅读 2018-04-28 17:07:30
    UIView和UIViewController一样,也有自己的生命周期。UIView生命周期包含的常见方法UIView包含的常见方法如下:- (void)didAddSubview:(UIView *)subview; - (void)willRemoveSubview:(UIView *)subview; - (void)...
  • UIView加边框及边框颜色

    万次阅读 2012-09-19 15:08:27
    引用库: #import 使用: //添加边框和提示  CGRect frameRect = CGRectMake(20, 90, self.window.frame.size.width-40, self.window.frame.size.height-180);... UIView *frameView = [[UIView all
  • UIView添加点击事件

    万次阅读 2016-08-24 18:24:26
    使用 UITapGestureRecognizer ,创建一个 UITapGestureRecognizer 将它添加到view上即可 ... UIView *tapView=[[UIView alloc]initWithFrame:SCREEN_FRAME];    UITapGestureRecognizer *tapGesturRecogn
  • UIView大小缩放的动画效果函数

    万次阅读 2014-03-27 14:08:57
    转自:http://blog.sina.com.cn/s/blog_9bf272cf01015i9b.html UIView *singleMapView = [[UIView alloc] initWithFrame:CGRectMake(10, 150, 300, 250)]; singleMapView.backgrou
  • iOS 完全复制UIView

    万次阅读 2014-03-03 15:05:25
    如果要完全复制一个UIView和对象的时候可以使用对象序列化方法 // Duplicate UIView - (UIView*)duplicate:(UIView*)view { NSData * tempArchive = [NSKeyedArchiver archivedDataWithRootObject:view]; return ...
  • iOS开发动画(Animation)总结

    万次阅读 2013-12-25 14:32:44
    UIView的,翻转、旋转,偏移,翻页,缩放,取反的动画效果 翻转的动画  //开始动画 [UIView beginAnimations:@"doflip" context:nil]; //设置时常 [UIView setAnimationDuration:1]; //设置动画...
  • 将一个UIView显示在最前面只需要调用其父视图的 bringSubviewToFront()方法。   将一个UIView层推送到背后只需要调用其父视图的 sendSubviewToBack()方法
  • 如何停止UIView的animation

    万次阅读 2015-03-09 23:36:31
    旋转通常有两种方法:CAAnimation 和 UIView的animation 两者的主要区别在于:当你想控制或停止某一动画的时候,那么只能用CAAnimation UIView的animation “` /成员变量/ UIImageView * _recordImageView; //...
  • IOS UIView的淡入淡出效果

    万次阅读 2012-09-26 10:40:14
    - (void)viewDidLoad {  [super viewDidLoad];  // Do any additional setup after loading the view from its nib.  timer=[NSTimer scheduledTimerWithTimeInterval:3
  • Swift UIView 常用添加方法

    万次阅读 2015-08-30 16:12:00
    Swift 添加UIView有几种常见方法 func insertSubview(view: UIView, atIndex index: Int) func addSubview(view: UIView) func insertSubview(view: UIView, belowSubview siblingSubview: UIView) func ins
  • UIView中添加点击事件oc及swift

    千次阅读 2017-06-02 13:56:40
    UIView继承于UIResponder是没有addTarget 方法的,所有只能在UIView上添加手势UITapGestureRecognizer来实现点击事件。 首先设定UIView(或其子类)为可交互的:iconView.userInteractionEnabled = YES;添加tap手势...
  • UIView设置背景图片的方法

    万次阅读 2012-07-23 22:52:44
    项目中,可能需要我们为某个视图设置背景图片,而API中UIView没有设置背景图片的方法,那么该如何实现呢? 第一种方法: 利用的UIView的设置背景颜色方法,用图片做图案颜色,然后传给背景颜色。 UIColor *...
  • (1)UIView-Extent.h #import @interface UIView (Extend) - (UIViewController *)viewController; @end (2) UIView-Extent.m #import "UIView+Extend.h" @implementation UIView (Extend) - ...
  • iOS|开发小技巧之UIView创建xib

    千次阅读 2017-07-31 15:05:04
    我们有的时候在创建UIView的时候,想要使用xib进行创建视图发现,xib文件不能和UIView文件一起创建。所以,我们要单独创建xib文件。 我们选择Empty文件,而不要选择View文件。记得文件名和你之前创建的UIView文件名...
1 2 3 4 5 ... 20
收藏数 98,202
精华内容 39,280
关键字:

uiview