[Swift通天遁地]2、表格表單-(7)電子郵件Mail:實現單元格左右滑動調出功能按鈕

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公衆號:山青詠芝(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 }
相關文章
相關標籤/搜索