uitableviewで複雑なレイアウトを作る方法
はじめに
今回作りたい画面はこんなかんじ。
スクロール前
スクロール後
webとかでもありがちなページです。
ページ上部にヘッダがあって、ページ下部にフッターがあって、間にリストみたいなのがある。
ちなみにヘッダーとフッターは固定ではありません
が、ずっとUIScrollViewを使ってやろうとしてたんですけど、なかなかうまくいかず、、、
どこかの記事でiPhoneアプリ開発はUITableViewを使ってナンボみたいなのを読んで記憶があって無理やりUITableViewで実現してみました。
実装
ViewController.swif
import UIKit class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { // テーブルビュー var tableView: UITableView! // テーブルデータ var tableData = [ "データ1", "データ2", "データ3", "データ4", "データ5", "データ6", "データ7", "データ8", "データ9", "データ10", ] override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. let displayWidth = self.view.frame.width let displayHeight = self.view.frame.height tableView = UITableView(frame: CGRect(x:0, y:0, width:displayWidth, height:displayHeight)) tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "Cell") tableView.registerClass(CustomTableViewFooterCell.self, forCellReuseIdentifier: "FooterCell") tableView.delegate = self tableView.dataSource = self self.view.addSubview(tableView) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } // 1セクション目のフッターをヘッダーとして使うためにダミーのセクションを返します func numberOfSectionsInTableView(tableView: UITableView) -> Int { return 2 } func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { if section == 0 { return 0 } else { return tableData.count + 1 // 行数+フッター数 } } // テーブルヘッダーの高さをかえします(フッターだけどヘッダーとして利用) func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { if section == 0 { let heightView = self.setHeaderView(tableView,isLayout: false) as! CGFloat return heightView } else { return 0 } } // テーブルヘッダーにViewをセットしてかえします(フッターだけどヘッダーとして利用) func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { if section == 0 { let viewHeader = self.setHeaderView(tableView, isLayout: true) as! UIView return viewHeader } else { return UIView() } } // Viewの追加とViewの高さを求めてかえします func setHeaderView(tableView: UITableView, isLayout: Bool) -> AnyObject { // View全体の高さ var heightView: CGFloat = 0 // ベースとなるView(高さは変わるので暫定) let viewHeader = UIView() viewHeader.frame = CGRectMake(0, 0, tableView.frame.width, 100) // ヘッダーラベル let myLabel = UILabel(frame: CGRectMake(0, 0, self.view.frame.width, 200)) myLabel.text = "ヘッダー" myLabel.font = UIFont.systemFontOfSize(22) myLabel.textAlignment = NSTextAlignment.Center myLabel.backgroundColor = UIColor.redColor() heightView += myLabel.frame.height if isLayout == true { viewHeader.addSubview(myLabel) return viewHeader } else { return heightView } } // テーブルセルの高さをかえします func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { // 1セクション目はダミー if indexPath.section == 0 { return 0 // 2セクション目が本来のデータ } else { if self.tableData.count > indexPath.row { return 44 } else { let cell = CustomTableViewFooterCell() var height = cell.setData(false) as! CGFloat return height } } } // テーブルセルにデータをセットします func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { // 1セクション目はダミー if indexPath.section == 0 { let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UITableViewCell return cell // 2セクション目が本来のデータ } else { if self.tableData.count > indexPath.row { let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UITableViewCell cell.textLabel?.text = self.tableData[indexPath.row] return cell } else { let cell = tableView.dequeueReusableCellWithIdentifier("FooterCell", forIndexPath: indexPath) as! CustomTableViewFooterCell cell.setData(true) return cell } } } }
CustomTableViewFooterCell.swift
class CustomTableViewFooterCell: UITableViewCell { var buttonShowMore = UIButton() override init(style: UITableViewCellStyle, reuseIdentifier: String!) { //First Call Super super.init(style: style, reuseIdentifier: reuseIdentifier) } required init(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } func setData(isLayout: Bool) -> AnyObject { // View全体の高さ var heightView: CGFloat = 1 var myLabel = UILabel(frame: CGRectMake(0, 0, self.frame.width, 200)) myLabel.text = "フッター" myLabel.backgroundColor = UIColor.blueColor() myLabel.font = UIFont.systemFontOfSize(22) myLabel.textAlignment = NSTextAlignment.Center heightView += myLabel.frame.height if isLayout == true { self.contentView.addSubview(myLabel) return true } else { return heightView } } }
ポイントとしては
1. UITableViewにはセクションごとにヘッダーとフッターが用意されているのですが、それのフッターをヘッダーとして使った
2. UITableViewCellのカスタムセルにViewをつくって突っ込めば色々複雑なデザインが作れる
とかでしょうか
1. をヘッダではなく、フッターを使って理由はヘッダーを使うとスクロールしても付いてきてしまって
調べるとやり方はいくつか出てきたんですけど、なんか理解できなくてフッターを使うという手段を使いました。
初心者ですので、こんな奇異なやり方なんですけど、
ちゃんとしたかたからしたら、そんなやり方やらなくても、、、とかあると思うのでアドバイスいただけると嬉しいです!
けど、テーブルビュー使うと直感的にわかりやすいですね
以上です