前言
在开发过程中,很多时候我们都在自定义tableview,在用户注册界面涉及性别或者出生年月的时候,这时候就需要tableview和pickerview的完美结合。由于开发工龄不大,我目前遇到过两种式样书:
1)点击cell,pickerview从下面弹出来
2)点击cell,插入一行cell(即插入pickerview)
第一种相对来说比较常见,写一个弹性动画即可实现,第二种有利于我们更好的理解tableview。
首先从object library中,拖拽一个UITableView 到 main.storyboard的UIViewController中,当你设置table view的Content为:Static Cells。这个时候就会发生神奇的事情,那就是会报错: static table views are only valid when embedded in UITableViewController instances。翻译下:tableview一定要添加到UITableViewController中。所以说我们要采取一些措施重新来操作一遍:
1、拖拽一个UITableViewController到storyboard中
2、创建一个继承UITableViewController的类
3、设置table view的Content为:Static Cells
效果图
当我们点击出生年月的时候出现以下的效果:
当我们点击性别的时候出现以下的效果:
实现思路
1、我们在storyboard里面布局时会将4个row一起布局并设置好相应的约束。
2、设置2个Bool值(datePickerIsOpen,sexPickerIsOpen)去判断是否展开pickview。
3、在UITableViewDataSource代理中写展开与不展开时候返回的row的个数以及row的高度。
4、我们可以看见第一个图,只生成了row = 0 和 row = 2 的 cell。这主要是通过控制生成cell时候的indexPath。(图2、图3 同理)
5、在点击事件中,主要是一个插入和删除cell的操作
主要代码
class RegisterViewModel: NSObject {
var datePickerIsOpen = false
var sexPickerIsOpen = false
}
extension RegisterViewModel {
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch section {
case 0: return 3
case 1:
if datePickerIsOpen == true && sexPickerIsOpen == false{
return 3
}else if datePickerIsOpen == false && sexPickerIsOpen == false{
return 2
}else if sexPickerIsOpen == true && datePickerIsOpen == false{
return 3
}else {
return 4
}
default: break
}
return 0
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if datePickerIsOpen && indexPath.row == 1 && indexPath.section == 1{
return 150
}else if sexPickerIsOpen && indexPath.row == 2 && indexPath.section == 1{
return 150
}
return 44
}
}
class RegisterViewController: UITableViewController {
@IBOutlet weak var datePickerView: UIDatePicker!
@IBOutlet weak var sexPickerView: UIPickerView!
@IBOutlet weak var dateShowLabel: UILabel!
@IBOutlet weak var sexShowLabel: UILabel!
private let sexDataSource = ["男","女","保密"]
private var viewModel: RegisterViewModel = RegisterViewModel()
override func viewDidLoad() {
self.tableView.backgroundView = UIImageView.init(image: UIImage(named: "img_background"))
}
}
extension RegisterViewController {
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.viewModel.tableView(tableView, numberOfRowsInSection: section)
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return self.viewModel.tableView(tableView, heightForRowAtIndexPath: indexPath)
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var indexPath = indexPath
if self.viewModel.datePickerIsOpen == false && (indexPath.section == 1 && indexPath.row == 1){
indexPath = NSIndexPath(forRow: indexPath.row + 1, inSection: 1)
}else if self.viewModel.sexPickerIsOpen == true && (indexPath.section == 1 && indexPath.row == 2) {
indexPath = NSIndexPath(forRow: indexPath.row + 1, inSection: 1)
}
return super.tableView(tableView, cellForRowAtIndexPath: indexPath)
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: false)
func showDatePicker() {
if self.viewModel.sexPickerIsOpen == true {
hiddenSexPicker()
}
self.viewModel.datePickerIsOpen = true
tableView.insertRowsAtIndexPaths([NSIndexPath(forRow: 1, inSection: 1)], withRowAnimation: .Fade)
}
func showSexPicker() {
if self.viewModel.datePickerIsOpen == true {
hiddenDatePicker()
}
self.viewModel.sexPickerIsOpen = true
tableView.insertRowsAtIndexPaths([NSIndexPath(forRow: 2, inSection: 1)], withRowAnimation: .Fade)
}
func hiddenDatePicker() {
self.viewModel.datePickerIsOpen = false
tableView.deleteRowsAtIndexPaths([NSIndexPath(forRow: 1, inSection: 1)], withRowAnimation: .Fade)
}
func hiddenSexPicker() {
self.viewModel.sexPickerIsOpen = false
tableView.deleteRowsAtIndexPaths([NSIndexPath(forRow: 2, inSection: 1)], withRowAnimation: .Fade)
}
func hiddenAll(){
if self.viewModel.datePickerIsOpen {
hiddenDatePicker()
}else if self.viewModel.sexPickerIsOpen {
hiddenSexPicker()
}
}
if indexPath.section == 1 && indexPath.row == 0 {
self.viewModel.datePickerIsOpen ? hiddenDatePicker(): showDatePicker()
}else if self.viewModel.datePickerIsOpen && (indexPath.section == 1 && indexPath.row == 2) {
showSexPicker()
}else if !self.viewModel.datePickerIsOpen && (indexPath.section == 1 && indexPath.row == 1) {
self.viewModel.sexPickerIsOpen ? hiddenSexPicker() : showSexPicker()
}
if indexPath.section == 0 {
hiddenAll()
}
}
}
extension RegisterViewController: UIPickerViewDelegate,UIPickerViewDataSource {
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return sexDataSource.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return sexDataSource[row]
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
sexShowLabel.text = sexDataSource[row]
self.sexShowLabel.layoutIfNeeded()
}
}