/*
* 解决IOS8.1中UIActionSheet与UIPickerView不兼容
* 我的思路是用UIView模拟UIActionSheet的效果,向UIView中加入UIPickerView
*
* 背景:做一个备忘录的时候,设置提醒时间时,想要做成万年历的效果(底部弹出一个时间选择项,还可以选择农历日历),本想在
* UIActionSheet中,加入UIPickerView实现的。但UIActionSheet在IOS8.1后已经废弃了,且实现起来效果很糟糕。
* 声明:刚好在网站看到这个问题的解决方案,但是用objective-c实现,我用swift实现了一遍,担心新人和我一样,不太容易理解使用
* 增加了注释。原文出处:黑月神话, vjson.com
*/
import UIKit
//使用代理模式,以便于自定义点击“确认”或“取消”按钮后执行的操作
protocol SimulateActionSheetDelegate:UIPickerViewDelegate {
func actionCancle() //取消按钮
func actionDone() //确认按钮
}
class SimulateActionSheet: UIView,SimulateActionSheetDelegate {
var headToolBar:UIView! //头部工具条,用于放置操作按钮(取消按钮、确认按钮)
var pickView:UIPickerView! //pickView 用户显示内容
var delegate:SimulateActionSheetDelegate!
var headToolBarColor:UIColor! //头部工具条背景颜色
var textColorNormal:UIColor! //按钮文本颜色
var textClolorPressed:UIColor! //按钮按下文本颜色
var pickerBgColor:UIColor! //pickView的背景颜色
//初始化,设置样式
init(frame: CGRect,headToolBarColor:UIColor,textColorNormal:UIColor,textClolorPressed:UIColor,pickerBgColor:UIColor) {
super.init(frame: frame)
self.headToolBarColor = headToolBarColor
self.textColorNormal = textColorNormal
self.textClolorPressed = textClolorPressed
self.pickerBgColor = pickerBgColor
}
//required修饰符的使用规则
/*required修饰符只能用于修饰类初始化方法。
*当子类含有异于父类的初始化方法时(初始化方法参数类型和数量异于父类),子类必须要实现父类的required初始化方法,
并且也要使用required修饰符而不是override。
*当子类没有初始化方法时,可以不用实现父类的required初始化方法。
*/
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
//类方法,获得自定义样式的SimulateActionSheet类的实例
class func getSimulateActionSheet(headToolBarColor:UIColor,textColorNormal:UIColor,textClolorPressed:UIColor,pickerBgColor:UIColor)->SimulateActionSheet {
let sheet = SimulateActionSheet.init(frame: CGRectMake(0,0,UIScreen.mainScreen().bounds.size.width,UIScreen.mainScreen().bounds.size.height), headToolBarColor: headToolBarColor, textColorNormal: textColorNormal, textClolorPressed: textClolorPressed, pickerBgColor: pickerBgColor)
sheet.backgroundColor = UIColor.clearColor()
sheet.headToolBar = sheet.actionHeadToolBar() //初始化头部工具条
sheet.pickView = sheet.actionPickerView() //初始化UIPickView
sheet.addSubview(sheet.headToolBar) //把工具条,添加到自定义的SimulateActionSheet中
sheet.addSubview(sheet.pickView) //把UIPickView,添加到自定义的SimulateActionSheet中
return sheet
}
//初始化头部工具条
func actionHeadToolBar() ->UIView {
let headTools = UIView(frame: CGRectMake(0, 0, 320, 44))
headTools.backgroundColor = self.headToolBarColor
//设置取消按样式
let cancelButton = UIButton(frame: CGRectMake(0,0,0,0))
cancelButton.setTitle("取消", forState: .Normal)
cancelButton.setTitleColor(self.textClolorPressed, forState: .Highlighted)
cancelButton.setTitleColor(self.textColorNormal, forState: .Normal)
cancelButton.addTarget(self, action: "actionCancle", forControlEvents: .TouchUpInside)
cancelButton.sizeToFit()
headTools.addSubview(cancelButton)
//将自适应向布局约束的转化关掉(根据情况有时需要有时不需要)
cancelButton.translatesAutoresizingMaskIntoConstraints = false
let cancleConstraintLeft = NSLayoutConstraint(item: cancelButton, attribute: NSLayoutAttribute.Leading, relatedBy: .Equal, toItem: headTools, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 10.0)
let cancleConstrainY = NSLayoutConstraint(item: cancelButton, attribute: NSLayoutAttribute.CenterY, relatedBy: .Equal, toItem: headTools, attribute: NSLayoutAttribute.CenterY, multiplier: 1.0, constant: 0)
headTools.addConstraint(cancleConstraintLeft)
headTools.addConstraint(cancleConstrainY)
//确认按钮
let okButton = UIButton(frame: CGRectMake(0,0,0,0))
okButton.setTitle("确认", forState: .Normal)
okButton.setTitleColor(self.textClolorPressed, forState: .Highlighted)
okButton.setTitleColor(self.textColorNormal, forState: .Normal)
okButton.addTarget(self, action: "actionDone", forControlEvents: .TouchUpInside)
okButton.sizeToFit()
headTools.addSubview(okButton)
okButton.translatesAutoresizingMaskIntoConstraints = false
let okConstraintRight = NSLayoutConstraint(item: okButton, attribute: NSLayoutAttribute.Trailing, relatedBy: .Equal, toItem: headTools, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: -10.0)
let okConstrainY = NSLayoutConstraint(item: okButton, attribute: NSLayoutAttribute.CenterY, relatedBy: .Equal, toItem: headTools, attribute: NSLayoutAttribute.CenterY, multiplier: 1.0, constant: 0)
headTools.addConstraint(okConstraintRight)
headTools.addConstraint(okConstrainY)
return headTools
}
//初始化PickerView
func actionPickerView() ->UIPickerView {
let picker = UIPickerView(frame:CGRectMake(0, 44, 0, 0))
picker.showsSelectionIndicator = true
picker.backgroundColor = self.pickerBgColor
return picker
}
//设置整个项目显示的位置
func setInitPostion(Control:UIViewController) {
UIApplication.sharedApplication().keyWindow?.addSubview(self)
self.superview?.bringSubviewToFront(self)
self.pickView.frame = CGRectMake(self.pickView.frame.origin.x, UIScreen.mainScreen().bounds.size.height, self.pickView.frame.size.width, self.pickView.frame.size.height)
self.headToolBar.frame = CGRectMake(self.headToolBar.frame.origin.x, UIScreen.mainScreen().bounds.size.height, self.headToolBar.frame.size.width, self.headToolBar.frame.size.height)
}
/*UIPickerViewDataSource在项目实际使用中,自己根据项目情况自己实现*/
//设置当前列默认显示第几行数据
func selectRow(row: Int, Component: Int, animate: Bool) {
self.pickView.selectRow(row, inComponent: Component, animated: animate)
}
func selectedRowInComponent(component: Int) ->Int {
return self.pickView.selectedRowInComponent(component)
}
func actionCancle(){
self.delegate.actionCancle()
}
func actionDone(){
self.delegate.actionDone()
}
func setDelegate(delegate:SimulateActionSheetDelegate) {
self.delegate = delegate
self.pickView.delegate = delegate
}
//项目出现
func show(controller:UIViewController) {
self.setInitPostion(controller)
let toolBarYposition = UIScreen.mainScreen().bounds.size.height - (self.pickView.frame.size.height
+ self.headToolBar.frame.size.height)
UIView.animateWithDuration(0.25, animations: { () -> Void in
self.backgroundColor = UIColor.darkGrayColor().colorWithAlphaComponent(0.5)
controller.view.tintAdjustmentMode = .Dimmed
controller.navigationController?.navigationBar.tintAdjustmentMode = .Dimmed
self.headToolBar.frame = CGRectMake(self.headToolBar.frame.origin.x, toolBarYposition, self.headToolBar.frame.size.width, self.headToolBar.frame.size.height)
self.pickView.frame = CGRectMake(self.pickView.frame.origin.x, toolBarYposition + self.headToolBar.frame.size.height , self.pickView.frame.size.width, self.pickView.frame.size.height)
}, completion: nil)
}
//项目消失
func dismiss(controller:UIViewController) {
UIView.animateWithDuration(0.25, animations: { () -> Void in
self.backgroundColor = UIColor.clearColor()
controller.view.tintAdjustmentMode = .Normal
controller.navigationController?.navigationBar.tintAdjustmentMode = .Normal
}) { (finished:Bool) -> Void in
self.removeFromSuperview()
}
}
}
测试:
//
// ViewController.swift
// SimulateActionSheet
//
// Created by mac on 16/5/5.
// Copyright © 2016年 fish. All rights reserved.
//
import UIKit
class ViewController: UIViewController,SimulateActionSheetDelegate,UIPickerViewDataSource {
var sheet:SimulateActionSheet!
var provinces = [String]()
var citys = Dictionary<String,[String]>()
var iComponent = 1 //默认只有一列
var iprovince = 0 //当前选中的省
override func viewDidLoad() {
super.viewDidLoad()
provinces.append("广东省")
provinces.append("江西省")
provinces.append("湖南省")
provinces.append("浙江省")
provinces.append("福建省")
citys = ["广东省":["深圳市","广州市","东莞市","清远市"],"湖南省":["长沙市","邵阳市","娄底市","武冈市"],"江西省":["南昌市","九江市","赣州市","上饶市"],"浙江省":["杭州市","宁波市"],"福建省":["福州市","宁波市","泉州市"]]
// Do any additional setup after loading the view, typically from a nib.
}
@IBAction func clickTestButton(sender: UIButton) {
//测试一列按钮的tag设置为100 测试二列按钮的tag设置为200
if sender.tag == 100 {
iComponent = 1
}
else {
iComponent = 2
}
self.sheet = SimulateActionSheet.getSimulateActionSheet(UIColor(red: 240/255, green: 240/255, blue: 240/255, alpha: 0.9), textColorNormal: UIColor(red: 0, green: 146/255, blue: 255/255, alpha: 1), textClolorPressed: UIColor(red: 209/255, green: 213/255, blue: 219/255, alpha: 0.9), pickerBgColor: UIColor(red: 209/255, green: 213/255, blue: 219/255, alpha: 0.9))
self.sheet.setDelegate(self)
self.sheet.selectRow(provinces.count/2, Component: 0, animate: true)
if iComponent == 2 {
iprovince = provinces.count/2
self.sheet.pickView.reloadComponent(1)
}
self.sheet.show(self)
}
func actionCancle() {
sheet.dismiss(self)
}
func actionDone() {
sheet.dismiss(self)
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return iComponent
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if iComponent == 1 {
return self.provinces.count
}
else {
if component == 0 {
return self.provinces.count
}
else {
return (self.citys["\(provinces[iprovince])"]?.count)!
}
}
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if iComponent == 1 {
return self.provinces[row]
}
else {
if component == 0 {
return self.provinces[row]
}
else {
return (self.citys["\(provinces[iprovince])"]?[row])!
}
}
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if component == 0 {
iprovince = row
self.sheet.pickView.reloadComponent(1)
}
}
// @IBOutlet weak var clickTestButton: UIButton!
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
效果: