Created
February 18, 2019 16:52
-
-
Save auramagi/0768176ea34e4d3b9e1005b999153a55 to your computer and use it in GitHub Desktop.
Present UIPicker on a UILabel to select from a few options. Supports a placeholder value. For this example the picker selects a weekday.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
enum Weekday: Int { | |
case monday = 1 | |
case tuesday = 2 | |
case wednesday = 3 | |
case thursday = 4 | |
case friday = 5 | |
case saturday = 6 | |
case sunday = 0 | |
var string: String { | |
return Calendar.current.standaloneWeekdaySymbols[rawValue] | |
} | |
} | |
class ViewController: UIViewController { | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
let label = PickerLabel(frame: .zero) | |
view.addSubview(label) | |
label.translatesAutoresizingMaskIntoConstraints = false | |
let constraints = [ | |
label.centerXAnchor.constraint(equalTo: view.centerXAnchor), | |
label.centerYAnchor.constraint(equalTo: view.centerYAnchor) | |
] | |
NSLayoutConstraint.activate(constraints) | |
//// Pre-set the selected option here like this: | |
// label.selectedOption = .friday | |
} | |
} | |
class PickerLabel: UIControl { | |
var selectedOption: Weekday? = nil { | |
didSet { updateLabel() } | |
} | |
var labelPlaceholder: String = "Select me!" { | |
didSet { updateLabel() } | |
} | |
private let pickerOptions: [Weekday?] = [nil, .monday, .tuesday, .wednesday, .thursday, .friday, .saturday, .sunday] | |
private let pickerPlaceholder = "—" | |
private let label = UILabel() | |
override init(frame: CGRect) { | |
super.init(frame: frame) | |
setup() | |
} | |
required init?(coder aDecoder: NSCoder) { | |
super.init(coder: aDecoder) | |
setup() | |
} | |
func setup() { | |
addTarget(self, action: #selector(presentPicker), for: .touchUpInside) | |
addSubview(label) | |
label.translatesAutoresizingMaskIntoConstraints = false | |
let constraints = [ | |
label.topAnchor.constraint(equalTo: topAnchor), | |
label.bottomAnchor.constraint(equalTo: bottomAnchor), | |
label.leadingAnchor.constraint(equalTo: leadingAnchor), | |
label.trailingAnchor.constraint(equalTo: trailingAnchor) | |
] | |
NSLayoutConstraint.activate(constraints) | |
label.textAlignment = .center | |
updateLabel() | |
} | |
func updateLabel() { | |
if let selectedOption = selectedOption { | |
label.text = selectedOption.string | |
} else { | |
label.text = labelPlaceholder | |
} | |
} | |
// The picker itself | |
private lazy var _inputView: UIView = { | |
let pickerView = UIPickerView() | |
pickerView.delegate = self | |
let row = pickerOptions.firstIndex(of: selectedOption)! | |
pickerView.selectRow(row, inComponent: 0, animated: true) | |
return pickerView | |
}() | |
// Toolbar | |
private lazy var _inputAccessoryView: UIView = { | |
let toolbar = UIToolbar() | |
toolbar.items = [ | |
UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissPicker)), | |
UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)] | |
toolbar.autoresizingMask = [.flexibleHeight, .flexibleWidth] | |
return toolbar | |
}() | |
@objc func presentPicker() { | |
becomeFirstResponder() | |
label.textColor = .red | |
} | |
@objc func dismissPicker() { | |
resignFirstResponder() | |
label.textColor = .black | |
} | |
// Implementation for UIControl methods | |
override var canBecomeFirstResponder: Bool { return true } | |
override var inputView: UIView? { return _inputView } | |
override var inputAccessoryView: UIView? { return _inputAccessoryView } | |
} | |
extension PickerLabel: UIPickerViewDataSource { | |
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { | |
return pickerOptions.count | |
} | |
func numberOfComponents(in pickerView: UIPickerView) -> Int { | |
return 1 | |
} | |
} | |
extension PickerLabel: UIPickerViewDelegate { | |
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { | |
if let option = pickerOptions[row] { | |
return option.string | |
} | |
return pickerPlaceholder | |
} | |
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { | |
selectedOption = pickerOptions[row] | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment