Show UIPickerView like a keyboard, without UITextField

后端 未结 6 948
长发绾君心
长发绾君心 2021-02-05 15:56

I\'m looking for a way to present a UIPickerView when the user taps on a UIBarButtonItem. Imagine a filter for the table view results.

I know I

6条回答
  •  半阙折子戏
    2021-02-05 16:43

    Based on borisgolovnev's suggestion and CodeMonkey's answer, I have implemented the idea with an invisible UITextField in the following way in 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]
        }
    }
    

    Usage in your 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()
    }
    

    Example:

    I have attached it to a UITapGestureRecognizer.

提交回复
热议问题