swift学习之屏幕适配(SnapKit)


SnapKit简介

  • SnapKit是一个优秀的第三方自适应布局库,它可以让iOS、OS X应用更简单地实现自动布局(Auto Layout)。它的作者仍然是写Objective-C的第三方库Masonry的大牛 - @Robert Payne

  • 下载链接 SnapKit

SnapKit配置

  • 在项目工程里的Podfile文件里面添加

    source 'https://github.com/CocoaPods/Specs.git'      
    platform :ios, '10.0'
    use_frameworks!
    target '这里是你的工程名称' do
    pod 'SnapKit', '~> 3.0'
    end
  • 运行CocoaPods命令

    pod install
  • 引入头文件 import SnapKit

    import UIKit
    import SnapKit

SnapKit使用

  • 示例:

    testView.snp.makeConstraints { (make) in
        make.left.equalToSuperview().offset(50)
        make.right.equalToSuperview().offset(-50)
        make.top.equalToSuperview().offset(50)
        make.bottom.equalToSuperview().offset(-50)
    }
  • 基本格式:(make . 指定其的一个属性.约束关系)

    make.attr.constrains

     

  • make:可认为是要布局的view的代理 constrains:约束可能是多级的组合,比如make.left.equalToSuperview().offset(50)的两级组合,显示找到父view的左边位置,再向右(X轴)移动50点

给控件添加、更新约束、引用约束、停用、启用

  • 添加新的约束

    testView.snp.makeConstraints { (make) in
      
    }
  • 删除控件以前所有约束,添加新约束

    testView.snp.remakeConstraints { (make) in
      
    }
  • 更新约束,写哪条更新哪条,其他约束不变

    testView.snp.updateConstraints { (make) in
     
    }
  • 引用约束,声明一个局部变量或者类属性来引用要修改的约束

    var topConstraint: Constraint? = nil
    override func viewDidLoad() {
        super.viewDidLoad()        
    
        let testView = UIView()
        testView.backgroundColor = UIColor.red
        self.view.addSubview(testView)
          
        testView.snp.makeConstraints { (make) in
            self.topConstraint = make.left.equalToSuperview().offset(100).constraint
            make.right.equalToSuperview().offset(-100)
            make.top.equalToSuperview().offset(100)
            make.bottom.equalToSuperview().offset(-100)
         }
    }  
  • 停用

    self.topConstraint?.deactivate()
  • 启用

    self.topConstraint?.activate()

设置约束关系

约束关系 说明
equalTo() 设置属性等于某个数值
greaterThanOrEqualTo() 设置属性大于或等于某个数值
lessThanOrEqualTo() 设置属性小于或等于某个数值
multipliedBy() 设置属性乘以因子后的值
dividedBy() 设置属性除以因子后的值
  • Snapkit 的 greaterThanOrEqualTo 属性

    如果想让视图View2的左边>=父视图View1的左边, 这时我们就可以用到greaterThanOrEqualTo

    ///黑色视图作为父视图
    let view1 = UIView()
    view1.frame = CGRect(x: 0.0, y: 0.0, width: 300, height: 300)
    view1.center = view.center
    view1.backgroundColor = .black
    view.addSubview(view1)
            
    ///测试视图
    let view2 = UIView()
    view2.backgroundColor = .magenta
    view1.addSubview(view2)
    view2.snp.makeConstraints { (make) in
        make.top.equalTo(view1.snp.bottom).offset(10)
        make.width.height.equalTo(100)
        make.left.greaterThanOrEqualTo(view1)
    }

    效果图

  • lessThanOrEqualTo的用于上、下、左、右

    如果我们想要视图view2的左边 <= view1.left + 10, 那么就可以直接用到lessThanOrEqualTo布局了,看下面这个例子

    let view1 = UIView()
    view1.frame = CGRect(x: 0.0, y: 0.0, width: 300.0, height: 300.0)
    view1.center = view.center
    view1.backgroundColor = .black
    view.addSubview(view1)
            
    let view2 = UIView()
    view2.backgroundColor = .magenta
    view1.addSubview(view2)
    view2.snp.makeConstraints { (make) in
        make.left.lessThanOrEqualTo(20.0) //<= 父视图的左边+20
        make.right.equalTo(-40.0)         // = 父视图的右边-40
        make.height.equalTo(100.0)
        make.center.equalToSuperview()
    }
  • SnapKit的greaterThanOrEqualTo和lessThanOrEqualTo联合使用

    当我们想要让某个视图的width或height大于等于某个特定的值,小于等于某个特定的值的时候,一般而言,Snapkit会以greaterThanOrEqualTo为准,这里举一个width的例子,为了方便,这里指贴出了viewDidLoad中的代码(其他没必要)

    let view1 = UIView()
    view1.frame = CGRect(x: 0.0, y: 0.0, width: 300.0, height: 300.0)
    view1.center = view.center
    view1.backgroundColor = .black
    view.addSubview(view1)
            
    let view2 = UIView()
    view2.backgroundColor = .magenta
    view1.addSubview(view2)
    view2.snp.makeConstraints { (make) in
        make.width.lessThanOrEqualTo(300)
        make.width.greaterThanOrEqualTo(200)
        make.height.equalTo(100)
        make.center.equalToSuperview()
    }

    接着,我们来看一下效果图

    很明显,最后的宽度是以make.width.greaterThanOrEqualTo(200)为标准的,也可以这样的,在同时使用两者的情况下,greaterThanOrEqualTo的优先级略比lessThanOrEqualTo的优先级高。值得一提的是, 在上面的例子中,如果我们只设置make.width.lessThanOrEqualTo(300),那么view2是不会显示出来的,因为view2不知道你要表达的是要显示多少,小于等于300,到底是100还是200呢?(这里指针对width和height)所以它不能确定这个约束的值,但是,如果我们单独设置make.width.greaterThanOrEqualTo(200),那么就和上面的效果一样,因为它会以200为标准布局约束!

