寫在前面(Github地址)
個人項目
歡迎大家關注我的個人博客:<a >博客地址</a>,這里主要是我在個人開發時候遇到的坑和挖完的坑,包括 PHP CentOS 以及 Swift 等相關只是
主要記錄了,我在學習Snapkit中的一些整理記錄
學習目標
- 好好學習如何用代碼來做自動布局
- 使用SnapKit做了一個修改密碼的表單
1. Snapkit的安裝
- Cocoapods安裝
在項目的Podfile下添加如下信息
在終端中執行:<code>pod install</code>(注意路徑是當前項目中Podfile鎖在路徑)
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
use_frameworks!pod 'SnapKit', '~> 0.15.0'
- Carthage安裝
Carthage是一種分散式依賴管理庫用來自動為你的Cocoa應用添加第三方框架
1) 通過下面命令行執行安裝Carthage
brew update
brew install carthage
2) 通過下面命令行繼承SnapKit到你的項目中的Cartfile
github "SnapKit/SnapKit" >= 0.15.0
3.)通過直接講SnapKit的源代碼拖放到自己的項目目錄當中
這也是我比較喜歡的一種方式,這樣可以比較自由的講代碼拖放到自己執行的目錄下
2. SnapKit的兼容操作
如果希望SnapKit支持IOS7版本,需要在自己的項目的 Build Setting 中搜索的 OTHER_SWIFT_FLAGS,在其下面添加 -DSNAPKIT_DEPLOYMENT_LEGACY,如下圖所示:(否則會報錯!)
3. Snapkit官方文檔翻譯
通用模式:
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軸向下方向 為正
縮寫形式
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還可以通過下面幾個步驟來實現縮短代碼和提高代碼可讀性
- 確定最佳的普通視圖安裝限制。
- 保持軌道的約束安裝所以他們可以很容易地被刪除后。
- 在所有適當的視圖上確保 <code>setTranslatesAutoresizingMaskIntoConstraints(false)</code>屬性被設置
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 ,執行下面代碼:
//下面這兩者的約束是完全一樣的
make.left.greaterThanOrEqualTo(label)
make.left.greaterThanOrEqualTo(label.snp_left)
3.嚴格檢測(Strick Checks)
自動布局允許將寬度和高度屬性設置為常量值。如果你想對視圖設置一個最小和最大寬度,你必須先給他一個初始的平等塊:
//設置寬度>= 200 && <= 400
你也可以用其他的約束和結構來建立你的約束,像這樣:
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
優先級可以放在約束鏈的結束處,例如
//當前視圖的左邊>=label的底部 低優先級
make.left.greaterThanOrEqualTo(label.snp_left).priorityLow()
//當前視圖與label的頂部齊平,優先級:600
make.top.equalTo(label.snp_top).priority(600)
5.組成,組成,組成
SnapKit 也可以提供一些便利的方法來同時創建多約束
- edges(邊緣)
//讓當前視圖 的 上下左右(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(尺寸)
//當前視圖寬高 >= 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))
您可以串連視圖屬性增加可讀性
//所有邊緣除了top都等于父視圖, top為20
make.left.right.bottom.equalTo(superview)
make.top.equalTo(20)
6.Hold on for dear life
有時候你需要修改已經存在的約束為了移動或者移除、代替約束。在SnapKit 有一些不同的方法更新約束
1.引用(References)
你可以通過將約束的結果賦值給一個局部變量或一個類屬性來保持一個特定的約束的引用。您還可以將多個約束引用存儲在數組中。
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(更新約束)
如果你僅僅想更新一個常數給一個約束,你可以使用方法<code>snp_updateConstraints</code>來代替<code>snp_makeConstraints</code>
//這是一個蘋果官方推薦的添加和更新約束的地方
//這個方法在響應<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(重做約束)
<code>snp_remakeConstraints</code>與<code>snp_makeConstraints</code>類似,但是首先會先清除掉所有被SnapKit設置的約束
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)
創建屬性
var oldPassword: UITextField!
var newPassword: UITextField!
var confirmPassword: UITextField!
var formView: UIView!
var confirmButton:UIButton!
var topConstraint: Constraint?
UI初始化
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的代理
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
樣式
UITextBorderStyle.None:無邊框
UITextBorderStyle.Line:直線邊框
UITextBorderStyle.RoundedRect:圓角矩形邊框
UITextBorderStyle.Bezel:邊線+陰影
輸入提示
textField.placeholder="請輸入用戶名"
內容設置
//當文字超出文本框寬度時,自動調整文字大小
textField.adjustsFontSizeToFitWidth = true
//最小可縮小的字號
textField.minimumFontSize = 14
對齊方式
//水平右對齊
textField.textAlignment = .Right
//水平居中對齊
textField.textAlignment = .Center
//水平左對齊
textField.textAlignment = .Left
//垂直向上對齊
textField.contentVerticalAlignment = .Top
//垂直居中對齊
textField.contentVerticalAlignment = .Center
//垂直向下對齊
textField.contentVerticalAlignment = .Bottom
設置清除按鈕
//編輯時出現清除按鈕
textField.clearButtonMode = UITextFieldViewMode.WhileEditing
//編輯時不出現,編輯后才出現清除按鈕
textField.clearButtonMode = UITextFieldViewMode.UnlessEditing
//一直顯示清除按鈕
textField.clearButtonMode = UITextFieldViewMode.Always
設置鍵盤的類型
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
焦點
//獲取焦點
textField.becomeFirstResponder()
//移除焦點
textField.resignfirstresponder()
設置返回return樣式跟功能
//表示完成輸入
textField.returnKeyType = UIReturnKeyType.Done
//表示完成輸入,同時會跳到另一頁
textField.returnKeyType = UIReturnKeyType.Go
//表示搜索
textField.returnKeyType = UIReturnKeyType.Search
//表示注冊用戶或添加數據
textField.returnKeyType = UIReturnKeyType.Join
//表示繼續下一步
textField.returnKeyType = UIReturnKeyType.Next
//表示發送
textField.returnKeyType = UIReturnKeyType.Send
代理
//開始編輯時的操作
func textFieldDidBeginEditing()
//點擊返回按鈕時的操作
func textFieldShouldReturn()