SnapKit - 修改约束

AutoLayout现在是iOS开发布局的必备,对于使用Swift语言开发的项目,我们经常使用SnapKit进行UI布局,因为使用简单,方便。基本的使用方法官方已经写的非常详情了,可以看这里官方为我们提供了几种方式来修改约束,先了解一下:

1、引用约束(References)

我们能够声明一个局部变量或者类属性来引用我们想要修改的约束,也可以使用数组存储引用多个约束,然后对引用的约束进行修改

var topConstraint: Constraint? = nil

...

// when making constraints
view1.snp.makeConstraints { (make) -> Void in
  self.topConstraint = make.top.equalTo(superview).offset(padding.top).constraint
  make.left.equalTo(superview).offset(padding.left)
}

...
// then later you can call
self.topConstraint.uninstall()

// or if you want to update the constraint
self.topConstraint.updateOffset(5)

2、使用updateConstraints进行约束更新

如果我们仅仅只想更新约束的常量值,那么我们可以使用updateConstraints方法

// this is Apple's recommended place for adding/updating constraints
// this method can get called multiple times in response to setNeedsUpdateConstraints
// which can be called by UIKit internally or in your code if you need to trigger an update to your constraints
override func updateConstraints() {
    self.growingButton.snp.updateConstraints { (make) -> Void in
        make.center.equalTo(self);
        make.width.equalTo(self.buttonSize.width).priority(250)
        make.height.equalTo(self.buttonSize.height).priority(250)
        make.width.lessThanOrEqualTo(self)
        make.height.lessThanOrEqualTo(self)
    }
    
   // according to Apple super should be called at end of method
	 super.updateConstraints()
}

注意:更新约束是基于现有的约束条件进行修改其常量值,如果不是对已有的约束进行修改,那么会出错,并且不需要将所有的约束重新写一遍,只需要修改想要更新的约束即可。例如:一个UILabel控件,相对于父视图左右边距分别是10,并且居中显示,添加约束如下:

 label.snp.makeConstraints { (make) in
     make.centerY.equalToSuperview()
     make.left.right.equalToSuperview().inset(10)
 }

现在修改距离左右两边的约束为30,直接使用updateConstraints方法即可

label.snp.updateConstraints { (make) in
    make.left.right.equalToSuperview().inset(30)
}

3、使用remarkConstraints修改约束

使用remarkConstraints跟使用makeConstriants相似,但是首先会将之前所有的约束都去除,然后重新添加相关的约束

func changeButtonPosition() {
  self.button.snp.remakeConstraints { (make) -> Void in 
    make.size.equalTo(self.buttonSize)
    if topLeft {
      make.top.left.equalTo(10)
    } else {
      make.bottom.equalTo(self.view).offset(-10)
      make.right.equalTo(self.view).offset(-10)
    }
  }
}

开发的过程中,我们可能会碰到这样的需求:一个UI控件事先已经添加好约束了,这时候我想修改改控件其中的一个约束或者多个约束,并且约束的对象也发生了改变。实现思路有2种:

1)使用remarkConstraints方法在对应的条件下添加约束

2)事先添加所需要的所有约束并对约束进行引用,然后配合Constraints的activate()方法和deactivate()方法,使用deactivate()处理暂时不需要的约束,在需要的时候activate()需要的约束。

看一个简单例子

添加两个UILabel和一个UISwitch控件,点击UISwitch修改对应的约束。初始化基本约束和页面效果如下:

 func setupConstraints() {
        label1.snp.makeConstraints { (make) in
            make.left.top.equalToSuperview().inset(50)
            make.size.equalTo(CGSize(width: 100, height: 100))
        }
        label2.snp.makeConstraints { (make) in
            make.left.size.equalTo(label1)
            make.top.equalTo(label1.snp.bottom).offset(50)
        }
        st.snp.makeConstraints { (make) in
            make.center.equalToSuperview()
        }
        st.addTarget(self, action: #selector(tapSwitch(_:)), for: .touchUpInside)
    }

页面效果


1)使用remarkConstraints方法修改约束,如果是点击打开,那么将label2设置约束为距离父视图的右边为50,大小变为200,顶部相对于label1的底部,如果是关闭,那么回到最初的约束

    @objc func tapSwitch(_ st: UISwitch) {
        if st.isOn {
            label2.snp.remakeConstraints { (make) in
                make.right.equalToSuperview().offset(-50)
                make.size.equalTo(CGSize(width: 200, height: 200))
                make.top.equalTo(label1.snp.bottom)
            }
        } else {
            label2.snp.remakeConstraints { (make) in
                make.left.size.equalTo(label1)
                make.top.equalTo(label1.snp.bottom).offset(50)
            }
        }
    }

可以看到操作也挺简单,直接使用remarkConstraints方法添加想要的约束即可。

2)使用activate()和deactivate()

1、需要使用变量引用对应的约束

var leftConstraint: Constraint!
var rightConstraint: Constraint!
var originalSizeConstraint: Constraint!
var orignalTopConstraint: Constraint!
var targetTopConstraint: Constraint!
var targetSizeConstraint: Constraint!
var originalConstraints: [Constraint] = []
var targetConstraints: [Constraint] = []

2、为label2添加所有的约束

label2.snp.makeConstraints { (make) in
    leftConstraint = make.left.equalTo(label1).constraint
    originalSizeConstraint = make.size.equalTo(label1).constraint
    orignalTopConstraint = make.top.equalTo(label1.snp.bottom).offset(50).constraint

    targetTopConstraint = make.top.equalTo(label1.snp.bottom).priority(999).constraint
    targetSizeConstraint =  make.size.equalTo(CGSize(width: 200, height: 200)).priority(999).constraint
    rightConstraint = make.right.equalToSuperview().offset(-50).priority(999).constraint
 }

这里需要将目标约束降低优先级,不然会出现约束冲突,因为系统不知道什么使用约束,当约束优先级被降低之后,会默认先使用高优先级。

3、使用数组存储对应的约束,方便后续的操作,注意:失效目标约束,即去除多余的约束

 // 添加到对应的数组
 originalConstraints.append(leftConstraint)
 originalConstraints.append(orignalTopConstraint)
 originalConstraints.append(originalSizeConstraint)

 targetConstraints.append(targetTopConstraint)
 targetConstraints.append(targetSizeConstraint)
 targetConstraints.append(rightConstraint)

 // 失效之后的约束
 targetConstraints.forEach {$0.deactivate()}

4、点击开关修改约束

 @objc func tapSwitch(_ st: UISwitch) {
     if st.isOn { // 失效原有约束,生效目标约束
         originalConstraints.forEach {$0.deactivate()}
         targetConstraints.forEach {$0.activate()}
     } else { // 失效目标约束,生效原有的约束
         targetConstraints.forEach {$0.deactivate()}
         originalConstraints.forEach {$0.activate()}
     }
}





猜你喜欢

转载自blog.csdn.net/longshihua/article/details/80289061