我正在寻找一种方法来呈现UIPickerView用户点击的时间UIBarButtonItem.想象一下表格视图结果的过滤器.
我知道我可以使用UITextFieldinputView,但事实并非如此 - 我只有a UIBarButtonItem和a UITableView.
我已经看过使用UIActionSheet,但它看起来并不自然,特别是当它显示动画时.
UIView手动启动和关闭屏幕动画是唯一的选择吗?
该应用程序仅适用于iOS 6+和iPhone,因此我无需与任何其他版本/习语保持兼容.
Mic*_*son 20
将UIPickerView作为已添加到视图中的0大小的UITextField的inputView附加.
let picker = UIPickerView()
picker.dataSource = self
picker.delegate = self
let dummy = UITextField(frame: CGRectZero)
view.addSubview(dummy)
dummy.inputView = picker
dummy.becomeFirstResponder()
Run Code Online (Sandbox Code Playgroud)
一个更好的选择仍然是使用UITextField.您不必在屏幕上实际显示它.只需将它放在0x0 UIView中就可以看到它,将它设置inputView为你的UIPickerView并调用becomeFirstResponder它来显示选择器并resignFirstResponder隐藏它.
为方便起见,有一个UIView实现所有的与沿子类UIPickerViewDelegate和UIPickerViewDataSource方法.
至少对我来说最干净的方式,对于Swift4 + Autolayout解决方案,没有a UITextField是添加一个UIView作为顶视图/按钮的容器UIPickerView和a UIToolbar.
然后,如果需要,可以使用动画切换该容器视图的插入/偏移,以隐藏和取消隐藏选择器.
性能
private lazy var view_PickerContainer: UIView = {
let view = UIView()
view.backgroundColor = .white
view.addSubview(self.timePicker)
view.addSubview(self.toolbar_Picker)
return view
}()
private lazy var timePicker: UIDatePicker = {
let picker = UIDatePicker()
picker.minimumDate = Date()
picker.datePickerMode = .time
picker.setDate(Date(), animated: true)
return picker
}()
private let timeFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "hh:mm a"
return formatter
}()
private lazy var toolbar_Picker: UIToolbar = {
let toolbar = UIToolbar()
toolbar.barStyle = .blackTranslucent
toolbar.barTintColor = .blueDarkText
toolbar.tintColor = .white
self.embedButtons(toolbar)
return toolbar
}()
Run Code Online (Sandbox Code Playgroud)
我用来SnapKit以编程方式布局我的视图.您可以使用timePicker's bounds.size作为布局的参考.
实施
在viewDidLoad()中
// Setup timepicker and its container.
self.view.addSubview(self.view_PickerContainer)
self.view_PickerContainer.snp.makeConstraints { (make) in
make.height.equalTo(self.timePicker.bounds.size.height + 50.0)
make.leading.trailing.equalToSuperview()
self.constraint_PickerContainerBottom = make.bottom.equalToSuperview().inset(-500.0).constraint
}
self.timePicker.snp.makeConstraints { (make) in
make.height.equalTo(self.timePicker.bounds.size.height)
make.width.equalToSuperview()
make.bottom.equalToSuperview()
}
// Add toolbar for buttons.
self.toolbar_Picker.snp.makeConstraints { (make) in
make.height.equalTo(40.0)
make.top.leading.trailing.equalToSuperview()
}
Run Code Online (Sandbox Code Playgroud)
嵌入顶视图
private func embedButtons(_ toolbar: UIToolbar) {
func setupLabelBarButtonItem() -> UIBarButtonItem {
let label = UILabel()
label.text = "Set Alarm Time"
label.textColor = .white
return UIBarButtonItem(customView: label)
}
let todayButton = UIBarButtonItem(title: "Today", style: .plain, target: self, action: #selector(self.todayPressed(_:)))
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(self.donePressed(_:)))
let flexButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil)
toolbar.setItems([todayButton, flexButton, setupLabelBarButtonItem(), flexButton, doneButton], animated: true)
}
Run Code Online (Sandbox Code Playgroud)
结果如下:
我选择了borisgolovnev建议的隐形,UITextField并提出了以下Swift 2.3实现:
import UIKit
class PickerViewPresenter: UITextField {
// MARK: - Initialization
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
init() {
super.init(frame: CGRect.zero)
inputView = pickerView
inputAccessoryView = pickerInputAccessoryView
}
// MARK: - Public
var pickerDelegate: UIPickerViewDelegate? {
didSet {
pickerView.delegate = pickerDelegate
}
}
var pickerDataSource: UIPickerViewDataSource? {
didSet {
pickerView.dataSource = pickerDataSource
}
}
var selectButtonAction: (() -> Void)?
var currentlySelectedRow: Int {
return pickerView.selectedRowInComponent(0)
}
func selectRowAtIndex(index: Int) {
pickerView.selectRow(index, inComponent: 0, animated: false)
}
func showPicker() {
self.becomeFirstResponder()
}
func hidePicker() {
self.resignFirstResponder()
}
// MARK: - Views
private let pickerView = UIPickerView(frame: CGRect.zero)
private lazy var pickerInputAccessoryView: UIView = {
let frame = CGRect(x: 0.0, y: 0.0, width: 0.0, height: 48.0)
let pickerInputAccessoryView = UIView(frame: frame)
// Customize the view here
return pickerInputAccessoryView
}()
func selectButtonPressed(sender: UIButton) {
selectButtonAction?()
}
}
Run Code Online (Sandbox Code Playgroud)
然后可以方便地使用PickerViewPresenter:
class ViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(pickerViewPresenter)
}
private let dataModel = [10, 20, 30, 40, 50]
private lazy var pickerViewPresenter: PickerViewPresenter = {
let pickerViewPresenter = PickerViewPresenter()
pickerViewPresenter.pickerDelegate = self
pickerViewPresenter.pickerDataSource = self
pickerViewPresenter.selectButtonAction = { [weak self] () -> Void in
guard let strongSelf = self else {
return
}
let result = strongSelf.dataModel[pickerViewPresenter.currentlySelectedRow]
pickerViewPresenter.hidePicker()
// ...
}
return pickerViewPresenter
}()
private func presentPickerView {
let index = 0 // [0..dataModel.count-1]
pickerViewPresenter.selectRowAtIndex(index)
pickerViewPresenter.showPicker()
}
// MARK: - UIPickerViewDataSource
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return dataModel.count
}
// MARK: - UIPickerViewDelegate
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return "\(dataModel[row]) drunken sailors"
}
}
Run Code Online (Sandbox Code Playgroud)
希望有人发现这个有用=)
它可能不是您唯一的选择,但动画 UIPickerView 对您来说应该相对容易。添加选择器视图,使其显示在屏幕底部之外。什么时候动画它:
[UIView animateWithDuration:0.3 animations:^{
self.datePicker.frame = CGRectMake(0, self.view.bounds.size.height - datePicker.bounds.size.height, datePicker.bounds.size.width, datePicker.bounds.size.height);
}];
Run Code Online (Sandbox Code Playgroud)
当需要隐藏它时:
[UIView animateWithDuration:0.3 animations:^{
self.datePicker.frame = CGRectMake(0, self.view.bounds.size.height, datePicker.bounds.size.width, datePicker.bounds.size.height);
}];
Run Code Online (Sandbox Code Playgroud)
基于borisgolovnev 的建议和CodeMonkey 的回答,我UITextField在Swift 5中以以下方式实现了一个隐形的想法。
import UIKit
class PickerViewPresenter: UITextField, UIPickerViewDataSource, UIPickerViewDelegate {
private lazy var doneToolbar: UIToolbar = {
let toolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 50))
let flexSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(doneButtonTapped))
let items = [flexSpace, doneButton]
toolbar.items = items
toolbar.sizeToFit()
return toolbar
}()
private lazy var pickerView: UIPickerView = {
let pickerView = UIPickerView()
pickerView.dataSource = self
pickerView.delegate = self
return pickerView
}()
var items: [Item] = []
var didSelectItem: ((Item) -> Void)?
private var selectedItem: Item?
init() {
super.init(frame: .zero)
setupView()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setupView() {
inputView = pickerView
inputAccessoryView = doneToolbar
}
@objc private func doneButtonTapped() {
if let selectedItem = selectedItem {
didSelectItem?(selectedItem)
}
resignFirstResponder()
}
func showPicker() {
becomeFirstResponder()
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return items.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return items[row].name
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
selectedItem = items[row]
}
}
Run Code Online (Sandbox Code Playgroud)
在您的 ViewController 中的用法:
private var selectedItem: Item?
private lazy var pickerViewPresenter: PickerViewPresenter = {
let pickerViewPresenter = PickerViewPresenter()
pickerViewPresenter.didSelectItem = { [weak self] item in
self?.selectedItem = item
}
return pickerViewPresenter
}()
view.addSubview(pickerViewPresenter)
// e.g. on a button tap
@objc private func buttonTapped() {
pickerViewPresenter.showPicker()
}
Run Code Online (Sandbox Code Playgroud)
例子:
我已将其附加到UITapGestureRecognizer.
| 归档时间: |
|
| 查看次数: |
10349 次 |
| 最近记录: |