设置控件布局属性

布局属性 说明
尺寸 widthheightsize
边距 lefttoprightbottomleadingtrailing
中心点 centercenterXcenterY
边界 edges
//iOS8之后Masonry新出了几个属性: //距离边框的距离,等同于选中Storyboard的Constrain to margins后加约束public var leftMargin: SnapKit.ConstraintMakerExtendable { get } public var rightMargin: SnapKit.ConstraintMakerExtendable { get } public var topMargin: SnapKit.ConstraintMakerExtendable { get } public var bottomMargin: SnapKit.ConstraintMakerExtendable { get } public var leadingMargin: SnapKit.ConstraintMakerExtendable { get } public var trailingMargin: SnapKit.ConstraintMakerExtendable { get } public var centerXWithinMargins: SnapKit.ConstraintMakerExtendable { get } public var centerYWithinMargins: SnapKit.ConstraintMakerExtendable { get }

其中leadinglefttrailingright 在正常情况下是等价的,但是当一些布局是从右至左时(比如阿拉伯文) 则会对调

设置约束偏移

方法 参数 说明
offset(CGFloat offset) CGFloat 控件属性相对于参照物偏移多少
insets(MASEdgeInsets insets) MASEdgeInsets 控件四边相对于参照物偏移多少
  • offset示例

    testView.snp.makeConstraints { (make) in
        make.left.equalToSuperview().offset(20)
        make.right.equalToSuperview().offset(-20)
        make.top.equalToSuperview().offset(20)
        make.bottom.equalToSuperview().offset(-20)
    }
  • insets示例

    刚开始使用 SnapKit 时,我都是直接使用 offset 来控制边距的:

    view.snp.makeConstraints {
        $0.top.left.equalToSuperview().offset(10)
        $0.right.bottom.equalToSuperview().offset(-10)
    }

    offset 使用的是绝对值,例如说 superviewbottom 是 300 时,那 viewbottom 就会是 300 + (-10)

    为了简化在这种情况下的语法,SnapKit 封装了一个高级抽象 inset,帮我们自动转换:

    switch layoutAttribute {
        case .left   : return value.left
        case .top    : return value.top
        case .right  : return -value.right
        case .bottom : return -value.bottom
        ...
    }

    使用 inset,之前的代码就可以简化成这样:

    view.snp.makeConstraints {
        $0.top.left.bottom.right.equalToSuperview().inset(10)
        // 或者直接使用 edges
        $0.edges.equalToSuperview().inset(10)
    }

    总结一句就是,在描述 view 与 superview 关系时,应该使用 inset,而描述 view 与同一层级的其它 view 时,应该使用 offset

设置约束优先级

  • SnapKit为我们提供了三个默认的方法,requiredhighmediumlow,优先级最大数值是1000

    public static var required: ConstraintPriority {
        return 1000.0
    }
    public static var high: ConstraintPriority {
        return 750.0
    }
    public static var medium: ConstraintPriority {
        #if os(OSX)
            return 501.0
        #else
            return 500.0
        #endif
    }
    public static var low: ConstraintPriority {
        return 250.0
    }
  • 自己设置优先级的值,可以通过priority()方法来设置

    testView.snp.makeConstraints { (make) in
        make.center.equalToSuperview()
        make.width.equ  alTo(100).priority(ConstraintPriority.low)
        make.width.equalTo(100).priority(ConstraintPriority.high)
       
        make.height.equalTo(100).priority(200)
        make.height.equalTo(50).priority(800)
    }

Snapkit布局的灵活性

  • Snapkit布局灵活性很强, 我们看下面的例子, 他们的效果是一样的
    make.left.equalToSuperview().offset(10)
    make.left.equalTo(10)
    make.left.equalTo(view1.snp.left).offset(10)
  • 设置视图的大小(width,height),他们效果是一样的

    make.width.height.equalTo(100)
    或
    make.width.equalTo(100)
    make.height.equalTo(100)
    或
    make.size.equalTo(CGSize(width: 100, height: 100))

SnapKit 注意

  • 使用SnapKit添加约束之前,需要在addSubview之后才能使用,否则会导致崩溃
  • 在添加约束时常会出现一些错误,约束出现问题的原因一般就是两种:约束冲突和缺少约束。对于这两种问题,可以通过调试和log排查


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM