1. 程式人生 > >[Swift通天遁地]二、表格表單-(3)在表格中巢狀另一個表格並使Cell的高度自適應

[Swift通天遁地]二、表格表單-(3)在表格中巢狀另一個表格並使Cell的高度自適應

本文將演示如何在表格中巢狀另一個表格並使Cell的高度自適應,建立更加強大的佈局效果。

在專案資料夾【DemoApp】上點選滑鼠右鍵,彈出右鍵選單。

【New File】->【Cocoa Touch Class】->【Next】->

【Class】:CustomizeUITableViewCell ,類名。

【Subclass of】:UITableViewCell ,父類

【Language】:Swift

->【Next】->【Create】
在專案導航區,開啟剛剛建立的程式碼檔案【CustomizeUITableViewCell.swift】

現在開始編寫程式碼,建立一個自定義的單元格的類。

  1 import UIKit
  2 
  3 //引入需要遵循的表格檢視的相關協議UITableViewDataSource, UITableViewDelegate
  4 class CustomizeUITableViewCell: UITableViewCell, UITableViewDataSource, UITableViewDelegate {
  5     
  6     //新增兩個屬性:
  7     //1.表格物件
  8     var tableView : UITableView!;
  9     //2.資料來源
 10     var
comments : [String] = [] 11 12 //重寫單元格的初始化方法,在該方法中對單元格進行自定義操作 13 override init(style: UITableViewCellStyle, reuseIdentifier: String?) 14 { 15 //首先實現父類的初始化方法 16 super.init(style: style, reuseIdentifier: reuseIdentifier); 17 18 //初始化一個表格物件,並設定表格物件的顯示區域
19 tableView = UITableView(frame: CGRect(x: 20, y: 0, width: 280, height: 90)) 20 //設定表格物件的資料來源為當前的檢視控制器物件 21 tableView.dataSource = self 22 //設定表格物件的代理為當前的檢視控制器物件 23 tableView.delegate = self 24 //設定不允許內部表格的滾動, 25 //只允許單元格所屬表格可以進行滾動 26 tableView.isScrollEnabled = false; 27 28 //將表格檢視新增到根檢視中 29 self.addSubview(tableView) 30 } 31 32 //新增一個代理方法,用來設定表格的行數 33 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 34 { 35 //在此設定表格的行數,與陣列的長度保持一致 36 return comments.count 37 } 38 39 //新增一個代理方法,用來初始化或複用表格中的單元格 40 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 41 { 42 //建立一個字串常量,作為單元格的複用標識 43 let identifier = "reusedCell" 44 //根據複用標識,從表格中獲得可以複用的單元格 45 var cell = tableView.dequeueReusableCell(withIdentifier: identifier) 46 47 //如果沒有可以複用的單元格 48 if(cell == nil) 49 { 50 //則初始化一個預設樣式的單元格,並設定單元格的複用標識 51 cell = UITableViewCell(style: UITableViewCellStyle.default, 52 reuseIdentifier: identifier) 53 } 54 55 //從陣列中獲得指定序號的字串,作為單元格的標題文字。 56 cell?.textLabel?.text = comments[(indexPath as NSIndexPath).row] 57 //設定標題文字的字型大小為12 58 cell?.textLabel?.font = UIFont.systemFont(ofSize: 12) 59 //設定文字的顏色為灰色 60 cell?.textLabel?.textColor = UIColor.gray 61 //設定標籤可顯示多行文字 62 cell?.textLabel?.numberOfLines = 0; 63 64 return cell! 65 } 66 67 //建立一個類方法,用來根據字串的長度,計算單元格的高度 68 class func caculateCellHeight(comment:String)->CGFloat 69 { 70 //建立一個字型常量,和單元格的字型大小相同 71 let font = UIFont.systemFont(ofSize: 12) 72 //通過計算獲得文字的顯示區域 73 let size = comment.boundingRect(with: CGSize(), 74 options: .usesFontLeading, 75 attributes: [NSFontAttributeName:font], 76 context: nil); 77 78 //通過顯示區域的高度,減去文字至基線的距離,獲得文字的高度。 79 //將顯示區域的寬度,除以每行文字的寬度,獲得文字的行數,兩者相乘獲得總的高度。 80 return (size.height-2*size.origin.y)*(size.width/280.0) 81 } 82 83 //新增一個代理方法,用來設定單元格的高度 84 func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath)-> CGFloat 85 { 86 //根據單元格的序號,獲得該單元格將要顯示的字串 87 let subComments = comments[(indexPath as NSIndexPath).row] 88 //根據剛剛建立的類方法,計算單元格容納該字串所需的高度 89 let cellHeight = CustomizeUITableViewCell.caculateCellHeight(comment:subComments) 90 //然後進行臨界判斷,從而將高度數值保持在一個合理的範圍之內。 91 if(cellHeight < 30) 92 { 93 return 30 94 } 95 else 96 { 97 return cellHeight 98 } 99 } 100 101 //新增一個方法,用來設定表格的資料來源。該方法將在外部的表格中被呼叫。 102 func setCommentsForTable(_ comments:[String]) 103 { 104 //設定自定義單元格的陣列屬性,作為該單元格的表格的資料來源。 105 self.comments = comments 106 107 //計算單元格內部的表格的高度 108 //首先初始化一個浮點常量 109 var tableHeight:CGFloat = 0 110 //建立一個迴圈,遍歷表格的資料來源。 111 //通過對每個單元格的高度進行累計,合計整個表格的高度。 112 for i in 0 ..< comments.count 113 { 114 tableHeight += CustomizeUITableViewCell.caculateCellHeight(comment:comments[i]) 115 } 116 117 //重新繪製表格的顯示區域 118 tableView.frame = CGRect(x: 20, y: 0, width: 280, height: tableHeight + 20) 119 //並重新整理表格中的資料 120 tableView.reloadData() 121 } 122 123 //新增一個方法,用來獲得單元格內部表格的高度數值 124 func getMyHeight()->CGFloat 125 { 126 //用來獲得單元格內部表格的高度數值 127 return tableView.frame.size.height 128 } 129 130 //最後新增一個必須實現的初始化方法 131 required init(coder aDecoder: NSCoder) 132 { 133 fatalError("init(code:)has not brrn implomented"); 134 } 135 }

在專案導航區,開啟檢視控制器的程式碼檔案【ViewController.swift】

現在開始建立處於外部的表格檢視,並在表格中使用剛剛自定義的包含表格的單元格。

  1 import UIKit
  2 
  3 //使當前的檢視控制器類,遵循表格的資料來源協議UITableViewDataSource和代理協議UITableViewDelegate
  4 class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
  5     
  6     //建立一個數組,作為新聞的標題。
  7     var articles = ["SpaceX wants to launch 4,425 satellites", 
  8     "Free Workshop in Los Angeles, December 10!", 
  9     "Stephen Hawking just gave humanity a due date for finding another planet"]
 10     //建立另一個二維陣列,作為新聞的評論內容。
 11     var comments = [["1.Elon Musk's SpaceX wants to launch thousands of satellites into space with the aim of providing super-fast global internet coverage, according to a regulatory filing.","2.SpaceX – the company on a mission to colonize Mars – outlined plans to put 4,425 satellites into space in a Federal Communications Commission (FCC) filing from earlier this week.","3.Billionaire Musk – who is also the chief executive of electric car company Tesla – first announced plans for the project in 2015, with an estimated cost of $10 billion."],["1.Join us for a free Rich Dad Education financial workshop in Los Angeles.","2.All attendees are entered to win a tablet. Save your spot now!","3.Dream of working in Australia?"],["1.If humanity survives the rise of artificial intelligence, the ravages of climate change and the threat of nuclear terrorism in the next century, it doesn't mean we're home free, according to Stephen Hawking.","2.The renowned theoretical physicist has gone as far as providing humanity with a deadline for finding another planet to colonize: We have 1,000 years.","3.Remaining on Earth any longer, Hawking believes, places humanity at great risk of encountering another mass extinction."]]
 12     
 13     override func viewDidLoad() {
 14         super.viewDidLoad()
 15         // Do any additional setup after loading the view, typically from a nib.
 16         
 17         //獲得裝置的螢幕尺寸
 18         let screenRect = UIScreen.main.bounds
 19         //建立一個矩形區域,作為表格檢視的顯示區域
 20         let tableRect = CGRect(x: 0,
 21                                y: 20,
 22                                width: screenRect.size.width,
 23                                height: screenRect.size.height - 20)
 24         //初始化一個指定顯示區域的表格物件
 25         let tableView = UITableView(frame: tableRect)
 26         
 27         //設定表格物件的資料來源為當前的檢視控制器物件
 28         tableView.dataSource = self
 29         //設定表格物件的代理為當前的檢視控制器物件
 30         tableView.delegate = self
 31         
 32         //設定單元格的分隔線為空白
 33         tableView.separatorStyle = UITableViewCellSeparatorStyle.none
 34         //將表格檢視新增到根檢視中
 35         self.view.addSubview(tableView)
 36     }
 37     
 38     //新增一個代理方法,用來設定表格的行數
 39     func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
 40     {
 41         //在此設定表格的行數為新聞標題陣列長度的兩倍。
 42         //偶數行用來顯示標題,奇數行用來顯示評論
 43         return articles.count * 2
 44     }
 45     
 46     //新增一個代理方法,用來初始化或複用表格中的單元格
 47     func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath)-> UITableViewCell
 48     {
 49         //建立兩個字串常量,作為單元格的複用標識
 50         //1.用於顯示新聞標題的偶數行單元格
 51         let cellForArticle = "cellForArticle"
 52         //2.用於顯示新聞評論的奇數行的自定義單元格
 53         let cellForComments = "cellForComments"
 54         
 55         //建立兩個單元格物件
 56         //1.系統預設樣式的單元格
 57         var cell1:UITableViewCell?;
 58         //2.包含子表格的自定義單元格
 59         var cell2:CustomizeUITableViewCell?;
 60         
 61         //判斷偶數行
 62         if (indexPath as NSIndexPath).row % 2 == 0
 63         {
 64             //根據偶數行的複用標識,從表格中獲得可以複用的單元格
 65             cell1 = tableView.dequeueReusableCell(withIdentifier: cellForArticle)
 66             //如果沒有可以複用的單元格
 67             if cell1 == nil
 68             {
 69                 //則初始化一個預設樣式的單元格,並設定單元格的複用標識
 70                 cell1 = UITableViewCell(style: UITableViewCellStyle.default,
 71                                         reuseIdentifier: cellForArticle)
 72             }
 73             
 74             //設定單元格的標題文字為新聞的標題
 75             cell1?.textLabel?.text = articles[(indexPath as NSIndexPath).row/2]
 76             //設定標題文字的字型大小為14
 77             cell1?.textLabel?.font = UIFont.systemFont(ofSize: 14)
 78             //設定文字的顏色為白色
 79             cell1?.textLabel?.textColor = UIColor.white
 80             //設定單元格的背景顏色為橙色
 81             cell1?.backgroundColor = UIColor.orange
 82             
 83             //返回設定好的偶數行單元格
 84             return cell1!
 85         }
 86         else
 87         {
 88             //處理奇數行的單元格
 89              //根據奇數行的複用標識,從表格中獲得可以複用的單元格
 90             cell2 = tableView.dequeueReusableCell(withIdentifier: cellForComments) as? CustomizeUITableViewCell
 91             //如果沒有可以複用的單元格
 92             if cell2 == nil
 93             {
 94                 //則初始化一個預設樣式的單元格,並設定單元格的複用標識
 95                 cell2 = CustomizeUITableViewCell(style: UITableViewCellStyle.default,
 96                                                  reuseIdentifier: cellForComments)
 97             }
 98             
 99             //從陣列中獲得該單元格將要顯示的文字內容
100             let subComments = comments[(indexPath as NSIndexPath).row/2]
101             //然後呼叫自定義單元格物件的,設定子表格的資料來源的方法,
102             //在設定子表格資料來源的同時,也使子表格的高度做到自適應。
103             cell2?.setCommentsForTable(subComments)
104             
105             //返回奇數行的單元格
106             return cell2!
107         }
108     }
109     
110     //新增一個代理方法,用來設定單元格的高度
111     func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
112     {
113         //如果是偶數行的單元格,則設定高度為40
114         if (indexPath as NSIndexPath).row % 2 == 0
115         {
116             return 40
117         }
118         else
119         {
120             //處理奇數行單元格的情況
121             //獲得該單元格中的所有文字
122             let subComments = comments[(indexPath as NSIndexPath).row/2]
123             //初始化一個浮點數的變數,用來合計單元格的高度
124             var cellHeight:CGFloat = 0
125             //此處通過相同的方式
126             for i in 0 ..< subComments.count
127             {
128                 //通過累加的方式計運算元表格的高度
129                 cellHeight += CustomizeUITableViewCell.caculateCellHeight(comment: subComments[i])
130             }
131 
132             //最後返回該高度與20的和,避免單元格中的文字過於擁擠
133             return cellHeight + 20
134         }
135     }
136     
137     override func didReceiveMemoryWarning() {
138         super.didReceiveMemoryWarning()
139         // Dispose of any resources that can be recreated.
140     }
141 }