★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公衆號:山青詠芝(shanqingyongzhi)
➤博客園地址:山青詠芝(https://www.cnblogs.com/strengthen/)
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:http://www.javashuo.com/article/p-yzxhaksq-kg.html
➤若是連接不是山青詠芝的博客園地址,則多是爬取做者的文章。
➤原文已修改更新!強烈建議點擊原文地址閱讀!支持做者!支持原創!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★html
目錄:[Swift]通天遁地Swiftgit
本文將演示對單元格進行擴展,當手指在單元格左右滑動時,彈出不一樣的功能菜單。github
Github項目:【MGSwipeTableCell】swift
下載該項目的源代碼。文件夾【demo】->文件夾【MailAppDemoSwift】->文件夾【MailAppDemoSwift】api
->雙擊文件【MailAppDemoSwift。xcodeproj】打開示例工程。數組
選擇該項目中的幾個文件,拖動到本身的開發項目中。按住【Shift】,選擇xcode
【MGSwipeButton.h】微信
【MGSwipeButton.m】app
【MGSwipeTableCell.h】ide
【MGSwipeTableCell.m】
按下【Command】,以選擇其餘不相鄰的文件。
【MailViewController.swift】
【MailTableCell.swift】
【ObjCBridgingHeader.h】
將上面選擇的7個文件拖動到本身的項目中。
->保持默認的設置選項,點擊【Finish】
接着對項目進行一些設置,以引入橋接文件。
點擊項目名稱【DemoApp】->【Buildings】->橋接文件配置區域【Object-C Bridging Header】
->在配置選項中雙擊,打開配置窗口。
->在配置窗口中,輸入剛剛導入的橋接文件的名稱:【DemoApp/ObjCBridgingHeader.h】
在項目導航區,打開視圖控制器的代碼文件【ViewController.swift】
如今開始編寫代碼,建立一個可經過左右滑動,來調出功能按鈕的表格。
1 import UIKit 2 3 //添加一個郵件數據類,這個類將用來表示表格中的數據 4 class MailData 5 { 6 //給類添加四個屬性: 7 //1.來源 8 var from: String! 9 //2.主題 10 var subject: String! 11 //3.內容 12 var message: String! 13 //4.日期 14 var date: String! 15 //添加兩個屬性 16 //1.郵件是否已被閱讀 17 var read = false 18 //2.郵件是否擁有標記 19 var flag = false 20 } 21 22 //建立一個別名,表示功能按鈕被點擊時所執行的方法的類型。 23 typealias MailActionCallback = (_ cancelled: Bool, _ deleted: Bool, _ actionIndex: Int) -> Void 24 25 //使當前的視圖控制器類,遵循: 26 //1.表格的數據源協議UITableViewDataSource 27 //2.表格視圖代理協議UITableViewDelegate 28 //3.滑動表格單元格代理協議 29 //4.動做表單協議 30 class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, MGSwipeTableCellDelegate, UIActionSheetDelegate 31 { 32 //添加一個表格視圖類型的變量,做爲當前類的一個屬性 33 var tableView: UITableView! 34 //建立一個郵件數據類型的數組,做爲表格的數據源 35 var demoData = [MailData]() 36 //使用剛剛建立的別名,建立一個動做類型 37 var actionCallback: MailActionCallback? 38 39 //添加一個方法,用來設置表格的數據源 40 func prepareDemoData() 41 { 42 //建立第一個字符串數組常量,做爲郵件的來源 43 var from = [ 44 "Vincent", 45 "Mr Glass", 46 "Marsellus", 47 "Ringo", 48 "Sullivan" 49 ] 50 51 //建立第二個字符串數組常量,做爲郵件的主題 52 var subjects = [ 53 "You think water moves fast?", 54 "They called me Mr Glass", 55 "The path of the righteous man", 56 "Do you see any Teletubbies in here?", 57 "Now that we know who you are" 58 ] 59 60 //建立第三個字符串數組常量,做爲郵件的信息 61 var messages = [ 62 "You should see ice. It moves like it has a mind. ", 63 "And I will strike down upon thee with great vengeance and furious anger.", 64 "Look, just because I don't be givin' no man a foot massage don't make it right.", 65 "No? Well, that's what you see at a toy store.", 66 "In a comic, you know how you can tell who the arch-villain's going to be?" 67 ] 68 69 //經過一個循環,遍歷信息數組 70 for i in 0 ..< messages.count 71 { 72 //建立一個郵件數據對象 73 let mail = MailData() 74 //從數組中加載相應的內容 75 mail.from = from[i] 76 //並依次設置郵件數據對象的各個屬性 77 mail.subject = subjects[i] 78 mail.message = messages[i] 79 //設置郵件數據對象的時間屬性 80 mail.date = String(format: "11:%d", arguments: [43 - i]) 81 //將郵件數據對象,添加到表格的數據源數組當中 82 demoData.append(mail) 83 } 84 } 85 86 //添加一個方法 87 //用來從數據源數組中,根據單元格的位置得到相應的數據 88 func mailForIndexPath(_ path: IndexPath) -> MailData 89 { 90 //根據單元格的行號,返回數據源數組中的數據 91 return demoData[(path as NSIndexPath).row] 92 } 93 94 //添加一個方法 95 //用來響應單元格中的刪除按鈕被點擊時的事件 96 func deleteMail(_ path:IndexPath) 97 { 98 //從數據源數組中刪除指定位置的數據 99 demoData.remove(at: (path as NSIndexPath).row) 100 //從表格中刪除指定的單元格 101 tableView.deleteRows(at: [path], with: .left) 102 } 103 104 //添加一個方法 105 //當郵件的狀態改變時調用此方法 106 //例如郵件從未讀轉換爲已讀 107 func updateCellIndicator(_ mail: MailData, cell: MailTableCell) 108 { 109 //建立兩個顏色變量,做爲標識郵件狀態的圖標的顏色 110 var color: UIColor 111 var innerColor : UIColor? 112 113 //根據郵件不一樣的狀態,設置郵件不一樣的顏色 114 if !mail.read && mail.flag 115 { 116 //當郵件未讀並有標識時 117 //設置標識圖標的標識顏色 118 color = UIColor.init(red: 1.0, green: 149/255.0, blue: 0.05, alpha: 1.0) 119 //設置標識圖標內部的顏色 120 innerColor = UIColor.init(red: 0.0, green: 122/255.0, blue: 1.0, alpha: 1.0) 121 } 122 else if mail.flag 123 { 124 //當郵件具備標識時, 125 //設置標識圖標的標識顏色 126 color = UIColor.init(red: 1.0, green: 149/255.0, blue: 0.05, alpha: 1.0) 127 } 128 else if mail.read 129 { 130 //當郵件處於已讀狀態時, 131 //設置標識圖標的顏色爲無色 132 //即在視覺上隱藏該圖標 133 color = UIColor.clear 134 } 135 else 136 { 137 //設置郵件在其餘狀態下的默認顏色 138 color = UIColor.init(red: 0.0, green: 122/255.0, blue: 1.0, alpha: 1.0) 139 } 140 141 //設置標識圖標的顏色 142 cell.indicatorView.indicatorColor = color 143 //設置標識圖標內部的顏色 144 cell.indicatorView.innerColor = innerColor 145 } 146 147 //添加一個方法,用來彈出一個動做表單 148 func showMailActions(_ mail: MailData, callback: @escaping MailActionCallback) 149 { 150 //設置動做屬性的值 151 actionCallback = callback 152 153 //初始化一個動做表單,依次設置相關參數 154 let sheet = UIActionSheet.init(title: "Actions", //標題 155 delegate: self,//代理 156 cancelButtonTitle: "Cancel",//取消按鈕的標題 157 destructiveButtonTitle: "Trash")//銷燬按鈕的標題 158 159 //往動做表單中依次添加三個按鈕, 160 //並設置三個按鈕的標題文字 161 sheet.addButton(withTitle: "Mark as unread") 162 sheet.addButton(withTitle: "Mark as read") 163 sheet.addButton(withTitle: "Flag") 164 165 //在根視圖中顯示動做表單 166 sheet.show(in: self.view) 167 } 168 169 //添加一個代理方法,用來監聽動做表單中的選項被點擊時的事件 170 func actionSheet(_ actionSheet: UIActionSheet, clickedButtonAt index: Int) 171 { 172 //得到當前類的屬性的值 173 if let action = actionCallback 174 { 175 //根據點擊的不一樣選項,執行不一樣的操做 176 action(index == actionSheet.cancelButtonIndex, 177 index == actionSheet.destructiveButtonIndex, 178 index) 179 actionCallback = nil 180 } 181 } 182 183 //添加一個方法,用來根據不一樣的標識狀態,返回不一樣的文字內容 184 func readButtonText(_ read:Bool) -> String 185 { 186 return read ? "Mark as\nunread" : "Mark as\nread" 187 } 188 189 190 override func viewDidLoad() 191 { 192 super.viewDidLoad() 193 194 //初始化一個矩形區域,做爲表格的顯示區域 195 let frame = CGRect(x: 0, y: 20, width: 320, height: 548) 196 //建立一個指定顯示區域的表格視圖 197 tableView = UITableView(frame: frame, style: UITableViewStyle.plain) 198 199 //設置表格對象的數據源爲當前的視圖控制器對象 200 tableView.delegate = self 201 //設置表格對象的代理爲當前的視圖控制器對象 202 tableView.dataSource = self 203 //將表格視圖添加到根視圖中 204 view.addSubview(tableView) 205 206 //調用方法,用來初始化表格的數據源 207 prepareDemoData() 208 } 209 210 //添加一個代理方法,用來設置表格的行數 211 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 212 { 213 //在此設置表格的行數爲數組的長度 214 return demoData.count 215 } 216 217 //添加一個代理方法,用來初始化或複用表格中的單元格 218 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 219 { 220 //建立一個字符串常量,做爲單元格的複用標識 221 let identifier = "MailCell" 222 //根據複用標識,從表格中得到能夠複用的單元格 223 var cell: MailTableCell! = tableView.dequeueReusableCell(withIdentifier: identifier) as? MailTableCell 224 225 //若是沒有能夠複用的單元格 226 if cell == nil 227 { 228 //則初始化一個默認樣式的單元格,並設置單元格的複用標識 229 cell = MailTableCell(style: UITableViewCellStyle.default, reuseIdentifier: identifier) 230 } 231 //設置單元格的代理對象爲當前的視圖控制器對象 232 cell.delegate = self 233 234 //根據當前單元格的行號,得到數組中對應的郵件數據 235 let data: MailData = demoData[(indexPath as NSIndexPath).row] 236 //設置單元格的郵件來源標籤的文字內容 237 cell!.mailFrom.text = data.from 238 //依次設置其餘標籤的相關內容 239 cell!.mailSubject.text = data.subject 240 cell!.mailMessage.text = data.message 241 cell!.mailTime.text = data.date 242 243 //調用方法,根據郵件的狀態,刷新單元格的視覺效果 244 updateCellIndicator(data, cell: cell) 245 246 //最後返回設置好的單元格對象 247 return cell 248 } 249 250 //添加一個代理方法,用來設置單元格的高度爲110 251 func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat 252 { 253 return 110 254 } 255 256 //添加一個代理方法,設置單元格容許滑動的手勢 257 func swipeTableCell(_ cell: MGSwipeTableCell, canSwipe direction: MGSwipeDirection) -> Bool 258 { 259 return true 260 } 261 262 //添加一個代理方法,設置當單元格上有滑動手勢時,所顯示的功能按鈕,以及功能按鈕顯示的視覺效果 263 func swipeTableCell(_ cell: MGSwipeTableCell, swipeButtonsFor direction: MGSwipeDirection, swipeSettings: MGSwipeSettings, expansionSettings: MGSwipeExpansionSettings) -> [UIView]? 264 { 265 //設置功能按鈕的顯示方式爲三維旋轉效果。 266 //共有:邊緣、靜態、拖動、中心裁切、三維旋轉等五種效果 267 swipeSettings.transition = MGSwipeTransition.rotate3D 268 //設置功能按鈕的索引爲0 269 expansionSettings.buttonIndex = 0 270 271 //得到在當前單元格中,須要顯示的郵件內容 272 let mail = mailForIndexPath(tableView.indexPath(for: cell)!) 273 274 //處理當手勢爲從左到右滑動時的狀況 275 if direction == MGSwipeDirection.leftToRight 276 { 277 //設置在該手勢下,按鈕將以彈性的方式返回原來的位置 278 expansionSettings.fillOnTrigger = false 279 //設置觸發顯示功能按鈕的閾值大小,默認值爲1.5 280 expansionSettings.threshold = 2 281 //初始化一個顏色常量,做爲功能按鈕的背景顏色 282 let color = UIColor.init(red:0.0, green:122/255.0, blue:1.0, alpha:1.0) 283 284 //返回一個功能按鈕,並設置按鈕的標題、背景顏色和交互動做 285 return [ 286 MGSwipeButton(title: readButtonText(mail.read),//標題 287 backgroundColor: color,//背景顏色 288 callback: { (cell) -> Bool in//交互動做 289 //當該按鈕被點擊時,將切換當前郵件的閱讀狀態 290 mail.read = !mail.read 291 //同時刷新當前郵件所在單元格的外觀狀態 292 self.updateCellIndicator(mail, cell: cell as! MailTableCell) 293 //接着刷新單元格的內容視圖 294 cell.refreshContentView() 295 //根據郵件的閱讀狀態的變化,刷新被添加按鈕的標題文字 296 (cell.leftButtons[0] as! UIButton).setTitle(self.readButtonText(mail.read), for: UIControlState()) 297 298 //最後返回真,使功能按鈕自動隱藏,結束按鈕的點擊事件 299 return true 300 }) 301 ] 302 } 303 else 304 { 305 //處理當手勢爲從右到左滑動時的狀況 306 307 //設置在該手勢下,按鈕將在觸發時填充單元格 308 expansionSettings.fillOnTrigger = true 309 //設置觸發顯示功能按鈕的閾值大小1.1,默認值爲1.5 310 expansionSettings.threshold = 1.1 311 312 //設置按鈕的內邊距爲15 313 let padding = 15 314 //初始化三個顏色常量,做爲三個按鈕的背景顏色 315 let color1 = UIColor.init(red:1.0, green:59/255.0, blue:50/255.0, alpha:1.0) 316 let color2 = UIColor.init(red:1.0, green:149/255.0, blue:0.05, alpha:1.0) 317 let color3 = UIColor.init(red:200/255.0, green:200/255.0, blue:205/255.0, alpha:1.0) 318 319 //添加第一個功能按鈕,依次設置相關參數 320 let trash = MGSwipeButton(title: "Trash",//標題 321 backgroundColor: color1, //背景顏色 322 padding: padding, //內間距 323 callback: { (cell) -> Bool in//交互動做 324 //當該按鈕被點擊時, 325 //將從表格中移除按鈕所在的單元格, 326 //並在數組中移除該單元格的內容。 327 self.deleteMail(self.tableView.indexPath(for: cell)!) 328 return false 329 }) 330 331 //添加第二個功能按鈕,依次設置相關參數 332 let flag = MGSwipeButton(title: "Flag",//標題 333 backgroundColor: color2,//背景顏色 334 padding: padding, //內間距 335 callback: { (cell) -> Bool in//交互動做 336 //得到在當前單元格中,須要顯示的郵件內容 337 let mail = self.mailForIndexPath(self.tableView.indexPath(for: cell)!) 338 //更改郵件的標識狀態 339 mail.flag = !mail.flag 340 //刷新當前郵件所在單元格的外觀狀態 341 self.updateCellIndicator(mail, cell: cell as! MailTableCell) 342 //刷新單元格的內容視圖 343 cell.refreshContentView() 344 345 return true 346 }) 347 348 //添加第三個功能按鈕,依次設置相關參數 349 let more = MGSwipeButton(title: "More", //標題 350 backgroundColor: color3,//背景顏色 351 padding: padding, //內間距 352 callback: { (cell) -> Bool in//交互動做 353 //得到當前單元格在表格中的位置 354 let path = self.tableView.indexPath(for: cell)! 355 //得到在當前單元格中,須要顯示的郵件內容 356 let mail = self.mailForIndexPath(path) 357 358 //建立一個動做表單,擁有:取消、刪除和索引三個選項 359 self.showMailActions(mail, callback: { (cancelled, deleted, index) in 360 //取消選項被點擊時的狀況 361 if cancelled 362 { 363 return 364 } 365 //刪除選項被點擊時的狀況 366 else if deleted 367 { 368 //此時刪除當前的單元格,以及數組中的數據 369 self.deleteMail(path) 370 } 371 //索引選項被點擊時的狀況,當索引值爲1時 372 else if index == 1 373 { 374 //更改郵件的閱讀狀態 375 mail.read = !mail.read 376 //根據更改後的閱讀狀態,刷新當前單元格的標識圖標 377 self.updateCellIndicator(mail, cell: cell as! MailTableCell) 378 //同時刷新單元格的內容視圖 379 cell.refreshContentView() 380 //根據郵件的閱讀狀態的變化,刷新被添加按鈕的標題文字 381 (cell.leftButtons[0] as! UIButton).setTitle(self.readButtonText(mail.read), for: UIControlState()) 382 //而後以動畫的方式,隱藏功能按鈕 383 cell.hideSwipe(animated: true) 384 } 385 }) 386 //最後返回假,以保持功能按鈕的顯示狀態 387 return false 388 }) 389 //在方法的末尾,返回三個功能按鈕 390 return [trash, flag, more] 391 } 392 } 393 394 override func didReceiveMemoryWarning() { 395 super.didReceiveMemoryWarning() 396 // Dispose of any resources that can be recreated. 397 } 398 }