写一个可以快速弹出多种滚轮选择器(PickerView)的小工具

使用这个小框架可以快速的完成注册页面或者个人信息页面的选择项

使用示例效果

TextField使用示例

TextField使用示例.gif

按钮使用示例(gif效果不满意<####>)

按钮使用示例.gif

可以简单快速的实现上图中的效果


使用方法

设置数据.png

1. TextField支持xib和代码生成使用, 只需调用一个方法, 设置选择的数据, 和默认选中的项(可选设置),可以设置是否在滚动的时候自动填充选中的值, 然后是在closure中处理点击完成的响应

TextField使用.png

2. 按钮(点击事件)中的使用, 只需要在相应的点击事件中使用UsefulPickerView的class方法即可, 这些方法和TextField的参数和使用完全相同, 多的一个效果就是点击背景会移除选择器
按钮使用.png

实现思路分析

  1. TextField的实现就比较的方便, 因为系统默认的是点击的时候弹出键盘, 且允许我们修改他的inputView, 所以只需要将TextField的inputView设置为我们想要弹出的pickerView即可.
  1. TextField同时被设置为不响应输入和不显示输入的光标, 这个效果, 只需要重写一个方法即可实现.
  2. 为TextField添加生成PickerView的方法, 最初笔者是在他的初始化的时候就初始化并且设置了他的inputView为需要的PickerView, 但是后来考虑到, 只需要在用户点击了输入框, 即开始编辑的代理方法中设置就好,然后为了避免过多的消耗, 在编辑结束代理方法中, 销毁了inputView.
  3. 最初是在TextField中实现的pickerView的代理方法, 但是后来考虑到按钮的使用的时候也需要实现这些代理方法, 所以就将PickerView和ToolBar单独抽出来了, 便于复用和代码分离.
  4. 因为TextField和pickerView的代理方法分开了, 要实现在用户滚动的时候同步设置选中的数据到TextField中就需要使用代理(Closure)将pickerView选中的数据传递给TextField, 所以 多了一个协议PickerViewDelegate
  5. ToolBar这部分比较简单, 只需要一个取消和确定按钮以及显示标题的Label即可, 同时需要提供给外界响应点击事件的方法(代理或者Closure)
  6. PickerView的实现就稍微要复杂一些, 因为要处理单列数据, 多列不关联数据, 多列关联数据, 城市选择, 日期选择.
  7. 需要实现PickerView相关的代理方法来设置数据, 显示数据和响应选中的数据, 在这些方法里面笔者分别使用了switch来对不同的显示方式(单列数据, 多列不关联数据...)进行了类似的处理.
  8. 关于参数的数组的使用问题, 最初是打算用NSArray来实现, 因为 单列数据中存的是String, 多列数据中存的是数组, 多列关联数据中存的是数组和字典, 所以用NSA仍然有来实现比较方便 , 但是还是想使用swift的Array, 所以就有了使用 [Any], 这种数组的想法, 但是这样就不能利用IDE来检测输入的数据格式是否正确, 所以就单独把每一中情况都使用了一个数组来实现比较的方便和安全.
    10.使用按钮弹出选择器的时候, 因为不像TextField那样本身就可以弹出视图, 所以这里选择了使用当前的Window来弹出一个View来显示pickerView, 同时在选择完成后或者点击背景后需要移除这个弹出的View, 需要使用到一点动画效果来过渡.

代码实现部分

代码比较多, 具体的请看源码地址

TextField部分

// 监听通知    
    private func commonInit() {
        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.didBeginEdit), name: UITextFieldTextDidBeginEditingNotification, object: self)
        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.didEndEdit), name: UITextFieldTextDidEndEditingNotification, object: self)
    }
    // 开始编辑添加pickerView
    func didBeginEdit()  {
        let pickerView = setUpPickerClosure?()
        pickerView?.delegate = self
        inputView = pickerView
    }
    // 编辑完成销毁pickerView
    func didEndEdit() {
        inputView = nil
    }
    // 不要显示输入光标
    override public func caretRectForPosition(position: UITextPosition) -> CGRect {
        return CGRectZero
    }



        // 保存在这个closure中, 在开始编辑的时候在执行, 避免像之前在这里直接初始化pickerView, 每个SelectionTextField在调用这个方法的时候就初始化pickerView,当有多个pickerView的时候就很消耗内存
        setUpPickerClosure = {() -> PickerView in
            
            return PickerView.singleColPicker(toolBarTitle, singleColData: data, defaultIndex: defaultSelectedIndex, cancelAction: {[unowned self] in
                
                    self.endEditing(true)
                
                }, doneAction: {[unowned self] (selectedIndex: Int, selectedValue: String) -> Void in
                    
                    doneAction?(textField:self, selectedIndex: selectedIndex, selectedValue: selectedValue)
                    self.endEditing(true)
                    
                })

            

    

UsefulPickerView. 处理弹出和移除view

    private func showPicker() {
        // 通过window 弹出view
        let window = UIApplication.sharedApplication().keyWindow
        guard let currentWindow = window else { return }
        currentWindow.addSubview(self)

        UIView.animateWithDuration(0.25, animations: {[unowned self] in
            self.backgroundColor = UIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.1)
            self.pickerView.frame = self.showFrame
        }, completion: nil)
        
        
    }
    
    func hidePicker() {
        // 把self从window中移除
        UIView.animateWithDuration(0.25, animations: { [unowned self] in
            self.backgroundColor = UIColor.clearColor()
            self.pickerView.frame = self.hideFrame

        }) {[unowned self] (_) in
            self.removeFromSuperview()
        }
    }

pickerView的代码就很多了,这里就不贴出来了.


详情和Demo请看源码源码地址, 如果您觉得有帮助,不妨给个star鼓励一下,欢迎关注, 欢迎交流

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266

推荐阅读更多精彩内容