使用Xib制作簡單的AlertView

使用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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市旁赊,隨后出現(xiàn)的幾起案子尊剔,更是在濱河造成了極大的恐慌贴唇,老刑警劉巖驴一,帶你破解...
    沈念sama閱讀 223,126評論 6 520
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異局服,居然都是意外死亡磷仰,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,421評論 3 400
  • 文/潘曉璐 我一進店門颁井,熙熙樓的掌柜王于貴愁眉苦臉地迎上來厅贪,“玉大人,你說我怎么就攤上這事雅宾⊙蹋” “怎么了?”我有些...
    開封第一講書人閱讀 169,941評論 0 366
  • 文/不壞的土叔 我叫張陵眉抬,是天一觀的道長贯吓。 經(jīng)常有香客問我,道長蜀变,這世上最難降的妖魔是什么悄谐? 我笑而不...
    開封第一講書人閱讀 60,294評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮库北,結(jié)果婚禮上爬舰,老公的妹妹穿的比我還像新娘。我一直安慰自己寒瓦,他們只是感情好情屹,可當我...
    茶點故事閱讀 69,295評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著杂腰,像睡著了一般垃你。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上喂很,一...
    開封第一講書人閱讀 52,874評論 1 314
  • 那天惜颇,我揣著相機與錄音,去河邊找鬼恤筛。 笑死官还,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的毒坛。 我是一名探鬼主播望伦,決...
    沈念sama閱讀 41,285評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼林说,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了屯伞?” 一聲冷哼從身側(cè)響起腿箩,我...
    開封第一講書人閱讀 40,249評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎劣摇,沒想到半個月后珠移,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,760評論 1 321
  • 正文 獨居荒郊野嶺守林人離奇死亡末融,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,840評論 3 343
  • 正文 我和宋清朗相戀三年钧惧,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片勾习。...
    茶點故事閱讀 40,973評論 1 354
  • 序言:一個原本活蹦亂跳的男人離奇死亡浓瞪,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出巧婶,到底是詐尸還是另有隱情乾颁,我是刑警寧澤,帶...
    沈念sama閱讀 36,631評論 5 351
  • 正文 年R本政府宣布艺栈,位于F島的核電站英岭,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏湿右。R本人自食惡果不足惜诅妹,卻給世界環(huán)境...
    茶點故事閱讀 42,315評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望诅需。 院中可真熱鬧漾唉,春花似錦荧库、人聲如沸堰塌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,797評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽场刑。三九已至,卻和暖如春蚪战,著一層夾襖步出監(jiān)牢的瞬間牵现,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,926評論 1 275
  • 我被黑心中介騙來泰國打工邀桑, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留瞎疼,地道東北人。 一個月前我還...
    沈念sama閱讀 49,431評論 3 379
  • 正文 我出身青樓壁畸,卻偏偏與公主長得像贼急,于是被迫代替她去往敵國和親茅茂。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,982評論 2 361

推薦閱讀更多精彩內(nèi)容