|
| 1 | +// |
| 2 | +// DropDown.swift |
| 3 | +// application |
| 4 | +// |
| 5 | +// Created by Nicolas LELOUP on 25/02/2017. |
| 6 | +// Copyright © 2017 Nicolas LELOUP - Buzznative. All rights reserved. |
| 7 | +// |
| 8 | + |
| 9 | +import Foundation |
| 10 | +import SBPickerSelector |
| 11 | +import UIKit |
| 12 | +import UIKitExtensions |
| 13 | + |
| 14 | +protocol DropDownDataSource { |
| 15 | + func controllerForDropDownDisplaying(_ dropDown: DropDown) -> UIViewController |
| 16 | + |
| 17 | + func valuesForDropDown(_ dropDown: DropDown) -> [String] |
| 18 | + |
| 19 | + func selectedIndexForDropDown(_ dropDown: DropDown) -> Int? |
| 20 | + |
| 21 | + func placeholderKeyForDropDown(_ dropDown: DropDown) -> String? |
| 22 | + |
| 23 | + func isRequired(_ dropDown: DropDown) -> Bool |
| 24 | + |
| 25 | + func getTextColor() -> UIColor |
| 26 | + |
| 27 | + func getFontName() -> String |
| 28 | + |
| 29 | + func getFontSize() -> CGFloat |
| 30 | + |
| 31 | + func getRightIcon() -> UIImage |
| 32 | +} |
| 33 | + |
| 34 | +protocol DropDownDelegate { |
| 35 | + func dropDown(_ dropDown: DropDown!, selectedValue value: String!, index: Int) |
| 36 | + |
| 37 | + func dropDownDeselectedValue(_ dropDown: DropDown!) |
| 38 | +} |
| 39 | + |
| 40 | +public class DropDown: OwnView { |
| 41 | + var dateFormat = "dd/MM/y" |
| 42 | + |
| 43 | + var delegate: DropDownDelegate! |
| 44 | + var dataSource: DropDownDataSource! { |
| 45 | + didSet { |
| 46 | + updatePlaceholder() |
| 47 | + } |
| 48 | + } |
| 49 | + |
| 50 | + var picker: SBPickerSelector = SBPickerSelector.picker() |
| 51 | + var values: [String]! |
| 52 | + var currentTextField: FormInput! |
| 53 | + var selectedIndex: Int! |
| 54 | + |
| 55 | + var mainColor: UIColor = UIColor.blue |
| 56 | + |
| 57 | + @IBOutlet weak var rightIcon: UIImageView! |
| 58 | + @IBOutlet weak var titleTextField: FormInput! |
| 59 | + |
| 60 | + override public func loadView() { |
| 61 | + super.loadView() |
| 62 | + |
| 63 | + picker.delegate = self |
| 64 | + picker.pickerType = SBPickerSelectorType.text |
| 65 | + picker.doneButtonTitle = "OK" |
| 66 | + picker.doneButton?.tintColor = mainColor |
| 67 | + picker.cancelButtonTitle = "Annuler" |
| 68 | + picker.cancelButton?.tintColor = mainColor |
| 69 | + |
| 70 | + updatePlaceholder() |
| 71 | + |
| 72 | + reloadData() |
| 73 | + |
| 74 | + NotificationCenter.default.addObserver( |
| 75 | + self, |
| 76 | + selector: #selector(DropDown.textFieldBecameFirstResponder(_:)), |
| 77 | + name: NSNotification.Name(rawValue: "textFieldBecameFirstResponder"), |
| 78 | + object: nil |
| 79 | + ) |
| 80 | + } |
| 81 | + |
| 82 | + func updatePlaceholder() { |
| 83 | + if let _ = dataSource { |
| 84 | + if let existingPlaceholder = dataSource.placeholderKeyForDropDown(self) { |
| 85 | + updatePlaceholderWithValue(existingPlaceholder) |
| 86 | + } |
| 87 | + } |
| 88 | + } |
| 89 | + |
| 90 | + func updatePlaceholderWithValue(_ value: String) { |
| 91 | + titleTextField.attributedPlaceholder = NSAttributedString( |
| 92 | + string: value, |
| 93 | + attributes: [ |
| 94 | + NSForegroundColorAttributeName: self.dataSource.getTextColor(), |
| 95 | + NSFontAttributeName: UIFont(name: self.dataSource.getFontName(), size: self.dataSource.getFontSize())! |
| 96 | + ] |
| 97 | + ) |
| 98 | + } |
| 99 | + |
| 100 | + func updateSelectedIndex(_ newIndex: Int) { |
| 101 | + selectedIndex = newIndex |
| 102 | + picker.pickerView.selectRow(selectedIndex, inComponent: 0, animated: true) |
| 103 | + if let data: [String] = picker.pickerData as? [String] { |
| 104 | + pickerSelector(picker, selectedValue: data[selectedIndex], index: selectedIndex) |
| 105 | + picker.pickerView(picker.pickerView, didSelectRow: selectedIndex, inComponent: 0) |
| 106 | + } |
| 107 | + } |
| 108 | + |
| 109 | + func resetValue() { |
| 110 | + titleTextField.text! = "" |
| 111 | + } |
| 112 | + |
| 113 | + func reloadData() { |
| 114 | + updatePlaceholder() |
| 115 | + if let itsDataSource = dataSource { |
| 116 | + var values: [String] = itsDataSource.valuesForDropDown(self) |
| 117 | + var offset = 0 |
| 118 | + if nil != dataSource && !dataSource.isRequired(self) { |
| 119 | + values.insert("-", at: 0) |
| 120 | + offset = 1 |
| 121 | + } |
| 122 | + |
| 123 | + picker.pickerData = values |
| 124 | + if let dataSourceSelectedIndex: Int = itsDataSource.selectedIndexForDropDown(self) { |
| 125 | + updateSelectedIndex(dataSourceSelectedIndex + offset) |
| 126 | + } |
| 127 | + } |
| 128 | + } |
| 129 | + |
| 130 | + func presentDropDown() { |
| 131 | + if let itsDataSource = dataSource { |
| 132 | + if let textField = currentTextField { |
| 133 | + textField.resignFirstResponder() |
| 134 | + } |
| 135 | + picker.showPickerOver(itsDataSource.controllerForDropDownDisplaying(self)) |
| 136 | + } |
| 137 | + } |
| 138 | + |
| 139 | + @IBAction func mainButtonTouched(_ sender: AnyObject) { |
| 140 | + presentDropDown() |
| 141 | + } |
| 142 | + |
| 143 | + func textFieldBecameFirstResponder(_ notification: Notification) { |
| 144 | + if let textField: FormInput = notification.object as? FormInput { |
| 145 | + if textField != titleTextField { |
| 146 | + currentTextField = textField |
| 147 | + } else { |
| 148 | + currentTextField = nil |
| 149 | + } |
| 150 | + } |
| 151 | + } |
| 152 | +} |
| 153 | + |
| 154 | +extension DropDown: OwnViewProtocol { |
| 155 | + public var viewName: String { |
| 156 | + return "DropDown" |
| 157 | + } |
| 158 | +} |
| 159 | + |
| 160 | +extension DropDown: SBPickerSelectorDelegate { |
| 161 | + public func pickerSelector(_ selector: SBPickerSelector!, selectedValue value: String!, index idx: Int) { |
| 162 | + let required = (nil != dataSource && !dataSource.isRequired(self)) |
| 163 | + var offset = 0 |
| 164 | + if (required && 0 != idx) || !required { |
| 165 | + titleTextField.text = value |
| 166 | + titleTextField.textColor = self.dataSource.getTextColor() |
| 167 | + titleTextField.font = UIFont(name: self.dataSource.getFontName(), size: self.dataSource.getFontSize()) |
| 168 | + if required { |
| 169 | + offset = 1 |
| 170 | + } |
| 171 | + |
| 172 | + if let itsDelegate = delegate { |
| 173 | + itsDelegate.dropDown(self, selectedValue: value, index: idx - offset) |
| 174 | + self.selectedIndex = idx - offset |
| 175 | + } |
| 176 | + } else { |
| 177 | + resetValue() |
| 178 | + |
| 179 | + if let itsDelegate = delegate { |
| 180 | + itsDelegate.dropDownDeselectedValue(self) |
| 181 | + self.selectedIndex = nil |
| 182 | + } |
| 183 | + } |
| 184 | + } |
| 185 | + |
| 186 | + public func pickerSelector(_ selector: SBPickerSelector!, dateSelected date: Date!) { |
| 187 | + if .date == picker.pickerType { |
| 188 | + if let _ = date { |
| 189 | + let dateFormatter = DateFormatter() |
| 190 | + dateFormatter.dateFormat = self.dateFormat |
| 191 | + |
| 192 | + titleTextField.text = dateFormatter.string(from: date) |
| 193 | + titleTextField.textColor = self.dataSource.getTextColor() |
| 194 | + titleTextField.font = UIFont(name: self.dataSource.getFontName(), size: self.dataSource.getFontSize()) |
| 195 | + |
| 196 | + if let dateSelf: DateDropDown = self as? DateDropDown { |
| 197 | + if let dateDropDownDelegate: DateDropDownDelegate = dateSelf.dateDropDownDelegate { |
| 198 | + dateDropDownDelegate.dropDown(dateSelf, selectedDate: date) |
| 199 | + dateSelf.selectedDate = date |
| 200 | + } |
| 201 | + } |
| 202 | + } |
| 203 | + } |
| 204 | + } |
| 205 | +} |
0 commit comments