說(shuō)明:示例在XCode7 beta5完成
創(chuàng)建一個(gè)Single View Application,填寫(xiě)相應(yīng)的信息. Language選擇Swift,把項(xiàng)目存儲(chǔ)到一個(gè)目錄,單擊Create完成創(chuàng)建.
Storyboard設(shè)計(jì)階段
-
打開(kāi)Main.storyboard文件,取消勾選Use Size Classes,讓設(shè)計(jì)視圖呈現(xiàn)iphone的大小.
下面是取消勾選后,設(shè)計(jì)面板的樣子.
現(xiàn)在開(kāi)始在storyboard中添加要使用到的控件.
從控件庫(kù)中拖出一個(gè)Segmented Control到設(shè)計(jì)面板的上方.
選中Segmented Control,給它增加如下約束.
接下來(lái)拖一個(gè)ScrollView到到設(shè)計(jì)面板中,讓它鋪滿剩余的空間.
同樣也要給ScrollView增加約束,這樣才可以適應(yīng)不同屏幕的大小.
接著拖一個(gè)TableView到設(shè)計(jì)面板中,放置在ScrollView上,成為ScrollView的子視圖.
調(diào)整它的大小,讓它的大小和ScrollView的相同.
現(xiàn)在給TableView加上約束.
此時(shí)設(shè)計(jì)面板中多了一些紅色的線條,這說(shuō)明缺少約束或者約束有沖突.
通過(guò)以下步驟來(lái)增加約束,這樣storyboard就有足夠的信息來(lái)確定控件的位置關(guān)系.點(diǎn)擊Document Outline左上方的紅色小圓圈,在點(diǎn)擊空心的紅色小圓圈,在彈出框中選擇Add Missing Constraints.
接著個(gè)體TableView增加一個(gè)Prototype Cell.
然后展開(kāi)TableView選中Table View Cell,給它設(shè)置一個(gè)重用ID.
為了區(qū)分接下來(lái)要添加的TableView,選中當(dāng)前的TableView,給它設(shè)置一個(gè)tag,這里設(shè)置為101,再給它取一個(gè)名字.
接下來(lái)添加第二個(gè)TableView,為了方便操作,在控件庫(kù)中直接把TableView拖放至Document Outline中,讓它位于ScrollView的下方,成為ScrollView的子視圖.
使用相同的方式給剛剛添加的TableView設(shè)置一個(gè)tag,這里設(shè)置為102,給它取一個(gè)名字,叫做SecondTableView.再給SecondTableView增加一個(gè)Prototype Cell,并設(shè)置它的reused identifier為second.
接下來(lái)這一步比較關(guān)鍵,要改變SecondTableView的位置,這樣才能給SecondTableView添加上正確的約束.把SecondTableView的x坐標(biāo)設(shè)置為320,完成后,會(huì)把SecondTableView移動(dòng)到設(shè)計(jì)面板之外,如下所示.
現(xiàn)在選中SecondTableView為它增加約束.
此時(shí)又出現(xiàn)了紅色的線條.沒(méi)關(guān)系,有這個(gè)方法讓紅色線條消失.選中FirstTableView,按住ctrl鍵,鼠標(biāo)左鍵從FirstTableView拖出一條箭頭到SecondTableView,松開(kāi)鼠標(biāo)在彈出菜單中選擇Equal Widths.這樣做的結(jié)果是,兩個(gè)TableView具有相同的寬度.
ok,到此為止,storyboard的設(shè)計(jì)工作完成,接下來(lái)進(jìn)入代碼階段.
代碼階段
打開(kāi)輔助視圖,為設(shè)計(jì)面板中的控件生成相應(yīng)的outlet.同時(shí)為Segmented Control綁定一個(gè)Action,它的事件類型為Value Changed,可以把Segmented Control上的items當(dāng)作獨(dú)立的button來(lái)使用.
完成后,代碼文件會(huì)類似于這樣.
import UIKit
class ViewController: UIViewController {
// 1. 拖拽生成控件的outlet
@IBOutlet weak var segmented: UISegmentedControl!
@IBOutlet weak var scrollView: UIScrollView!
@IBOutlet weak var firstTableView: UITableView!
@IBOutlet weak var secondTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
}
// 2. 當(dāng)Segmented Control選擇的item改變時(shí),會(huì)觸發(fā)這個(gè)Action
@IBAction func tabChanged(sender: AnyObject) {
}
}
為了不讓Segmented Control給狀態(tài)欄遮擋,在viewDidLoad()函數(shù)的下方,添加以下代碼,把狀態(tài)欄隱藏掉.
// 3. 隱藏狀態(tài)欄
override func prefersStatusBarHidden() -> Bool {
return true
}
讓當(dāng)前ViewController遵循UITableViewDataSource協(xié)議,這樣就能夠給TableView提供數(shù)據(jù).類定義的頭部將會(huì)是下面的樣子.
class ViewController: UIViewController, UITableViewDataSource
這里為什么不讓ViewController遵循UITableViewDelegate協(xié)議呢.因?yàn)檫@個(gè)例子只是給TableView填充數(shù)據(jù),并不處理發(fā)生在TableView上的行為事件.
接著實(shí)現(xiàn)兩個(gè)代理方法,為T(mén)ableView填充數(shù)據(jù).把這兩個(gè)方法添加在prefersStatusBarHidden()函數(shù)的下方.
// 4. 為T(mén)ableView填充數(shù)據(jù)
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 20
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var reusedID: String!
if tableView.tag == 101 {
reusedID = "first"
}
else {
reusedID = "second"
}
let cell = tableView.dequeueReusableCellWithIdentifier(reusedID) as UITableViewCell!
if tableView.tag == 101 {
cell.textLabel!.text = "第一個(gè)TableView"
}
else {
cell.textLabel!.text = "第二個(gè)TableView"
}
return cell
}
這里利用tag來(lái)判斷是哪一個(gè)TableView,然后使用設(shè)置好的reused identifier來(lái)獲取到cell,給cell的textLabel設(shè)置簡(jiǎn)單的字符串.
在viewDidLoad()函數(shù)中,添加以下兩行代碼.這樣TableView的代理方法將會(huì)由當(dāng)前的ViewController來(lái)執(zhí)行.
firstTableView.dataSource = self
secondTableView.dataSource = self
選擇一個(gè)模擬器,運(yùn)行一下看有什么效果.
第一個(gè)TableView已經(jīng)呈現(xiàn)出來(lái)了,試著往左滑動(dòng),把第二個(gè)TableView呈現(xiàn)出來(lái).滑了幾次,發(fā)現(xiàn)不能將SecondTableView呈現(xiàn)出來(lái),為什么會(huì)這樣呢??難道SecondTableView沒(méi)有添加到ScrollView中.利用前面添加的Action來(lái)做個(gè)實(shí)驗(yàn),看是否把SecondTableView添加到了ScrollView中.
首先viewDidLoad()函數(shù)的上方,定義一個(gè)變量,用來(lái)記錄ScrollView的內(nèi)容偏移量.
// 5. 定義一個(gè)變量來(lái)記錄scrollview的內(nèi)容偏移量
var offset: CGFloat = 0.0 {
// 當(dāng)offset的值改變后會(huì)執(zhí)行didSet代碼塊
didSet {
UIView.animateWithDuration(0.3) { () -> Void in
self.scrollView.contentOffset = CGPoint(x: self.offset, y: 0.0)
}
}
}
didSet代碼塊的作用是,用一個(gè)0.3秒的過(guò)度來(lái)設(shè)置ScrollView的內(nèi)容偏移量.
接著在 tabChanged(sender: AnyObject) Action中添加以下代碼.
// a. 獲取到當(dāng)前item的下標(biāo)
let index = (sender as! UISegmentedControl).selectedSegmentIndex
// b. 設(shè)置scrollview的內(nèi)容偏移量
offset = CGFloat(index) * self.view.frame.width
item的下標(biāo)從0開(kāi)始.因?yàn)門(mén)ableView的寬度和屏幕的寬度相同,所以呈現(xiàn)FirstTableView時(shí)ScrollView的內(nèi)容偏移量為0,呈現(xiàn)SecondTableView時(shí)ScrollView的內(nèi)容偏移量為一個(gè)屏幕的寬度,即(self.view.frame.width).
再運(yùn)行一遍程序,當(dāng)點(diǎn)擊Second item時(shí),可以把SecondTableView呈現(xiàn)出來(lái),說(shuō)明有把SecondTableView加到ScrollView中.
到這個(gè)階段的完整代碼如下.
import UIKit
class ViewController: UIViewController, UITableViewDataSource {
// 1. 拖拽生成控件的outlet
@IBOutlet weak var segmented: UISegmentedControl!
@IBOutlet weak var scrollView: UIScrollView!
@IBOutlet weak var firstTableView: UITableView!
@IBOutlet weak var secondTableView: UITableView!
// 5. 定義一個(gè)變量來(lái)記錄scrollview的內(nèi)容偏移量
var offset: CGFloat = 0.0 {
// 當(dāng)offset的值改變后會(huì)執(zhí)行didSet代碼塊
didSet {
UIView.animateWithDuration(0.3) { () -> Void in
self.scrollView.contentOffset = CGPoint(x: self.offset, y: 0.0)
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
firstTableView.dataSource = self
secondTableView.dataSource = self
}
// 2. 當(dāng)Segmented Control選擇的item改變時(shí),會(huì)觸發(fā)這個(gè)Action
@IBAction func tabChanged(sender: AnyObject) {
// a. 獲取到當(dāng)前item的下標(biāo)
let index = (sender as! UISegmentedControl).selectedSegmentIndex
// b. 設(shè)置scrollview的內(nèi)容偏移量
offset = CGFloat(index) * self.view.frame.width
}
// 3. 隱藏狀態(tài)欄
override func prefersStatusBarHidden() -> Bool {
return true
}
// 4. 為T(mén)ableView填充數(shù)據(jù)
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 20
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var reusedID: String!
if tableView.tag == 101 {
reusedID = "first"
}
else {
reusedID = "second"
}
let cell = tableView.dequeueReusableCellWithIdentifier(reusedID) as UITableViewCell!
if tableView.tag == 101 {
cell.textLabel!.text = "第一個(gè)TableView"
}
else {
cell.textLabel!.text = "第二個(gè)TableView"
}
return cell
}
}
為什么滑動(dòng)操作不成功呢,網(wǎng)上看到有人說(shuō)TableView繼承自ScrollView,那么滑動(dòng)手勢(shì)很可能在TableView攔截了,因此為ScrollView增加兩個(gè)滑動(dòng)手勢(shì)識(shí)別器.
在viewDidLoad()函數(shù)中添加以下代碼.
// 6. 為scrollView增加滑動(dòng)手勢(shì)識(shí)別器
let swipeLeft = UISwipeGestureRecognizer(target: self, action: "swipe:")
swipeLeft.direction = .Left
swipeLeft.numberOfTouchesRequired = 1
let swipeRight = UISwipeGestureRecognizer(target: self, action: "swipe:")
swipeRight.direction = .Right
swipeRight.numberOfTouchesRequired = 1
scrollView.addGestureRecognizer(swipeLeft)
scrollView.addGestureRecognizer(swipeRight)
定義了兩個(gè)滑動(dòng)的手勢(shì)識(shí)別器,方向分別向左和向右,numberOfTouchesRequired的意思是只要單點(diǎn)觸摸就可以完成滑動(dòng)操作.
把swipe()函數(shù)添加到最后一個(gè)花括號(hào)的上方.
// 滑動(dòng)手勢(shì)處理函數(shù)
func swipe(gesture: UISwipeGestureRecognizer) {
if gesture.direction == .Left {
// 向左滑時(shí)展示第二個(gè)tableview,同時(shí)設(shè)置選中的segmented item
offset = self.view.frame.width
segmented.selectedSegmentIndex = 1
}
else {
offset = 0.0
segmented.selectedSegmentIndex = 0
}
}
0k,代碼階段也結(jié)束了.
運(yùn)行一下程序, 左右滑動(dòng)可以呈現(xiàn)不同的TableView,選中的segmented item也會(huì)跟著改變.
圖片加載不出來(lái)的話, 這里有pdf格式的,提取碼:84e9