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