說明:在Xcode7 beta5 中制作完成
-
創(chuàng)建一個Single View Application,填寫相應(yīng)信息,選擇一個目錄存儲工程昧甘。
-
打開Main.storyboard,取消勾選Use Size Class,完成后設(shè)計視圖的大小將會呈現(xiàn)iphone大小
-
在storyboard中選中View Controller,單擊菜單欄上的Editor菜單,依次選擇Embed In和Navigation Controller拆魏。
完成后如下所示
-
選中Navigation Bar,改變它的Bar Tint(可以省略不做)
完成后的效果圖
-
導(dǎo)入要使用到的資源文件
單擊Assets.xcassets文件夾,把要使用到的菜單圖標(biāo)拖放到圖片資源框中咱娶。
完成后
-
拖放一個Bar Button Item到Navigation Bar上, 設(shè)置它的image屬性。
完成后的效果圖 -
從控件庫中拖一個TableView到View Controller中,選中TableView,把它的Prototype Cells的數(shù)量設(shè)置為1,接著改變TableView的位置和大小吨瞎。
-
展開TableView選中TableViewCell,設(shè)置它的identifier以及它的高度
-
再次選中TableView,給它增加約束株旷。單擊右下角的第3個按鈕塔次,給TableView增加如下約束(上邊距和左邊距為0)爷恳。這里把高度設(shè)置為544和寬度設(shè)置為80的原因是,每個菜單的大小為(80 x 80),導(dǎo)航欄的高度為64,一共有6個菜單,所以高度為544悯搔,寬度為80.
-
從控件庫中拖一個ImageView到TableViewCell中,改變它的位置大小。
給ImageView添加約束并給它設(shè)置一個tag
-
打開輔助視圖,會呈現(xiàn)storyboard和代碼編輯區(qū)
-
選中TableView按住ctrl鍵,鼠標(biāo)左鍵拖拽一個outlet到ViewController代碼文件中妒貌。
接下來添加代碼,一步一步實(shí)現(xiàn)側(cè)滑菜單的功能
在viewDidLoad()方法上添加一個數(shù)組,用來存儲菜單圖標(biāo)的名字铸豁。
let menuIcons = ["dribble-flat", "evernote-flat", "facebook-flat", "google-plus-flat", "pandora-flat", "phone-flat"]
讓ViewController遵循UITableView的兩個協(xié)議
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate
此時編譯器會報錯,因?yàn)檫€沒有實(shí)現(xiàn)必須的代理方法」嗍铮現(xiàn)在實(shí)現(xiàn)必須的代理方法。
//設(shè)置TableViewCell的高度
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 80
}
// 設(shè)置TableView的行數(shù)
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return menuIcons.count
}
// 配置每個TableViewCell
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// 1. 獲取到可重用的cell
let cell = tableView.dequeueReusableCellWithIdentifier("menuCell") as UITableViewCell!
// 2. 拿到imageView
let menuImageView = cell.viewWithTag(715) as! UIImageView
// 3. 設(shè)置imageView的圖片
menuImageView.image = UIImage(named: menuIcons[indexPath.row])
return cell
}
到此時為止节芥,代碼文件看起來應(yīng)該類似這樣在刺。
import UIKit
//3. 遵循TableView的兩個協(xié)議
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
// 1. 拖拽生成tableview的outlet
@IBOutlet weak var menuTableView: UITableView!
// 2.菜單圖標(biāo)名數(shù)組
let menuIcons = ["dribble-flat", "evernote-flat", "facebook-flat", "google-plus-flat", "pandora-flat", "phone-flat"]
override func viewDidLoad() {
super.viewDidLoad()
}
// 4. 實(shí)現(xiàn)代理方法
// 設(shè)置TableViewCell的高度
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 80
}
// 設(shè)置TableView的行數(shù)
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return menuIcons.count
}
// 配置每個TableViewCell
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// 1. 獲取到可重用的cell
let cell = tableView.dequeueReusableCellWithIdentifier("menuCell") as UITableViewCell!
// 2. 拿到imageView
let menuImageView = cell.viewWithTag(715) as! UIImageView
// 3. 設(shè)置imageView的圖片
menuImageView.image = UIImage(named: menuIcons[indexPath.row])
return cell
}
}
運(yùn)行一下,看有什么效果
哇!只有一個空的列表头镊。為什么會這樣呢??因?yàn)檫€沒有指定TableView的代理人是誰,那么TableView的代理就沒有人在執(zhí)行◎纪眨現(xiàn)在給TableView指定代理人,在viewDidLoad()方法中添加兩行代碼。
menuTableView.dataSource = self
menuTableView.delegate = self
這兩行代碼的作用是,把menuTableView的代理人指定為當(dāng)前的ViewController,那么當(dāng)前的ViewController就會執(zhí)行TableView的代理方法,為menuTableView提供數(shù)據(jù)以及對menuTableView的行為負(fù)責(zé)相艇。
OK,再次運(yùn)行,看下效果
還不錯,菜單圖標(biāo)已經(jīng)顯示出來了!!
接下來颖杏,先用觸發(fā)按鈕來控制菜單的出現(xiàn)與隱藏...
首先在viewDidLoad()方法的下方添加以下代碼,把菜單隱藏掉,這樣程序啟動完成后,就不會把菜單顯示出來
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
// 獲取到所有顯示的cell
let cells = menuTableView.visibleCells
// 把cell移動至可視區(qū)域外
for cell in cells {
cell.frame.origin = CGPoint(x: -80, y: cell.frame.origin.y)
}
}
在viewDidLoad()方法的上方添加一個菜單的狀態(tài)標(biāo)記,用來記錄菜單的顯示狀態(tài)
//一開始菜單的狀態(tài)為隱藏
var isShow = false
在最后一個花括號的上方,添加一個輔助函數(shù),用來更改菜單的位置和狀態(tài),達(dá)到顯示和隱藏的效果
func menuStateChange() {
let cells = menuTableView.visibleCells
//如果當(dāng)前菜單的狀態(tài)為隱藏,則讓每個菜單顯示出來
if isShow == false {
//改變每個cell的原點(diǎn)位置
for cell in cells {
cell.frame.origin = CGPoint(x: 0, y: cell.frame.origin.y)
}
}
else {
for cell in cells {
cell.frame.origin = CGPoint(x: -80, y: cell.frame.origin.y)
}
}
//改變菜單的顯示狀態(tài)
isShow = !isShow
}
接著在menuStateChange()的下方添加一個Action,這個Action將由導(dǎo)航欄上的按鈕觸發(fā)
// 觸發(fā)或關(guān)閉菜單
@IBAction func trigger(sender: AnyObject) {
menuStateChange()
}
回到Storyboard中,讓按鈕關(guān)聯(lián)這個Action. 選中Bar Button Item,按住ctrl鍵,鼠標(biāo)左鍵拖拽至View Controller,在彈出菜單中選擇trigger:
現(xiàn)在運(yùn)行一下程序,可以發(fā)現(xiàn)用按鈕控制菜單顯示狀態(tài)的目標(biāo)完成啦坛芽。留储。。
接下來用手指的滑動來控制菜單的顯示狀態(tài)
First. 在代碼文件中添加用手機(jī)滑動屏幕時會執(zhí)行的Action
// 實(shí)現(xiàn)滑動手勢,判斷滑動方向是否與當(dāng)前菜單狀態(tài)吻合
@IBAction func swipe(gesture: UISwipeGestureRecognizer) {
// 往左滑關(guān)掉菜單
if gesture.direction == UISwipeGestureRecognizerDirection.Left && isShow == true {
menuStateChange()
}
else if gesture.direction == UISwipeGestureRecognizerDirection.Right && isShow == false {
menuStateChange()
}
}
ok, 回到storyboard咙轩,增加兩個滑動手勢識別器.從控件庫中拖放一個Swipe Gesture Recognizer到View Controller中,讓View Controller的view能夠識別到滑動手勢.
選中Swipe Gesture Recognizer,按住ctrl鍵,鼠標(biāo)左鍵拖拽至View Controller,在彈出菜單中選擇swipe:,讓手勢識別器關(guān)聯(lián)到要執(zhí)行的Action
運(yùn)用相同的方法,再拖一個Swipe Gesture Recognizer到View Controller中,此時有一個地方要修改,因?yàn)榛瑒邮謩葑R別器的識別方向默認(rèn)為向右滑. 選中剛添加的手勢,修改它的識別方向. 同時將它與swipe Action關(guān)聯(lián)获讳。
運(yùn)行程序,看下效果. 左右滑動可以控制菜單的顯示狀態(tài),按鈕也工作正常,兩者沒有沖突。
為了讓菜單的隱藏與出現(xiàn)具有動態(tài)效果,現(xiàn)在給每一個菜單加一個動畫.
修改menuStateChange()函數(shù),添加動畫效果.
func menuStateChange() {
let cells = menuTableView.visibleCells
//一個單位的延遲時間
let diff = 0.05
if isShow == false {
for cell in cells {
cell.frame.origin = CGPoint(x: -80, y: cell.frame.origin.y)
}
// 給每個cell增加動畫
for i in 0..<cells.count {
let cell = cells[i]
//動畫效果
UIView.animateWithDuration(0.3, delay: Double(i+1) * diff,
options: UIViewAnimationOptions.CurveEaseIn,
animations: { () -> Void in
cell.frame.origin = CGPoint(x: 0, y: cell.frame.origin.y)
},
completion: nil)
}
}
else {
for i in (0..<cells.count).reverse() {
let cell = cells[i]
UIView.animateWithDuration(0.3, delay: Double(6 - i) * diff,
options: UIViewAnimationOptions.CurveEaseIn,
animations: { () -> Void in
cell.frame.origin = CGPoint(x: -80, y: cell.frame.origin.y)
},
completion: nil)
}
}
isShow = !isShow
}
解釋一下實(shí)現(xiàn)動畫效果的代碼
UIView.animateWithDuration(0.3, delay: Double(i+1) * diff,
options: UIViewAnimationOptions.CurveEaseIn,
animations: { () -> Void in
cell.frame.origin = CGPoint(x: 0, y: cell.frame.origin.y)
},
completion: nil)
第一個參數(shù)是每個Cell執(zhí)行動畫的時間,為0.3秒
第二個參數(shù)是動畫的延遲時間,因?yàn)橄M藛我粋€接一個的出現(xiàn)活喊,所以每個菜單都會比上一個菜單有一個單位時間的延遲
第三個參數(shù)是動畫按指定速率變化曲線執(zhí)行,這里的速率變化曲線為CurveEaseIn
第四個參數(shù)是要實(shí)現(xiàn)的動畫效果,這里改變每個cell的原點(diǎn)位置,控制它的顯示狀態(tài)
第五個參數(shù)是動畫結(jié)束后要執(zhí)行的事情,這里為nil,表明什么都不做.
ok,側(cè)滑菜單制作完了,運(yùn)行看下效果吧!!
出現(xiàn)時的效果