zoukankan      html  css  js  c++  java
  • IOS开发之自动布局框架设计(一)

      UI布局是app开发的很重要的一个环节,经历了从坐标布局到相对布局的过程,苹果推出的NSLayoutConstraint布局的方式可以通过指定view之间的相对位置来实现布局,我们先来看看使用NSLayoutConstraint布局的方式的实现,然后深度剖析下如何设计一款自动布局的框架。

    NSLayoutConstraint

    好吧 咱们一言不合就开始上代码吧,哈哈!!!

    1 NSLayoutConstraint *constaintTop = [NSLayoutConstraint
    2                                         constraintWithItem:self.tableView
    3                                         attribute:NSLayoutAttributeTop
    4                                         relatedBy:NSLayoutRelationEqual
    5                                         toItem:self.view 
    attribute:NSLayoutAttributeTop
    6 multiplier:1.0 7 constant:20]; 8 9 [_tableView addConstraint:constaintTop];

    首先我们来看NSLayoutConstraint,顾名思义,是布局约束的意思,我们进入看看它的类结构:

    1.这一段主要定义了它的一些属性的枚举,分别对应了Layout的一些属性,Left,Right,Top,Bottom,Center等等,我们仔细看看上面代码的参数:

    constraintWithItem:id类型的,也就是说不限于UIView,如果是其它类型的会出现神马情况呢....
    attribute:NSLayoutAttribute枚举类型的,也就是数字了。

    relatedBy:NSLayoutRelation枚举类型的,也就是数字了。

    toItem:id类型的,也就是说不限于UIView,如果是其它类型的会出现神马情况呢....
     1 typedef NS_ENUM(NSInteger, NSLayoutRelation) {
     2     NSLayoutRelationLessThanOrEqual = -1,
     3     NSLayoutRelationEqual = 0,
     4     NSLayoutRelationGreaterThanOrEqual = 1,
     5 };
     6 
     7 typedef NS_ENUM(NSInteger, NSLayoutAttribute) {
     8     NSLayoutAttributeLeft = 1,
     9     NSLayoutAttributeRight,
    10     NSLayoutAttributeTop,
    11     NSLayoutAttributeBottom,
    12     NSLayoutAttributeLeading,
    13     NSLayoutAttributeTrailing,
    14     NSLayoutAttributeWidth,
    15     NSLayoutAttributeHeight,
    16     NSLayoutAttributeCenterX,
    17     NSLayoutAttributeCenterY,
    18     NSLayoutAttributeBaseline,
    19     NSLayoutAttributeLastBaseline = NSLayoutAttributeBaseline,
    20     NSLayoutAttributeFirstBaseline NS_ENUM_AVAILABLE_IOS(8_0),
    21     
    22     
    23     NSLayoutAttributeLeftMargin NS_ENUM_AVAILABLE_IOS(8_0),
    24     NSLayoutAttributeRightMargin NS_ENUM_AVAILABLE_IOS(8_0),
    25     NSLayoutAttributeTopMargin NS_ENUM_AVAILABLE_IOS(8_0),
    26     NSLayoutAttributeBottomMargin NS_ENUM_AVAILABLE_IOS(8_0),
    27     NSLayoutAttributeLeadingMargin NS_ENUM_AVAILABLE_IOS(8_0),
    28     NSLayoutAttributeTrailingMargin NS_ENUM_AVAILABLE_IOS(8_0),
    29     NSLayoutAttributeCenterXWithinMargins NS_ENUM_AVAILABLE_IOS(8_0),
    30     NSLayoutAttributeCenterYWithinMargins NS_ENUM_AVAILABLE_IOS(8_0),
    31     
    32     NSLayoutAttributeNotAnAttribute = 0
    33 };
    34 
    35 typedef NS_OPTIONS(NSUInteger, NSLayoutFormatOptions) {
    36     NSLayoutFormatAlignAllLeft = (1 << NSLayoutAttributeLeft),
    37     NSLayoutFormatAlignAllRight = (1 << NSLayoutAttributeRight),
    38     NSLayoutFormatAlignAllTop = (1 << NSLayoutAttributeTop),
    39     NSLayoutFormatAlignAllBottom = (1 << NSLayoutAttributeBottom),
    40     NSLayoutFormatAlignAllLeading = (1 << NSLayoutAttributeLeading),
    41     NSLayoutFormatAlignAllTrailing = (1 << NSLayoutAttributeTrailing),
    42     NSLayoutFormatAlignAllCenterX = (1 << NSLayoutAttributeCenterX),
    43     NSLayoutFormatAlignAllCenterY = (1 << NSLayoutAttributeCenterY),
    44     NSLayoutFormatAlignAllBaseline = (1 << NSLayoutAttributeBaseline),
    45     NSLayoutFormatAlignAllLastBaseline = NSLayoutFormatAlignAllBaseline,
    46     NSLayoutFormatAlignAllFirstBaseline NS_ENUM_AVAILABLE_IOS(8_0) = (1 << NSLayoutAttributeFirstBaseline),
    47     
    48     NSLayoutFormatAlignmentMask = 0xFFFF,
    49     
    50     /* choose only one of these three
    51      */
    52     NSLayoutFormatDirectionLeadingToTrailing = 0 << 16, // default
    53     NSLayoutFormatDirectionLeftToRight = 1 << 16,
    54     NSLayoutFormatDirectionRightToLeft = 2 << 16,  
    55     
    56     NSLayoutFormatDirectionMask = 0x3 << 16,  
    57 };

    2.我们注意到里面有两个初始化的方法,用来初始化当前的constraint属性,对应的参数分别为 view1,attr1,relation,view2,attr2,multiplier,constant刚好是对应两个view的属性之间的关系,通过倍数以及修正值来准确描述相对的位置关系,view1.att1=view2.attr2*multiplier+constant;

    /* Create constraints explicitly.  Constraints are of the form "view1.attr1 = view2.attr2 * multiplier + constant" 
     If your equation does not have a second view and attribute, use nil and NSLayoutAttributeNotAnAttribute.
     */
    +(instancetype)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(nullable id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c;
    
    
    /* Create an array of constraints using an ASCII art-like visual format string.
     */
    + (NSArray<__kindof NSLayoutConstraint *> *)constraintsWithVisualFormat:(NSString *)format options:(NSLayoutFormatOptions)opts metrics:(nullable NSDictionary<NSString *,id> *)metrics views:(NSDictionary<NSString *, id> *)views;

    3.另外我们发现有相对应的一些属性,注意到它们都是只读属性

    1 @property (readonly, assign) id firstItem;
    2 @property (readonly) NSLayoutAttribute firstAttribute;
    3 @property (readonly) NSLayoutRelation relation;
    4 @property (nullable, readonly, assign) id secondItem;
    5 @property (readonly) NSLayoutAttribute secondAttribute;
    6 @property (readonly) CGFloat multiplier;

    从这个类的基本结构来看,橘子君对NSLayoutConstraint的理解就是:一个定义了两个view的相对关系以及能准确的描述出属性的相对数值的一个类。

    好吧,橘子君的理解是,上述的一串代码是可以准备的描述出一个约束的,感觉代码结构还是挺清晰的,但是貌似有那么一点点的冗长。

    我们再回过头来看看上面的一段代码吧

    1 NSLayoutConstraint *constaintTop = [NSLayoutConstraint
    2                                         constraintWithItem:self.tableView
    3                                         attribute:NSLayoutAttributeTop
    4                                         relatedBy:NSLayoutRelationEqual
    5                                         toItem:self.view attribute:NSLayoutAttributeTop
    6                                         multiplier:1.0
    7                                         constant:20];
    8     
    9  [_tableView addConstraint:constaintTop];

    上面的代码是通过constraintWithItem这个初始化方法来实现一个约束的,后面通过addConstraint方法添加到view上面去的,那么addConstraint方法里面主要做了哪些操作了,好吧,本着一探到低的精神,我们看看先

    // Installing Constraints
    
    /* A constraint is typically installed on the closest common ancestor of the views involved in the constraint. 
     It is required that a constraint be installed on _a_ common ancestor of every view involved.  The numbers in a constraint are interpreted in the coordinate system of the view it is installed on.  A view is considered to be an ancestor of itself.
     */
    @interface UIView (UIConstraintBasedLayoutInstallingConstraints)
    
    @property(nonatomic,readonly) NSArray<__kindof NSLayoutConstraint *> *constraints NS_AVAILABLE_IOS(6_0);
    
    - (void)addConstraint:(NSLayoutConstraint *)constraint NS_AVAILABLE_IOS(6_0); // This method will be deprecated in a future release and should be avoided.  Instead, set NSLayoutConstraint's active property to YES.
    - (void)addConstraints:(NSArray<__kindof NSLayoutConstraint *> *)constraints NS_AVAILABLE_IOS(6_0); // This method will be deprecated in a future release and should be avoided.  Instead use +[NSLayoutConstraint activateConstraints:].
    - (void)removeConstraint:(NSLayoutConstraint *)constraint NS_AVAILABLE_IOS(6_0); // This method will be deprecated in a future release and should be avoided.  Instead set NSLayoutConstraint's active property to NO.
    - (void)removeConstraints:(NSArray<__kindof NSLayoutConstraint *> *)constraints NS_AVAILABLE_IOS(6_0); // This method will be deprecated in a future release and should be avoided.  Instead use +[NSLayoutConstraint deactivateConstraints:].
    @end

    好吧,原来是写在了UIView的分类里面,UIConstraintBasedLayoutInstallingConstraints,按字面意思理解,基本布局初始化约束,它将这些约束添加到数组里面,然后计算出它们的位置。

    各位看官应该累了吧,上张美女图片大家养养眼,哈哈!!!

    至此,苹果原生的NSLayoutConstraint分析完毕,那么问题来了,很多吃瓜观众觉得太反锁了,如是乎,各位童鞋们进行了包装美化,市场上便出现了各式各样的开源框架,这就像当明星一样,只要那些运气好,颜值高的才能真正的站在无赖上上,像Masonry,SDAutoLayoutZXPAutoLayout,Keep Layout,Bee Framework。

    好吧,如果需要我们自己设计一套布局的接口,该有哪些思路呢???

    我们先上一些美女图片吧!!!

  • 相关阅读:
    day2 python基础
    day2 jmeter和charles
    nmon参数详解
    根据路径遍历该路径下的文件夹和文件并以列表形式显示出来、文件(夹)的复制
    GridView创建菜单栏
    GridView(网格视图)+MotionEvent(触控事件)实现可以拖动排序的网格图
    android 下拉刷新框架PullToRefreshScrollView(com.handmark.pulltorefresh)
    android轮播图的实现原理
    自定义进度条渐变色View
    android显示通知栏Notification以及自定义Notification的View
  • 原文地址:https://www.cnblogs.com/guchengfengyun/p/5851970.html
Copyright © 2011-2022 走看看