看板 KnucklesNote
作者 標題 [Xcode][Swift3] 使用 ContainerView 切換子頁面
時間 2017-04-04 Tue. 23:45:11
依照前一篇 [Xcode][Swift3] 使用 ScrollView 建立水平捲動選單 - KnucklesNote板 - Disp BBS
使用水平選單產生選取頁籤的效果
但下方只有一個 TableView,只能簡單的更換不同的資料來顯示
如果想在下方建立一個子頁面,可以切換成不同的 Controller 的話
要使用 Container View
在 storyboard 使用 Container View 載入預設的第一頁
刪掉原本的 TableView 元件,拉一個 Container View 進來
![[圖]](http://i.imgur.com/ZiIMpK4.png)
可以看到 Container View 旁邊會附帶一個相同大小的 View Controller
對 Container View 加上四個方向為0的 Constraints
![[圖]](http://i.imgur.com/f1uDodW.png)
接下來可以在附帶的 View Controller 中加上 TableView 元件
或是改成使用 Table View Controller
要改用 Table View Controller 的話
先刪掉附帶的 View Controller,拉一個 Table View Controller 進來
![[圖]](http://i.imgur.com/gU9Bdaw.png)
按著 Ctrl 將 Container View 拉至 Table View Controller
跳出的選單選擇「Embed」
![[圖]](http://i.imgur.com/nXlRyQR.png)
這樣即可將 Container View 改為附帶一個 Table View Controller
點一下連接的 Segue,在屬性檢視器輸入 Identifier 為「ContainerViewSegue」
之後在程式會用到
![[圖]](http://i.imgur.com/4Hk5zAt.png)
新增一個 Table View Controller 的程式檔
點 command+n 新增一個 Cocoa Touch Class
Class 名稱輸入「Page1ViewController」
Subclass of 「UITableViewController」
![[圖]](http://i.imgur.com/v4H4J9U.png)
新增好程式檔後,要到 storyboard 設定自訂類別為「Page1Viewcontroller」
然後在 Storyboard ID 輸入「Page1」,之後在程式會用到
![[圖]](http://i.imgur.com/dn5wvY5.png)
設定 Table View Cell 的 Identifier 為「TableViewCell」
![[圖]](http://i.imgur.com/6Kl2sDA.png)
有使用下拉更新的話,在 Table View Controller 的屬性檢視器
開啟並設定下拉更新的功能
![[圖]](http://i.imgur.com/g7hss8S.png)
編輯程式檔 Page1ViewController.swift
將原本寫在 ViewController.swift 中關於 TableView 的程式改寫在這裡
像這樣
class Page1ViewController: UITableViewController {
func loadData() {
print("load data")
if (self.refreshControl?.isRefreshing)! {
self.refreshControl?.endRefreshing()
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.refreshControl?.addTarget(self, action: #selector(loadData), for: UIControlEvents.valueChanged)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 20
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath)
cell.textLabel?.text = "測試標題 \(indexPath.row)"
return cell
}
注意 Table View Controller 已有內建 refreshControlfunc loadData() {
print("load data")
if (self.refreshControl?.isRefreshing)! {
self.refreshControl?.endRefreshing()
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.refreshControl?.addTarget(self, action: #selector(loadData), for: UIControlEvents.valueChanged)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 20
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath)
cell.textLabel?.text = "測試標題 \(indexPath.row)"
return cell
}
所以不用在成員變數新增,只要在 viewDidLoad() 設定要執行的函數即可
原本寫在 ViewController.swift 中關於 TableView 的程式就可以刪除了
執行看看
![[圖]](http://i.imgur.com/rirZ8Ao.png)
使用程式載入其他頁
在 storyboard 中,使用 Container View 只能內嵌一個 View Controller 而已
要切換為內嵌其他的 View Controller 的話只能用程式達成
假設其他四頁都只要使用簡單的 View Controller 就好
新增四個繼承 ViewController 的類別程式檔,檔名分別為
Page2ViewController.swift
Page3ViewController.swift
Page4ViewController.swift
Page5ViewController.swift
在 storyboard 拉四個 View Controller 進來
調整 Background 為不同的顏色以示區別
![[圖]](http://i.imgur.com/p0wvYm3.png)
此時會出現一個警告訊息,說這幾個 View Controller 沒有進入點
只要有設定 Storyboard ID 就可以消除這個警告
設定每頁的自訂類別,以及 Storyboard ID
例如第5頁的自訂類別為 Page5ViewController,Storyboard ID 為 Page5
![[圖]](http://i.imgur.com/9fnRw28.png)
再來要寫程式來切換要顯示的頁面
先使用 Assistant edior 新增 Contain View 的 @IBOutlet
名稱輸入「containerView」
![[圖]](http://i.imgur.com/8uDlMEj.png)
編輯程式檔 ViewController.swift
新增成員變數
// 1.
var page1ViewController: Page1ViewController!
// 2.
lazy var page2ViewController: Page2ViewController = {
self.storyboard!.instantiateViewController(withIdentifier: "Page2" as! Page2ViewController
}()
lazy var page3ViewController: Page3ViewController = {
self.storyboard!.instantiateViewController(withIdentifier: "Page3" as! Page3ViewController
}()
lazy var page4ViewController: Page4ViewController = {
self.storyboard!.instantiateViewController(withIdentifier: "Page4" as! Page4ViewController
}()
lazy var page5ViewController: Page5ViewController = {
self.storyboard!.instantiateViewController(withIdentifier: "Page5" as! Page5ViewController
}()
// 3.
var selectedViewController: UIViewController!
1. page1ViewController 因為有使用 Segue 連結了,後面會使用 prepare() 來取得var page1ViewController: Page1ViewController!
// 2.
lazy var page2ViewController: Page2ViewController = {
self.storyboard!.instantiateViewController(withIdentifier: "Page2" as! Page2ViewController
}()
lazy var page3ViewController: Page3ViewController = {
self.storyboard!.instantiateViewController(withIdentifier: "Page3" as! Page3ViewController
}()
lazy var page4ViewController: Page4ViewController = {
self.storyboard!.instantiateViewController(withIdentifier: "Page4" as! Page4ViewController
}()
lazy var page5ViewController: Page5ViewController = {
self.storyboard!.instantiateViewController(withIdentifier: "Page5" as! Page5ViewController
}()
// 3.
var selectedViewController: UIViewController!
2. 其他四頁使用 Storyboard ID 來取得頁面的 Controller,存為成員變數
前面加 lazy 代表變數第一次使用到的時候才會去取得初始值
後面接一個立即執行的匿名函數,因為內容只有一行所以可以不用加 return
3. 使用成員變數 selectedViewController 來記錄目前選取的是哪一頁
新增成員函數 prepare(for:sender:)
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "ContainerViewSegue" {
page1ViewController = segue.destination as! Page1ViewController
}
}
使用連結兩頁面的 Segue 來取得 page1ViewControllerif segue.identifier == "ContainerViewSegue" {
page1ViewController = segue.destination as! Page1ViewController
}
}
在 viewDidLoad() 裡加上
selectedViewController = page1ViewController
設定預設選取的是第一頁新增成員函數 changePage(to:)
// 1.
func changePage(to newViewController: UIViewController) {
// 2. Remove previous viewController
selectedViewController.willMove(toParentViewcontroller: nil)
selectedViewController.view.removeFromSuperview()
selectedViewController.removeFromParentViewController()
// 3. Add new viewController
addChildViewController(newViewController)
self.containerView.addSubview(newViewController.view)
newViewController.view.frame = containerView.bounds
newViewController.didMove(toParentViewController: self)
// 4.
self.selectedViewController = newViewController
}
1. 參數傳入新頁面的 Controller,會先移除 Container View 上附帶的舊 Controllerfunc changePage(to newViewController: UIViewController) {
// 2. Remove previous viewController
selectedViewController.willMove(toParentViewcontroller: nil)
selectedViewController.view.removeFromSuperview()
selectedViewController.removeFromParentViewController()
// 3. Add new viewController
addChildViewController(newViewController)
self.containerView.addSubview(newViewController.view)
newViewController.view.frame = containerView.bounds
newViewController.didMove(toParentViewController: self)
// 4.
self.selectedViewController = newViewController
}
再將新的 Controller 加到 Container View
2. 移除 Controller 前要先呼叫 willMove() 讓 Contrller 執行離開頁面的程式
然後使用 removeFromSuperview() 將 Controller 移出 Container View
最後使用 removeFromParentViewController 將 Contrller 移出主頁的 Controller
3. 先用 addChildViewController() 將新的 Controller 加進主頁的 Controller
接著將新的 Controller 加進 Container View
設定新 Controller 中頁面的尺寸為 Container View 的大小
呼叫 didMove() 讓新的 Controller 執行頁面載入的程式
4. 修改目前選取的頁面為新的 Controller
修改五個按鈕的 @IBAction 為
@IBAction func showPage1(_ sender: Any) {
changeTab(to: page1Button)
changePage(to: page1ViewController)
}
@IBAction func showPage2(_ sender: Any) {
changeTab(to: page2Button)
changePage(to: page2ViewController)
}
@IBAction func showPage3(_ sender: Any) {
changeTab(to: page3Button)
changePage(to: page3ViewController)
}
@IBAction func showPage4(_ sender: Any) {
changeTab(to: page4Button)
changePage(to: page4ViewController)
}
@IBAction func showPage5(_ sender: Any) {
changeTab(to: page5Button)
changePage(to: page5ViewController)
}
在每個按鈕點擊後執行 changePage(to:)changeTab(to: page1Button)
changePage(to: page1ViewController)
}
@IBAction func showPage2(_ sender: Any) {
changeTab(to: page2Button)
changePage(to: page2ViewController)
}
@IBAction func showPage3(_ sender: Any) {
changeTab(to: page3Button)
changePage(to: page3ViewController)
}
@IBAction func showPage4(_ sender: Any) {
changeTab(to: page4Button)
changePage(to: page4ViewController)
}
@IBAction func showPage5(_ sender: Any) {
changeTab(to: page5Button)
changePage(to: page5ViewController)
}
執行看看
![[圖]](http://i.imgur.com/sgeE6VR.png)
參考
Cocoacasts Managing View CodePathControllers With Container View Controllers
CodePath Container View Controllers Quickstart
--
※ 作者: Knuckles 時間: 2017-04-04 23:45:11
※ 編輯: Knuckles 時間: 2017-04-09 01:13:58
※ 看板: KnucklesNote 文章推薦值: 0 目前人氣: 0 累積人氣: 4851
回列表(←)
分享