使用這個小框架可以快速的完成注冊頁面或者個人信息頁面的選擇項
使用示例效果
TextField使用示例
TextField使用示例.gif
按鈕使用示例(gif效果不滿意<####>)
按鈕使用示例.gif
按鈕使用示例.gif
可以簡單快速的實現上圖中的效果
使用方法
設置數據.png
1. TextField支持xib和代碼生成使用, 只需調用一個方法, 設置選擇的數據, 和默認選中的項(可選設置),可以設置是否在滾動的時候自動填充選中的值, 然后是在closure中處理點擊完成的響應
TextField使用.png
2. 按鈕(點擊事件)中的使用, 只需要在相應的點擊事件中使用UsefulPickerView的class方法即可, 這些方法和TextField的參數和使用完全相同, 多的一個效果就是點擊背景會移除選擇器
按鈕使用.png
按鈕使用.png
實現思路分析
- TextField的實現就比較的方便, 因為系統默認的是點擊的時候彈出鍵盤, 且允許我們修改他的inputView, 所以只需要將TextField的inputView設置為我們想要彈出的pickerView即可.
- TextField同時被設置為不響應輸入和不顯示輸入的光標, 這個效果, 只需要重寫一個方法即可實現.
- 為TextField添加生成PickerView的方法, 最初筆者是在他的初始化的時候就初始化并且設置了他的inputView為需要的PickerView, 但是后來考慮到, 只需要在用戶點擊了輸入框, 即開始編輯的代理方法中設置就好,然后為了避免過多的消耗, 在編輯結束代理方法中, 銷毀了inputView.
- 最初是在TextField中實現的pickerView的代理方法, 但是后來考慮到按鈕的使用的時候也需要實現這些代理方法, 所以就將PickerView和ToolBar單獨抽出來了, 便于復用和代碼分離.
- 因為TextField和pickerView的代理方法分開了, 要實現在用戶滾動的時候同步設置選中的數據到TextField中就需要使用代理(Closure)將pickerView選中的數據傳遞給TextField, 所以 多了一個協議PickerViewDelegate
- ToolBar這部分比較簡單, 只需要一個取消和確定按鈕以及顯示標題的Label即可, 同時需要提供給外界響應點擊事件的方法(代理或者Closure)
- PickerView的實現就稍微要復雜一些, 因為要處理單列數據, 多列不關聯數據, 多列關聯數據, 城市選擇, 日期選擇.
- 需要實現PickerView相關的代理方法來設置數據, 顯示數據和響應選中的數據, 在這些方法里面筆者分別使用了switch來對不同的顯示方式(單列數據, 多列不關聯數據...)進行了類似的處理.
- 關于參數的數組的使用問題, 最初是打算用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鼓勵一下,歡迎關注, 歡迎交流