zoukankan      html  css  js  c++  java
  • [Swift通天遁地]二、表格表单-(7)电子邮件Mail:实现单元格左右滑动调出功能按钮

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
    ➤微信公众号:山青咏芝(shanqingyongzhi)
    ➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/
    ➤GitHub地址:https://github.com/strengthen/LeetCode
    ➤原文地址:https://www.cnblogs.com/strengthen/p/10189864.html 
    ➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
    ➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

    目录:[Swift]通天遁地Swift

    本文将演示对单元格进行扩展,当手指在单元格左右滑动时,弹出不同的功能菜单。

    Github项目:【MGSwipeTableCell】

    下载该项目的源代码。文件夹【demo】->文件夹【MailAppDemoSwift】->文件夹【MailAppDemoSwift】

    ->双击文件【MailAppDemoSwift。xcodeproj】打开示例工程。

    选择该项目中的几个文件,拖动到自己的开发项目中。按住【Shift】,选择

    【MGSwipeButton.h】

    【MGSwipeButton.m】

    【MGSwipeTableCell.h】

    【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
    unread" : "Mark as
    read"
    187     }
    188     
    189     
    190     override func viewDidLoad()
    191     {
    192         super.viewDidLoad()
    193         
    194         //初始化一个矩形区域,作为表格的显示区域
    195         let frame = CGRect(x: 0, y: 20,  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 }
  • 相关阅读:
    指针和引用作为函数参数传递
    cv::Mat.type()
    Matlab 双目标定工具箱
    invalid conversion from `const void*' to `void*'
    error: 'vector' is not a member of cv
    单例模式与静态成员
    RGBD SLAM V2 +Ubuntu 16.04+ROS KINETIC配置及运行
    EntityFrameworkCore + MySQL 主从复制应用读写分离
    Docker 搭建 MySQL8.0 主从复制环境
    Asp.Net Core 项目中使用 Serilog 输出日志到 Elasticsearch
  • 原文地址:https://www.cnblogs.com/strengthen/p/10189864.html
Copyright © 2011-2022 走看看