iOS SDAutoLayout(自动布局)~详解

//联系人:石虎  QQ: 1224614774昵称:嗡嘛呢叭咪哄

一、概念

    SDAutoLayout如果真的能够做到预计的方便使用,应该是很爽的,但是我个人觉得还是没有到那步。当然也可能是我的能力有限,很多东西都仅仅停留在表面,没办法,不太省心,又开源,又不想轻易放弃,只能啃源码了。

优点

1、语法简单(相比官方的语法,Masonry)

2、纯代码的方式,代码维护容易(相比使用xib,storyboard)

3、UIlabel的内容能够自动根据内容算出宽度

4、UITableviewCell能够自动算出height

5、UIView能够自动算出height

6、创建的时候,只需要alloc->init,不需要关心对应的frame

缺点

1、 leftspacetoview等方式,经常出现UIView布局完以后,不可见,有时候不太准,有时候是self的左边基准,有时候是self的右边为基准,一般来说,self的width都是屏幕宽度,所以子控件的x经常飞出屏幕

2、 花费比预料多很多的时候去调试

二、源码分析

1、项目地址

2、文件总数

说真的,文件也不太多,就4个。这也是我愿意啃源码的一个强有力的原因。

3、代码总数

     146 ./UITableView+SDAutoTableViewCellHeight.h
     374 ./UITableView+SDAutoTableViewCellHeight.m
     457 ./UIView+SDAutoLayout.h
    1712 ./UIView+SDAutoLayout.m
    2689 total

4、源码总结

1)利用关键字sd_layout,生成SDAutoLayoutModel并添加到父类的autoLayoutModelsArray数组里去。

2、在sd_layoutSubviews根据上面生成的SDAutoLayoutModel计算frame

3)流程分析

一)先使用sd_layout为父类添加一系列的SDAutoLayoutModel类型的数组autoLayoutModelsArray

二) 在sd_layoutSubviewsHandle根据autoLayoutModelsArray,遍历每个子view,计算每个子view的frame

三) 在sd_resizeWithModel函数里面,生成子view的frame,如果子frame存在sd_bottomViewsArray和sd_rightViewsArray数组,就递归执行上面的步骤。

5、类构成

  • @interface SDAutoLayoutModel : NSObject
    • 包含一系列的关于frame处理的block
    • 还包含一个指向自身的needsAutoResizeView的指针
  • @interface UIView (SDAutoHeightWidth)
    • 包含主要的面向用户的API调用之一,高度、宽度自适应相关方法,button(高),right(宽),强制更新UI的约束函数
  • @interface UIView (SDLayoutExtention)
    • 设置圆角半径、九宫格浮动效果、自动布局回调block等相关方法
  • @interface UIView (SDAutoLayout)
    • 设置约束、更新约束、清空约束、从父view移除并清空约束、开启cell的frame缓存等相关方法

下面是一个特别的UIView的特别适用方法
  • @interface UIScrollView (SDAutoContentSize)
    • UIScrollView 内容竖向自适应、内容横向自适应方法
  • UILabel (SDLabelAutoResize)
    • 开启富文本布局、设置单行文本label宽度自适应、 设置label最多可以显示的行数
  • @interface UIButton (SDExtention)
    • UIButton 设置button根据单行文字自适应

下面属于扩展熟悉

@interface SDAutoLayoutModelItem : NSObject
@interface UIView (SDChangeFrame)
最后结果的处理
@interface SDUIViewCategoryManager : NSObject

5、主要函数分析

sd_layoutSubviews
1、利用打桩的里面,在layoutSubviews这个函数,加入sd_sd_layoutSubviewsHandle
sd_layoutSubviewsHandle
1、if (self.sd_equalWidthSubviews.count)
//
2、if (self.sd_categoryManager.flowItems.count && (self.sd_categoryManager.lastWidth != self.width_sd))
处理等高处理的view

 3、if (self.autoLayoutModelsArray.count)

真正进行frame计算的判断,主要分为两步,第一步就是缓存的处理,第二步(sd_resizeWithModel)是frame的计算。

4、if (self.tag == kSDModelCellTag && [self isKindOfClass:NSClassFromString(@"UITableViewCellContentView")])

解决UITableviewcell等高计算的,应该是上面的函数没有完全解决这个问题,所以需要额外加入这样的判断。

而且,是UITableViewCellContentView,而不是UITableViewCell,所以在UITableViewCell里面,一般应该将子UIView放入到self.contentview,而不是view里面,不然这个判断会失效,导致cell的高度计算失败

数据计算结果一般都是使用bottom_sd,height_sd等去存储这些数据都是存在于view的。这是新版的处理,旧版的数据没有后缀_sd。新版兼容旧版数据。主要是@interface UIView (SDChangeFrame)完成

  • sd_resizeWithModel
    • 功能
      • 计算frame的主要函数
    • 流程
      • 获取子view
      • 如果不需要自动布局,退出布局
      • // 靠右布局前提设置
      • (layoutWidthWithView:model:)
        • widthIs->width->width_sd和fixedWidth
        • widthRatioToView->ratio_width->width_sd和fixedWidth
      • (layoutHeightWithView:model:)
        • heightIs->height->height_sd和fixedHeight
        • heightRatioToView->ratio_height->height_sd和fixedHeight
      • (layoutLeftWithView:model:)需要重算width_sd
        • leftSpaceToView->left->left_sd
        • leftEqualToView->equalLeft->left_sd
        • centerXEqualToView->equalCenterX->centerX_sd
        • centerXIs->centerX->centerX_sd
      • (layoutRightWithView:model:)需要重算width_sd
        • rightSpaceToView->right->right_sd
        • rightEqualToView->equalRight->right_sd
      • // 底部布局前提设置
      • (layoutTopWithView:model:)需要重算height_sd
        • topSpaceToView->top->top_sd
        • topEqualToView->equalTop->top_sd
        • centerYEqualToView->equalCenterY->centerY_sd
        • centerYIs->centerY->centerY_sd
      • autoHeightRatioValue调用layoutAutoHeightWidthView:model:
        • autoHeightRatioValue根据宽度比例配置高度
      • 根据最大值和最小值进行高度重算
      • (layoutBottomWithView:model:)需要重算height_sd
        • bottomSpaceToView->bottom->bottom_sd
        • bottomEqualToView->equalBottom->bottom_sd
      • 根据widthEqualToHeight->widthEqualHeight或者heightEqualToWidth->heightEqualWidth去令高宽相等
      • 根据sd_bottomViewsArray和sd_rightViewsArray计算是否遍历子View的布局,并且重算高度
      • setupCornerRadiusWithView:model,设置圆角
        • sd_cornerRadius->view.layer.cornerRadius
        • sd_cornerRadiusFromHeightRatio->view.layer.cornerRadius
        • sd_cornerRadiusFromWidthRatio->view.layer.cornerRadius

谢谢!!!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值