Swift编程(六):Snapkit的启示录
写在前面(Github地址)
个人项目
欢迎大家关注我的个人博客:博客地址,这里主要是我在个人开发时候遇到的坑和挖完的坑,包括 PHP CentOS 以及 Swift 等相关只是
主要记录了,我在学习Snapkit中的一些整理记录
学习目标
- 好好学习如何用代码来做自动布局
- 使用SnapKit做了一个修改密码的表单
效果图
1. Snapkit的安装
- Cocoapods安装
在项目的Podfile下添加如下信息
在终端中执行:pod install
(注意路径是当前项目中Podfile锁在路径)
swift
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
use_frameworks!pod 'SnapKit', '~> 0.15.0'
- Carthage安装
Carthage是一种分散式依赖管理库用来自动为你的Cocoa应用添加第三方框架
1) 通过下面命令行执行安装Carthage
swift
brew update
brew install carthage
2) 通过下面命令行继承SnapKit到你的项目中的Cartfile
swift
github "SnapKit/SnapKit" >= 0.15.0
3.)通过直接讲SnapKit的源代码拖放到自己的项目目录当中
这也是我比较喜欢的一种方式,这样可以比较自由的讲代码拖放到自己执行的目录下
2. SnapKit的兼容操作
如果希望SnapKit支持IOS7版本,需要在自己的项目的 Build Setting 中搜索的 OTHER_SWIFT_FLAGS,在其下面添加 -DSNAPKIT_DEPLOYMENT_LEGACY,如下图所示:(否则会报错!)
示意图
3. Snapkit官方文档翻译
通用模式:
swift
let box = UIView()
superview.addSubview(box)
box.snp_makeConstraints { (make) -> Void in
//解释:box对象相对于父视图上边距为20像素
make.top.equalTo(superview).offset(20)
make.left.equalTo(superview).offset(20)
make.bottom.equalTo(superview).offset(-20)
make.right.equalTo(superview).offset(-20)
}
注意:在SnapKit当中 X轴向右方向;Y轴向下方向 为正
缩写形式
swift
let box = UIView()
superview.addSubview(box)
box.snp_makeConstraints { (make) -> Void in
//注释:box距离父视图上下左右边距都是20像素
make.edges.equalTo(superview).inset(UIEdgeInsetsMake(20, 20, 20, 20))
}
SnapKit还可以通过下面几个步骤来实现缩短代码和提高代码可读性
- 确定最佳的普通视图安装限制。
- 保持轨道的约束安装所以他们可以很容易地被删除后。
- 在所有适当的视图上确保
setTranslatesAutoresizingMaskIntoConstraints(false)
属性被设置
SnapKit中并不局限于 等于(equalTo)
- .equalTo:等于
- .lessThanOrEqualTo 小于等于
- .greaterThanOrEqualTo 大于等于
1.视图属性
//当前视图对象的中心x坐标小于等于view视图的左边的x左边
make.centerX.lessThanOrEqualTo(view.snp_left)
视图属性:
上 :上边对应的Y轴 (top)
下: 下边对应的Y轴 (bottom)
左: 左边对应的Y轴 (left)
右: 右边对应的X轴 (right)
视图属性(ViewAttribute) | 布局属性 (NSLayoutAttribute) |
---|---|
view.snp_left | NSLayoutAttribute.Left |
view.snp_right | NSLayoutAttribute.Right |
view.snp_top | NSLayoutAttribute.Top |
view.snp_bottom | NSLayoutAttribute.Bottom |
view.snp_leading | NSLayoutAttribute.Leading |
view.snp_trailing | NSLayoutAttribute.Trailing |
view.snp_width | NSLayoutAttribute.Width |
view.snp_height | NSLayoutAttribute.Height |
view.snp_centerX | NSLayoutAttribute.CenterX |
view.snp_centerY | NSLayoutAttribute.CenterY |
view.snp_baseline | NSLayoutAttribute.Baseline |
2.视图关系(UIView/NSView)
如果你想 视图 view.left 大于等于 label.left ,执行下面代码:
swift
//下面这两者的约束是完全一样的
make.left.greaterThanOrEqualTo(label)
make.left.greaterThanOrEqualTo(label.snp_left)
3.严格检测(Strick Checks)
自动布局允许将宽度和高度属性设置为常量值。如果你想对视图设置一个最小和最大宽度,你必须先给他一个初始的平等块:
swift
//设置宽度>= 200 && <= 400
你也可以用其他的约束和结构来建立你的约束,像这样:
swift
make.top.equalTo(42)
make.height.equalTo(20)
make.size.equalTo(CGSizeMake(50,100))
make.edges.equalTo(UIEdgeInsetsMake(10,0,10,0))
make.left.equalTo(view).offset(UIEdgeInsetsMake(10,0,10,0))
4.学习优先级
- .priority: 允许您指定一个确切的优先级
- .priorityHigh: 高优先级 等价于 UILayoutPriority.DefaultHigh
- .priorityMedium:中优先级
- .priorityLow:低优先级 UILayoutPriority.DefaultLow
优先级可以放在约束链的结束处,例如
swift
//当前视图的左边>=label的底部 低优先级
make.left.greaterThanOrEqualTo(label.snp_left).priorityLow()
//当前视图与label的顶部齐平,优先级:600
make.top.equalTo(label.snp_top).priority(600)
5.组成,组成,组成
SnapKit 也可以提供一些便利的方法来同时创建多约束
- edges(边缘)
swift
//让当前视图 的 上下左右(top,left,bottom,right) 等于 view2
make.edges.equalTo(view2)
// make top = superview.top + 5; left = superview.left +10
// bottom = superview.bottom -15; right = superview.right - 20
make.edges.equalTo(superView).inset(UIEdgeInsetsMake(5,10,15,20))
2.size(尺寸)
swift
//当前视图宽高 >= titleLabel
make.size.greaterThanOrEqualTo(titleLabel)
//make width = superview.width + 100; height = superview.height -50
//即 当前视图宽 = 父视图 + 100,高 = 父视图.高 - 50
make.size.equalTo(superview).offset(CGSizeMake(100, -50))
3.center(中心)
swift
//当前视图与 button1中心相同 (centerX 和 centerY)
make.center.equalTo(button1)
//make centerX = superview.centerX - 5; centerY = superview.centerY +10
make.center.equalTo(superview).offset(CGPointMake(-5,10))
您可以串连视图属性增加可读性
swift
//所有边缘除了top都等于父视图, top为20
make.left.right.bottom.equalTo(superview)
make.top.equalTo(20)
6.Hold on for dear life
有时候你需要修改已经存在的约束为了移动或者移除、代替约束。在SnapKit 有一些不同的方法更新约束
1.引用(References)
你可以通过将约束的结果赋值给一个局部变量或一个类属性来保持一个特定的约束的引用。您还可以将多个约束引用存储在数组中。
swift
var topConstraint: Constraint? = nil
//当制作约束时
view1.snp_makeConstraints{ (make) -> Void in
self.topConstrain = make.top.equalTo(superview).offset(padding.top).constraint
make.left.equalTo(superview).offset(padding.left)
// 然后接下来你可以这样
self.topConstraint.uninstall()
//或者如果你想要更新约束
self.topConstraint.updateOffset(5)
2.snp_updateConstraints(更新约束)
如果你仅仅想更新一个常数给一个约束,你可以使用方法snp_updateConstraints
来代替snp_makeConstraints
swift
//这是一个苹果官方推荐的添加和更新约束的地方
//这个方法在响应<code>setNeedsUpdateConstraints</code>多次调用
//这个方法可以倍UIKit调用
override func updateConstraints() {
self.growingButton.snp_updateConstraints{ (make) -> Void in
make.center.equalTo(self);
make.width.equalTo(self.buttonSize.width).priorityLow()
make.height.equalTo(self.buttonSize.height).priorityLow()
make.width.lessThanOrEqualTo(self)
make.height.lessThanOrEqualTo(self)
}
//父类可以调用
super.updateConstraints()
}
3.snp_remakeConstraints(重做约束)
snp_remakeConstraints
与snp_makeConstraints
类似,但是首先会先清除掉所有被SnapKit设置的约束
swift
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)
}
}
}
4.Demo的具体代码(我的Github)
创建属性
swift
var oldPassword: UITextField!
var newPassword: UITextField!
var confirmPassword: UITextField!
var formView: UIView!
var confirmButton:UIButton!
var topConstraint: Constraint?
UI初始化
swift
func initUI(){
self.title = "修改密码"
self.view.backgroundColor = UIColor.redColor()
//登录框背景
self.formView = UIView()
self.formView.layer.borderWidth = 0.5
self.formView.layer.borderColor = UIColor.lightGrayColor().CGColor
self.formView.backgroundColor = UIColor.whiteColor()
self.formView.layer.cornerRadius = 5
self.view.addSubview(self.formView)
//最常规的设置模式
self.formView.snp_makeConstraints { (make) -> Void in
make.left.equalTo(15)
make.right.equalTo(-15)
//存储top属性
self.topConstraint = make.top.equalTo(200).constraint
make.height.equalTo(220)
}
//密码图
let imgLock1 = UIImageView(frame:CGRectMake(11, 11, 22, 22))
imgLock1.image = UIImage(named:"iconfont-password")
//密码图
let imgLock2 = UIImageView(frame:CGRectMake(11, 11, 22, 22))
imgLock2.image = UIImage(named:"iconfont-password")
//密码图
let imgLock3 = UIImageView(frame:CGRectMake(11, 11, 22, 22))
imgLock3.image = UIImage(named:"iconfont-password")
//旧密码输入框
self.oldPassword = UITextField()
self.oldPassword.delegate = self
self.oldPassword.tag = 100
self.oldPassword.placeholder = "请输入旧密码"
self.oldPassword.layer.cornerRadius = 5
self.oldPassword.layer.borderColor = UIColor.lightGrayColor().CGColor
self.oldPassword.layer.borderWidth = 0.5
self.oldPassword.leftView = UIView(frame:CGRectMake(0, 0, 44, 44))
self.oldPassword.leftViewMode = UITextFieldViewMode.Always
self.oldPassword.returnKeyType = UIReturnKeyType.Next
//密码输入框左侧图标
self.oldPassword.leftView!.addSubview(imgLock1)
self.formView.addSubview(self.oldPassword)
//布局
self.oldPassword.snp_makeConstraints { (make) -> Void in
make.left.equalTo(30)
make.top.equalTo(20)
make.right.equalTo(-30)
make.height.equalTo(44)
}
//新密码输入框
self.newPassword = UITextField()
self.newPassword.delegate = self
self.newPassword.tag = 101
self.newPassword.placeholder = "请输入新密码"
self.newPassword.layer.cornerRadius = 5
self.newPassword.layer.borderColor = UIColor.lightGrayColor().CGColor
self.newPassword.layer.borderWidth = 0.5
self.newPassword.leftView = UIView(frame:CGRectMake(0, 0, 44, 44))
self.newPassword.leftViewMode = UITextFieldViewMode.Always
self.newPassword.returnKeyType = UIReturnKeyType.Next
//密码输入框左侧图标
self.newPassword.leftView!.addSubview(imgLock2)
self.formView.addSubview(self.newPassword)
//布局
self.newPassword.snp_makeConstraints { (make) -> Void in
make.left.equalTo(30)
make.top.equalTo(self.oldPassword.snp_bottom).offset(20)
make.right.equalTo(-30)
make.height.equalTo(44)
}
//确认新密码输入框
self.confirmPassword = UITextField()
self.confirmPassword.delegate = self
self.confirmPassword.tag = 102
self.confirmPassword.placeholder = "请重复新密码"
self.confirmPassword.layer.cornerRadius = 5
self.confirmPassword.layer.borderColor = UIColor.lightGrayColor().CGColor
self.confirmPassword.layer.borderWidth = 0.5
self.confirmPassword.leftView = UIView(frame:CGRectMake(0, 0, 44, 44))
self.confirmPassword.leftViewMode = UITextFieldViewMode.Always
self.confirmPassword.returnKeyType = UIReturnKeyType.Done
//密码输入框左侧图标
self.confirmPassword.leftView!.addSubview(imgLock3)
self.formView.addSubview(self.confirmPassword)
//布局
self.confirmPassword.snp_makeConstraints { (make) -> Void in
make.left.equalTo(30)
make.top.equalTo(self.newPassword.snp_bottom).offset(20)
make.right.equalTo(-30)
make.height.equalTo(44)
}
self.confirmButton = UIButton()
self.confirmButton.setTitle("确认修改", forState: UIControlState.Normal)
self.confirmButton.setTitleColor(UIColor.whiteColor(), forState: UIControlState.Normal)
self.confirmButton.layer.cornerRadius = 5
self.confirmButton.backgroundColor = UIColor(colorLiteralRed: 0.99, green: 0.82, blue: 0.04, alpha: 1)
self.view.addSubview(self.confirmButton)
self.confirmButton.snp_makeConstraints { (make) -> Void in
make.left.equalTo(15)
make.top.equalTo(self.formView.snp_bottom).offset(20)
make.right.equalTo(-15)
make.height.equalTo(44)
}
}
UITextField的代理
swift
extension SnapkitViewController: UITextFieldDelegate {
//输入框获取焦点开始编辑
func textFieldDidBeginEditing(textField:UITextField)
{
let tag = textField.tag
switch tag {
case 100:
UIView.animateWithDuration(0.5, animations: { () -> Void in
self.topConstraint?.updateOffset(150)
self.view.layoutIfNeeded()
})
case 101:
UIView.animateWithDuration(0.5, animations: { () -> Void in
self.topConstraint?.updateOffset(100)
self.view.layoutIfNeeded()
})
case 102:
UIView.animateWithDuration(0.5, animations: { () -> Void in
self.topConstraint?.updateOffset(70)
self.view.layoutIfNeeded()
})
default:
print("error")
}
}
//输入框返回时操作
func textFieldShouldReturn(textField:UITextField) -> Bool
{
let tag = textField.tag
switch tag {
case 100:
self.newPassword.becomeFirstResponder()
case 101:
//下一个
self.confirmPassword.becomeFirstResponder()
case 102:
//收起键盘
textField.resignFirstResponder()
UIView.animateWithDuration(0.5, animations: { () -> Void in
self.topConstraint?.updateOffset(200)
self.view.layoutIfNeeded()
})
default:
print(textField.text)
}
return true
}
}
5.总结一下 UITextField
样式
swift
UITextBorderStyle.None:无边框
UITextBorderStyle.Line:直线边框
UITextBorderStyle.RoundedRect:圆角矩形边框
UITextBorderStyle.Bezel:边线+阴影
输入提示
```swift textField.placeholder="请输入用户名" ````
内容设置
swift
//当文字超出文本框宽度时,自动调整文字大小
textField.adjustsFontSizeToFitWidth = true
//最小可缩小的字号
textField.minimumFontSize = 14
对齐方式
swift
//水平右对齐
textField.textAlignment = .Right
//水平居中对齐
textField.textAlignment = .Center
//水平左对齐
textField.textAlignment = .Left
//垂直向上对齐
textField.contentVerticalAlignment = .Top
//垂直居中对齐
textField.contentVerticalAlignment = .Center
//垂直向下对齐
textField.contentVerticalAlignment = .Bottom
设置清除按钮
swift
//编辑时出现清除按钮
textField.clearButtonMode = UITextFieldViewMode.WhileEditing
//编辑时不出现,编辑后才出现清除按钮
textField.clearButtonMode = UITextFieldViewMode.UnlessEditing
//一直显示清除按钮
textField.clearButtonMode = UITextFieldViewMode.Always
设置键盘的类型
swift
Default:系统默认的虚拟键盘
ASCII Capable:显示英文字母的虚拟键盘
Numbers and Punctuation:显示数字和标点的虚拟键盘
URL:显示便于输入数字的虚拟键盘
Number Pad:显示便于输入数字的虚拟键盘
Phone Pad:显示便于拨号呼叫的虚拟键盘
Name Phone Pad:显示便于聊天拨号的虚拟键盘
Email Address:显示便于输入Email的虚拟键盘
Decimal Pad:显示用于输入数字和小数点的虚拟键盘
Twitter:显示方便些Twitter的虚拟键盘
Web Search:显示便于在网页上书写的虚拟键盘
//例子
textField.keyboardType = UIKeyboardType.NumberPad
焦点
swift
//获取焦点
textField.becomeFirstResponder()
//移除焦点
textField.resignfirstresponder()
设置返回return样式跟功能
swift
//表示完成输入
textField.returnKeyType = UIReturnKeyType.Done
//表示完成输入,同时会跳到另一页
textField.returnKeyType = UIReturnKeyType.Go
//表示搜索
textField.returnKeyType = UIReturnKeyType.Search
//表示注册用户或添加数据
textField.returnKeyType = UIReturnKeyType.Join
//表示继续下一步
textField.returnKeyType = UIReturnKeyType.Next
//表示发送
textField.returnKeyType = UIReturnKeyType.Send
代理
swift
//开始编辑时的操作
func textFieldDidBeginEditing()
//点击返回按钮时的操作
func textFieldShouldReturn()