使用Xib制作簡單的AlertView
不僅僅是個AlertView
1.啟動Xcode, 新建一個Single View Application, 填寫項目名稱SimpleAlertView, 點擊下一步, 找一個位置存放項目, 完成創(chuàng)建.
2.新建一個Xib文件, 文件名為SimpleAlertView.
3.打開SimpleAlertView.xib文件, 選中view, 對它的屬性做一些修改:
修改列表
屬性 | 屬性值 |
---|---|
Size | FreeForm |
Status Bar | None |
Width | 280 |
Height | 130 |
改完之后, view將不會那么巨大......
4.擺放控件
- Label
拖放兩個label到view中, 對label的字體屬性分別做以下修改
字體大的做為標題, 小的做為提示信息. 然后分別給兩個label增加一些約束, 左圖是要給標題label添加的, 右圖是針對提示信息label的.
最后選中提示信息label, 修改它的一個屬性, 讓label中的文字可以適應label的大小.
- Button
拖兩個button到view中, 一個是取消按鈕, 另一個是確定按鈕.
選中剛剛添加的兩個button, 使用StackView對它們進行布局. 選中button之后, 點擊設計面板右下角的Stack按鈕, 這樣就將兩個button放在StackView中了.
ok, 現(xiàn)在選中stackView, 只要對它添加一些約束以及修改一兩個屬性, button就布局好了.
最后只要修改button的一些屬性, 所有的布局就完成啦!!!!!!!!
屬性 | 取消按鈕 | 確定按鈕 |
---|---|---|
Title | Cancle | Confirm |
Text Color | Black | White |
background(RGB) | 235 235 235 | 149 77 235 |
完成后的截圖如下:
現(xiàn)在進入代碼環(huán)節(jié)
1.創(chuàng)建一個新的類文件, 選擇Cocoa Touch Class, 點擊下一步. 類的名稱為SimpleAlertView, 繼承自UIView, 完成創(chuàng)建.
2.打開SimpleAlertView.xib, 把它和剛剛創(chuàng)建的類綁定起來, 這樣就可以在SimpleAlertView.swift代碼文件中對自定義的SimpleAlertView進行額外的修改.
3.第一次嘗試, 看能否把SimpleAlertView顯示出來.
-
打開Main.storyboard, 在設計面板中往ViewController添加一個button, 把button的title改為Show AlertView, 之后打開輔助視圖為button關(guān)聯(lián)一個IBAction.
- 在showAlertView函數(shù)中添加以下的代碼段
//加載xib文件, 拿到自定義的SimpleAlertView, 設置大小和位置并添加到根視圖中
let alertView = NSBundle.mainBundle().loadNibNamed("SimpleAlertView", owner: nil, options: nil).first as! SimpleAlertView
alertView.frame.size = CGSize(width: 280, height: 130)
alertView.center = self.view.center
self.view.addSubview(alertView)
- 運行程序, 點擊Show AlertView按鈕, 可以看到alertView成功創(chuàng)建啦. 截屏效果圖...
貌似效果不是特別明顯, 沒關(guān)系, 接下來慢慢修飾!!
4.打開SimpleAlertView.xib文件, 再打開輔助視圖, 為label和button生成相應的outlei以及action.
import UIKit
class SimpleAlertView: UIView {
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var messageLabel: UILabel!
@IBOutlet weak var cancleButton: UIButton!
@IBOutlet weak var confirmButton: UIButton!
@IBAction func cancle(sender: UIButton) {
}
@IBAction func confirm(sender: UIButton) {
}
}
5.打開SimpleAlertView.swift代碼文件, 在這里可以對SimpleAlertView的外觀和行為進行控制.
- 在confirm IBAction的下方添加 awakeFromNib()函數(shù), 這個函數(shù)會在加載xib文件時調(diào)用, 可以在這時修改控件的外觀.
- awakeFromNib()函數(shù)中添加以下代碼
super.awakeFromNib()
//view的位置和大小
self.frame.size = CGSize(width: 280.0, height: 130.0)
self.center = CGPoint(x: UIScreen.mainScreen().bounds.midX, y: UIScreen.mainScreen().bounds.midY)
//view的陰影
self.layer.shadowColor = UIColor(white: 0, alpha: 1).CGColor
self.layer.shadowOffset = CGSize(width: 0, height: 5)
self.layer.shadowOpacity = 0.5
//view的邊框
self.layer.borderWidth = 0.3
self.layer.borderColor = UIColor(white: 0, alpha: 0.5).CGColor
//設置按鈕的圓角
cancleButton.layer.cornerRadius = 5
cancleButton.clipsToBounds = true
confirmButton.layer.cornerRadius = 5
confirmButton.clipsToBounds = true
- 回到ViewController.swift代碼文件中, 修改showAlertView, 將下面兩行代碼刪掉.然后打開Main.storyboard, 將ViewController的view的背景顏色修改為RGB(200, 200, 200)
alertView.frame.size = CGSize(width: 280, height: 130)
alertView.center = self.view.center
6.ok, 現(xiàn)在再一次運行程序, 發(fā)現(xiàn)效果比上一次好多了.
7.可不可以有更好的效果呢, 給它加點動畫吧.
改變SimpleAlertView的初始位置, 讓它一開始在屏幕之外.
self.center = CGPoint(x: UIScreen.mainScreen().bounds.midX, y: -self.frame.size.height)
接著在 awakeFromNib()函數(shù)中添加以下代碼段, 添加confirmButton.clipsToBounds = true這句代碼的下方.
//把view的透明度設為0, 逆時針旋轉(zhuǎn)45度
self.layer.opacity = 0
self.transform = CGAffineTransformMakeRotation(CGFloat(-M_PI_4))
//持續(xù)0.3秒的動畫, 實現(xiàn)漸變效果和旋轉(zhuǎn)效果
UIView.animateWithDuration(0.3, animations: { () -> Void in
self.center = CGPoint(x: UIScreen.mainScreen().bounds.midX, y: UIScreen.mainScreen().bounds.midY)
self.layer.opacity = 1
self.transform = CGAffineTransformMakeRotation(CGFloat(0))
}, completion: nil)
運行一遍就可以看到動畫效果了!!!!
重點部分, 對按鈕的點擊做出響應(用3種方式來實現(xiàn))
第一種方式-----閉包函數(shù)
8.awakeFromNib()函數(shù)的上方定義兩個私有變量, 它們的類型都是(() -> Void)?的閉包.它們分別用來對取消或者確定做出響應.
private var cancleHandler: (() -> Void)?
private var confirmHandler: (() -> Void)?
接著在awakeFromNib()函數(shù)的下方定義一個方法, 暴露給外界, 用來設置剛剛定義的私有變量.
func setActionHandler(actionType: String, handler: () -> Void) {
if actionType == "cancle" {
cancleHandler = handler
}else {
confirmHandler = handler
}
}
這里的actionType有兩種, cancle或者confirm. 根據(jù)第一個參數(shù)的值來設置不同的handler.
完成這一步之后, 在生成的IBAction中調(diào)用響應的handler.
@IBAction func cancle(sender: UIButton) {
UIView.animateWithDuration(0.3, animations: { () -> Void in
self.center = CGPoint(x: UIScreen.mainScreen().bounds.midX, y: UIScreen.mainScreen().bounds.maxY)
self.layer.opacity = 0
}) { (_) -> Void in
if self.cancleHandler == nil {
return
}
self.cancleHandler!()
}
}
@IBAction func confirm(sender: UIButton) {
UIView.animateWithDuration(0.3, animations: { () -> Void in
self.center = CGPoint(x: UIScreen.mainScreen().bounds.midX, y: UIScreen.mainScreen().bounds.maxY)
self.layer.opacity = 0
}) { (_) -> Void in
if self.confirmHandler == nil {
return
}
self.confirmHandler!()
}
}
這兩個IBAction都先把SimpleAlertView移到屏幕的下方, 在完成這個動畫之后就會執(zhí)行相應的handler.
到現(xiàn)在為止, SimpleAlertView.swift的完整代碼如下:
import UIKit
class SimpleAlertView: UIView {
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var messageLabel: UILabel!
@IBOutlet weak var cancleButton: UIButton!
@IBOutlet weak var confirmButton: UIButton!
private var cancleHandler: (() -> Void)?
private var confirmHandler: (() -> Void)?
override func awakeFromNib() {
super.awakeFromNib()
//view的位置和大小
self.frame.size = CGSize(width: 280.0, height: 130.0)
self.center = CGPoint(x: UIScreen.mainScreen().bounds.midX, y: -self.frame.size.height)
//view的陰影
self.layer.shadowColor = UIColor(white: 0, alpha: 1).CGColor
self.layer.shadowOffset = CGSize(width: 0, height: 5)
self.layer.shadowOpacity = 0.5
//view的邊框
self.layer.borderWidth = 0.3
self.layer.borderColor = UIColor(white: 0, alpha: 0.5).CGColor
//設置按鈕的圓角
cancleButton.layer.cornerRadius = 5
cancleButton.clipsToBounds = true
confirmButton.layer.cornerRadius = 5
confirmButton.clipsToBounds = true
//把view的透明度設為0, 逆時針旋轉(zhuǎn)45度
self.layer.opacity = 0
self.transform = CGAffineTransformMakeRotation(CGFloat(-M_PI_4))
//持續(xù)0.3秒的動畫, 實現(xiàn)漸變效果和旋轉(zhuǎn)效果
UIView.animateWithDuration(0.3, animations: { () -> Void in
self.center = CGPoint(x: UIScreen.mainScreen().bounds.midX, y: UIScreen.mainScreen().bounds.midY)
self.layer.opacity = 1
self.transform = CGAffineTransformMakeRotation(CGFloat(0))
}, completion: nil)
}
func setActionHandler(actionType: String, handler: () -> Void) {
if actionType == "cancle" {
cancleHandler = handler
}else {
confirmHandler = handler
}
}
@IBAction func cancle(sender: UIButton) {
UIView.animateWithDuration(0.3, animations: { () -> Void in
self.center = CGPoint(x: UIScreen.mainScreen().bounds.midX, y: UIScreen.mainScreen().bounds.maxY)
self.layer.opacity = 0
}) { (_) -> Void in
if self.cancleHandler == nil {
return
}
self.cancleHandler!()
}
}
@IBAction func confirm(sender: UIButton) {
UIView.animateWithDuration(0.3, animations: { () -> Void in
self.center = CGPoint(x: UIScreen.mainScreen().bounds.midX, y: UIScreen.mainScreen().bounds.maxY)
self.layer.opacity = 0
}) { (_) -> Void in
if self.confirmHandler == nil {
return
}
self.confirmHandler!()
}
}
}
接下來, 回到ViewController.swift代碼文件, 在showAlertView() IBAction中添加以下代碼, 來驗證閉包函數(shù)是否有備執(zhí)行到.
alertView.setActionHandler("cancle") { () -> Void in
print("test")
alertView.removeFromSuperview()
}
點擊cancle按鈕, 可以看到SimpleAlertView逐漸往屏幕下方淡出, 而且在控制打印出了test.
這里的handler閉包只是簡單把SimpleAlertView移除, 可以根據(jù)實際情況做更多的事.
第二種方式-----通知
9.首先注釋掉剛剛在showAlertView()添加的代碼, 以及在cancle(sender: UIButton), confirm(sender: UIButton)中的所有代碼.
然后在cancle(sender: UIButton)中添加下面這行代碼. 這行代碼的作用是發(fā)一個通知, 第一個參數(shù)是通知的名稱, 最后一個參數(shù)是附加信息.
NSNotificationCenter.defaultCenter().postNotificationName("buttonClick", object: nil, userInfo: ["actionType": "cancle"])
同樣在onfirm(sender: UIButton)中添加一行類似的代碼.
NSNotificationCenter.defaultCenter().postNotificationName("buttonClick", object: nil, userInfo: ["actionType": "confirm"])
回到ViewController.swift代碼文件, 在viewDidLoad()中添加一行代碼, 讓ViewController成為這個消息的接收者.
NSNotificationCenter.defaultCenter().addObserver(self, selector: "receiveNotification:", name: "buttonClick", object: nil)
在接收到通知之后就會調(diào)用receiveNotification()函數(shù), 可以在這個函數(shù)里面做出對應的響應. 這個函數(shù)現(xiàn)在實現(xiàn)如下:
func receiveNotification(notification: NSNotification) {
let alertView = self.view.viewWithTag(101) as! SimpleAlertView
let action = notification.userInfo!["actionType"] as! String
if action == "cancle" {
UIView.animateWithDuration(0.3, animations: { () -> Void in
alertView.center = CGPoint(x: UIScreen.mainScreen().bounds.midX, y: UIScreen.mainScreen().bounds.maxY)
alertView.layer.opacity = 0
}) { (_) -> Void in
alertView.removeFromSuperview()
}
}else {
alertView.removeFromSuperview()
}
}
為了讓這段代碼能夠執(zhí)行, 還要把alertView的tag設置為101. 在showAlertView(sender: UIButton)中添加這行代碼.
alertView.tag = 101
ok, 運行一次程序, 效果和第一種方式類似.
第三種方式-----代理
10.注釋掉viewDidLoad()中的那行接收通知的代碼.打開SimpleAlertView.swift代碼文件, 在import UIKit的下方定義一個協(xié)議.
@objc protocol SimpleAlertViewDelegate {
optional func simpleAlertView(actionType: String)
}
在awakeFromNib()函數(shù)的上方定義一個代理變量.
var delegate: SimpleAlertViewDelegate!
注釋掉cancle(sender: UIButton), confirm(sender: UIButton)中發(fā)送通知的代碼.
在cancle(sender: UIButton)中添加這行代碼.
delegate.simpleAlertView!("cancle")
在confirm(sender: UIButton)中添加響應的代碼.
delegate.simpleAlertView!("confirm")
回到ViwController.swift代碼文件, 讓ViewController實現(xiàn)SimpleAlertViewDelegate.
在ViewController的最下方的大括號之外, 添加以下代碼段.
extension ViewController: SimpleAlertViewDelegate {
func simpleAlertView(action: String) {
let alertView = self.view.viewWithTag(101) as! SimpleAlertView
if action == "cancle" {
UIView.animateWithDuration(0.3, animations: { () -> Void in
alertView.center = CGPoint(x: UIScreen.mainScreen().bounds.midX, y: UIScreen.mainScreen().bounds.maxY)
alertView.layer.opacity = 0
}) { (_) -> Void in
alertView.removeFromSuperview()
}
}else {
alertView.removeFromSuperview()
}
}
}
最后在showAlertView(sender: UIButton)中添加一行代碼, 讓ViewController成為SimpleAlertView的代理人.
alertView.delegate = self
到這里就完成這個demo了.
demo的地址SimpleAlertView