如何将一个选取器视图用于多个文本字段?



我正在尝试构建一些东西(我是 Xcode 和 swift 的新手(,我可以从带有 Picker View 的数组中选择一天的饭菜,我希望我的选择显示在特定日期的文本字段中。我已经得到了这个工作,但只有 1 天。如何让相同的功能在所有 (7( 天内工作?

当我单击下一个文本字段(星期二(时,我也设法获得了选择器视图,但是当我从列表中选择时,星期一的文本字段将遵循我在星期二所做的工作。它们是镜像的。我确实明白我可能应该做一些事情来让那个星期二-Picker以某种方式独一无二,但这就是我卡住的地方。我不知道该改/写什么。有人有什么想法吗?我已经用谷歌搜索了很多关于拾取器视图的信息,但没有关于如何以这种特定方式使用它们的信息......

//
//  ViewController.swift
//  dropdown
//
//  Created by -- on 2019-08-26.
//  Copyright © 2019 --. All rights reserved.
//
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var monday: UITextField!
@IBOutlet weak var tuesday: UITextField!
@IBOutlet weak var wednesday: UITextField!
@IBOutlet weak var thursday: UITextField!
@IBOutlet weak var friday: UITextField!
@IBOutlet weak var saturday: UITextField!
@IBOutlet weak var sunday: UITextField!
// the menu
let Menu = ["Palak Paner",
"Spagetti Köttfärssås",
"Thai Haloumi",
"Thai Quorn",
"Linssoppa",
"SparrisPasta",
"Gröt",
"Gulasch"]
let tuesdayMenu = ["Palak Paner",
"Spagetti Köttfärssås",
"Thai Haloumi",
"Thai Quorn",
"Linssoppa",
"SparrisPasta",
"Gröt",
"Gulasch"]

//When a menu from the list is selected, it will be shown as a string
var mondaySelectedMenu: String?
var tuesdaySelectedMenu: String?

override func viewDidLoad() {
super.viewDidLoad()
//Call on these functions when loaded
createMondayMenuPicker()
createTuesdayMenuPicker()
createToolbar()
}
// This is the pickerView
func createMondayMenuPicker() {
let mondayMenuPicker = UIPickerView()
mondayMenuPicker.delegate = self
monday.inputView = mondayMenuPicker
}
func createTuesdayMenuPicker() {
let tuesdayMenuPicker = UIPickerView()
tuesdayMenuPicker.delegate = self
tuesday.inputView = tuesdayMenuPicker
}

// This is the "DONE" button
func createToolbar() {
let toolBar = UIToolbar()
toolBar.sizeToFit()
let doneButton = UIBarButtonItem(title: "DONE", style: .plain, target: self, action: #selector(ViewController.dismissKeyboard))
toolBar.setItems([doneButton], animated: false)
toolBar.isUserInteractionEnabled = true
monday.inputAccessoryView = toolBar
tuesday.inputAccessoryView = toolBar
}

@objc func dismissKeyboard() {
view.endEditing(true)
}
}

// This is the details for the pickerView
extension ViewController: UIPickerViewDelegate, UIPickerViewDataSource {
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return Menu.count
}

func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return Menu[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
mondaySelectedMenu = Menu[row]
tuesdaySelectedMenu = tuesdayMenu[row]
monday.text = mondaySelectedMenu
tuesday.text = tuesdaySelectedMenu
}

}

因此,我想在单击所有七天时调用相同的数组,但我想显示从该列表中选择的日常选择。有什么想法吗?多谢!

实现此目的的一种方法是使用以下方法。我已将工具栏功能分离到它自己的类中。

创建一个新的类选取器视图的工具栏(在本例中,我调用了 ToolbarPickerView.swift(

import UIKit
protocol ToolbarPickerViewDelegate: class {
func didTapDone()
func didTapCancel()
}
class ToolbarPickerView: UIPickerView {
public private(set) var toolbar: UIToolbar?
public weak var toolbarDelegate: ToolbarPickerViewDelegate?
override init(frame: CGRect) {
super.init(frame: frame)
self.commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.commonInit()
}
private func commonInit() {
let toolBar = UIToolbar()
toolBar.barStyle = UIBarStyle.default
toolBar.isTranslucent = true
toolBar.tintColor = .black
toolBar.sizeToFit()
let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(self.doneTapped))
let spaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let cancelButton = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(self.cancelTapped))
toolBar.setItems([cancelButton, spaceButton, doneButton], animated: false)
toolBar.isUserInteractionEnabled = true
self.toolbar = toolBar
}
@objc func doneTapped() {
self.toolbarDelegate?.didTapDone()
}
@objc func cancelTapped() {
self.toolbarDelegate?.didTapCancel()
}
}

在视图控制器中

import UIKit
class ViewController: UIViewController {
@IBOutlet weak var monday: UITextField!
@IBOutlet weak var tuesday: UITextField!
@IBOutlet weak var wednesday: UITextField!
@IBOutlet weak var thursday: UITextField!
@IBOutlet weak var friday: UITextField!
@IBOutlet weak var saturday: UITextField!
@IBOutlet weak var sunday: UITextField!
var daysArray = [UITextField]()
let pickerView = ToolbarPickerView()
let Menu = ["Palak Paner",
"Spagetti Köttfärssås",
"Thai Haloumi",
"Thai Quorn",
"Linssoppa",
"SparrisPasta",
"Gröt",
"Gulasch"]
var selectedMenu : String?
override func viewDidLoad() {
super.viewDidLoad()
setupDelegateForPickerView()
setupDelegatesForTextFields()
}
func setupDelegatesForTextFields() {
//appending textfields in an array
daysArray += [monday, tuesday, wednesday, thursday, friday, saturday, sunday]
//using the array to set up the delegates, inputview for pickerview and also the inputAccessoryView for the toolbar
for day in daysArray {
day.delegate = self
day.inputView = pickerView
day.inputAccessoryView = pickerView.toolbar
}
}
func setupDelegateForPickerView() {
pickerView.dataSource = self
pickerView.delegate = self
pickerView.toolbarDelegate = self
}
}

为文本字段委托创建扩展

extension ViewController : UITextFieldDelegate {
func textFieldDidBeginEditing(_ textField: UITextField) {
self.pickerView.reloadAllComponents()
}
}

选取器视图和工具栏的扩展

extension ViewController : UIPickerViewDelegate, UIPickerViewDataSource {
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return self.Menu.count
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return self.Menu[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
// Check if the textfield isFirstResponder.
if monday.isFirstResponder {
monday.text = self.Menu[row]
} else if tuesday.isFirstResponder {
tuesday.text = self.Menu[row]
} else if wednesday.isFirstResponder {
wednesday.text = self.Menu[row]
} else if thursday.isFirstResponder {
thursday.text = self.Menu[row]
} else if friday.isFirstResponder {
friday.text = self.Menu[row]
} else if saturday.isFirstResponder {
saturday.text = self.Menu[row]
} else if sunday.isFirstResponder {
sunday.text = self.Menu[row]
} else {
//log errors
}
}
}
extension ViewController: ToolbarPickerViewDelegate {
func didTapDone() {
//      let row = self.pickerView.selectedRow(inComponent: 0)
//      self.pickerView.selectRow(row, inComponent: 0, animated: false)
//      selectedMenu = self.Menu[row]
self.view.endEditing(true)
}
func didTapCancel() {
self.view.endEditing(true)
}
}

PickerView的didSelectRow函数可以通过将其更改为以下内容来简化

func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
for day in daysArray {
if day.isFirstResponder {
day.text = self.Menu[row]
}
}
}

希望这个答案对您有所帮助。

创建一个公共选取器类,如下所示:

class PKMultiPicker: UIPickerView, UIPickerViewDelegate, UIPickerViewDataSource {
internal typealias PickerDone = (_ firstValue: String, _ secondValue: String) -> Void
private var doneBlock : PickerDone!
private var firstValueArray : [String]?
private var secondValueArray = [String]()
static var noOfComponent = 2

class func openMultiPickerIn(_ textField: UITextField? , firstComponentArray: [String], secondComponentArray: [String], firstComponent: String?, secondComponent: String?, titles: [String]?, toolBarTint: UIColor = UIColor.black, doneBlock: @escaping PickerDone) {
let picker = PKMultiPicker()
picker.doneBlock = doneBlock
picker.openPickerInTextField(textField, firstComponentArray: firstComponentArray, secondComponentArray: secondComponentArray, firstComponent: firstComponent, secondComponent: secondComponent, toolBarTint: toolBarTint)
if titles != nil {
let label = UILabel(frame: CGRect(x: UIScreen.main.bounds.size.width/4 - 10, y: 0, width: 100, height: 30))
label.text = titles![0].uppercased()
label.font = UIFont.boldSystemFont(ofSize: 18)
picker.addSubview(label)
if PKMultiPicker.noOfComponent > 1 {
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 30))
label.text = titles![1].uppercased()
label.font = UIFont.boldSystemFont(ofSize: 18)
picker.addSubview(label)
} else {
label.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 30)
label.textAlignment = NSTextAlignment.center
}
}
}
private func openPickerInTextField(_ textField: UITextField?, firstComponentArray: [String], secondComponentArray: [String], firstComponent: String?, secondComponent: String?, toolBarTint: UIColor = UIColor.black) {
firstValueArray  = firstComponentArray
secondValueArray = secondComponentArray
self.delegate = self
self.dataSource = self

let cancelButton = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(pickerCancelButtonTapped))
cancelButton.tintColor = toolBarTint
let doneButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.done, target: self, action: #selector(pickerDoneButtonTapped))
doneButton.tintColor = toolBarTint
let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: nil, action:nil)
let toolbar = UIToolbar()
toolbar.sizeToFit()
let array = [cancelButton, spaceButton, doneButton]
toolbar.setItems(array, animated: true)
toolbar.backgroundColor = UIColor.lightText
textField?.inputView = self
textField?.inputAccessoryView = toolbar
let index = self.firstValueArray?.index(where: {$0.lowercased() == (firstComponent ?? "").lowercased() })
self.selectRow(index ?? 0, inComponent: 0, animated: true)

if PKMultiPicker.noOfComponent > 1 {
let index1 = self.secondValueArray.index(where: {$0.lowercased() == (secondComponent ?? "").lowercased() })
self.selectRow(index1 ?? 0, inComponent: 1, animated: true)
}
}
@IBAction private func pickerCancelButtonTapped(){
UIApplication.shared.keyWindow?.endEditing(true)
}
@IBAction private func pickerDoneButtonTapped(){
UIApplication.shared.keyWindow?.endEditing(true)
let index1 : Int?
let firstValue : String?
index1 = self.selectedRow(inComponent: 0)
if firstValueArray?.count == 0{return}
else{firstValue = firstValueArray?[index1!]}
var index2 :Int!
var secondValue: String!
if PKMultiPicker.noOfComponent > 1 {
index2 = self.selectedRow(inComponent: 1)
secondValue = secondValueArray[index2]
}
self.doneBlock((firstValue ?? ""), (secondValue ?? ""))
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if component == 0 {
return firstValueArray!.count
}
return secondValueArray.count
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return PKMultiPicker.noOfComponent
}

func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
switch component {
case 0:
return firstValueArray?[row]
case 1:
return secondValueArray[row]
default:
return ""
}
}
}

打开选择器和管理选择的示例代码,还有一些选项,您还可以管理组件数量:-

PKMultiPicker.noOfComponent = 1
PKMultiPicker.openMultiPickerIn(textField, firstComponentArray: ["Apple", "Mango","Grapes","Pine apple"], secondComponentArray: [], firstComponent: textField.text, secondComponent: nil, titles: nil, toolBarTint: AppColors.themeGreen) { (firstSelect, secondSelect) in
print("first select : (firstSelect)")
textField.text = firstSelect // you can set text here to the respective text field.
}

在这里,@pawan_kumar描述了一种对具有相同数据的多个文本字段使用相同的选取器视图的方法。 但是您也可以为此绑定不同的数据源。 https://stackoverflow.com/a/60631018/10505343 有一个示例代码。 在这里,我使用UITextField.isFirstResponder来决定应将哪些数据加载到选取器视图中。希望这个答案对你也有帮助。

最新更新