说明:示例在XCode7 beta5完成
创建一个Single View Application,填写相应的信息. Language选择Swift,把项目存储到一个目录,单击Create完成创建.
Storyboard设计阶段
-
打开Main.storyboard文件,取消勾选Use Size Classes,让设计视图呈现iphone的大小.
下面是取消勾选后,设计面板的样子.
现在开始在storyboard中添加要使用到的控件.
从控件库中拖出一个Segmented Control到设计面板的上方.
选中Segmented Control,给它增加如下约束.
接下来拖一个ScrollView到到设计面板中,让它铺满剩余的空间.
同样也要给ScrollView增加约束,这样才可以适应不同屏幕的大小.
接着拖一个TableView到设计面板中,放置在ScrollView上,成为ScrollView的子视图.
调整它的大小,让它的大小和ScrollView的相同.
现在给TableView加上约束.
此时设计面板中多了一些红色的线条,这说明缺少约束或者约束有冲突.
通过以下步骤来增加约束,这样storyboard就有足够的信息来确定控件的位置关系.点击Document Outline左上方的红色小圆圈,在点击空心的红色小圆圈,在弹出框中选择Add Missing Constraints.
接着个体TableView增加一个Prototype Cell.
然后展开TableView选中Table View Cell,给它设置一个重用ID.
为了区分接下来要添加的TableView,选中当前的TableView,给它设置一个tag,这里设置为101,再给它取一个名字.
接下来添加第二个TableView,为了方便操作,在控件库中直接把TableView拖放至Document Outline中,让它位于ScrollView的下方,成为ScrollView的子视图.
使用相同的方式给刚刚添加的TableView设置一个tag,这里设置为102,给它取一个名字,叫做SecondTableView.再给SecondTableView增加一个Prototype Cell,并设置它的reused identifier为second.
接下来这一步比较关键,要改变SecondTableView的位置,这样才能给SecondTableView添加上正确的约束.把SecondTableView的x坐标设置为320,完成后,会把SecondTableView移动到设计面板之外,如下所示.
现在选中SecondTableView为它增加约束.
此时又出现了红色的线条.没关系,有这个方法让红色线条消失.选中FirstTableView,按住ctrl键,鼠标左键从FirstTableView拖出一条箭头到SecondTableView,松开鼠标在弹出菜单中选择Equal Widths.这样做的结果是,两个TableView具有相同的宽度.
ok,到此为止,storyboard的设计工作完成,接下来进入代码阶段.
代码阶段
打开辅助视图,为设计面板中的控件生成相应的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改变时,会触发这个Action
@IBAction func tabChanged(sender: AnyObject) {
}
}
为了不让Segmented Control给状态栏遮挡,在viewDidLoad()函数的下方,添加以下代码,把状态栏隐藏掉.
// 3. 隐藏状态栏
override func prefersStatusBarHidden() -> Bool {
return true
}
让当前ViewController遵循UITableViewDataSource协议,这样就能够给TableView提供数据.类定义的头部将会是下面的样子.
class ViewController: UIViewController, UITableViewDataSource
这里为什么不让ViewController遵循UITableViewDelegate协议呢.因为这个例子只是给TableView填充数据,并不处理发生在TableView上的行为事件.
接着实现两个代理方法,为TableView填充数据.把这两个方法添加在prefersStatusBarHidden()函数的下方.
// 4. 为TableView填充数据
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,然后使用设置好的reused identifier来获取到cell,给cell的textLabel设置简单的字符串.
在viewDidLoad()函数中,添加以下两行代码.这样TableView的代理方法将会由当前的ViewController来执行.
firstTableView.dataSource = self
secondTableView.dataSource = self
选择一个模拟器,运行一下看有什么效果.
第一个TableView已经呈现出来了,试着往左滑动,把第二个TableView呈现出来.滑了几次,发现不能将SecondTableView呈现出来,为什么会这样呢??难道SecondTableView没有添加到ScrollView中.利用前面添加的Action来做个实验,看是否把SecondTableView添加到了ScrollView中.
首先viewDidLoad()函数的上方,定义一个变量,用来记录ScrollView的内容偏移量.
// 5. 定义一个变量来记录scrollview的内容偏移量
var offset: CGFloat = 0.0 {
// 当offset的值改变后会执行didSet代码块
didSet {
UIView.animateWithDuration(0.3) { () -> Void in
self.scrollView.contentOffset = CGPoint(x: self.offset, y: 0.0)
}
}
}
didSet代码块的作用是,用一个0.3秒的过度来设置ScrollView的内容偏移量.
接着在 tabChanged(sender: AnyObject) Action中添加以下代码.
// a. 获取到当前item的下标
let index = (sender as! UISegmentedControl).selectedSegmentIndex
// b. 设置scrollview的内容偏移量
offset = CGFloat(index) * self.view.frame.width
item的下标从0开始.因为TableView的宽度和屏幕的宽度相同,所以呈现FirstTableView时ScrollView的内容偏移量为0,呈现SecondTableView时ScrollView的内容偏移量为一个屏幕的宽度,即(self.view.frame.width).
再运行一遍程序,当点击Second item时,可以把SecondTableView呈现出来,说明有把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的内容偏移量
var offset: CGFloat = 0.0 {
// 当offset的值改变后会执行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改变时,会触发这个Action
@IBAction func tabChanged(sender: AnyObject) {
// a. 获取到当前item的下标
let index = (sender as! UISegmentedControl).selectedSegmentIndex
// b. 设置scrollview的内容偏移量
offset = CGFloat(index) * self.view.frame.width
}
// 3. 隐藏状态栏
override func prefersStatusBarHidden() -> Bool {
return true
}
// 4. 为TableView填充数据
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
}
}
为什么滑动操作不成功呢,网上看到有人说TableView继承自ScrollView,那么滑动手势很可能在TableView拦截了,因此为ScrollView增加两个滑动手势识别器.
在viewDidLoad()函数中添加以下代码.
// 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()函数添加到最后一个花括号的上方.
// 滑动手势处理函数
func swipe(gesture: UISwipeGestureRecognizer) {
if gesture.direction == .Left {
// 向左滑时展示第二个tableview,同时设置选中的segmented item
offset = self.view.frame.width
segmented.selectedSegmentIndex = 1
}
else {
offset = 0.0
segmented.selectedSegmentIndex = 0
}
}
0k,代码阶段也结束了.
运行一下程序, 左右滑动可以呈现不同的TableView,选中的segmented item也会跟着改变.
图片加载不出来的话, 这里有pdf格式的,提取码:84e9