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