I'm trying to adapte the size of my UIPickerView, and the content inside, I have resize the height of the picker view:
let pickerView = UIPickerView()
if DeviceType.IS_IPHONE_4_OR_LESS {
pickerView.frame=CGRectMake(0, 200, view.frame.width, 100)
} else if DeviceType.IS_IPHONE_5 {
pickerView.frame=CGRectMake(0, 200, view.frame.width, 200)
} else if DeviceType.IS_IPHONE_6 {
pickerView.frame=CGRectMake(0, 200, view.frame.width, 200)
} else if DeviceType.IS_IPHONE_6P {
pickerView.frame=CGRectMake(0, 200, view.frame.width, 250)
} else if UIDevice.currentDevice().userInterfaceIdiom == .Pad {
pickerView.frame=CGRectMake(0, 200, view.frame.width, 300)
}
// pickerView.backgroundColor = .whiteColor()
pickerView.showsSelectionIndicator = true
pickerView.delegate = self
pickerView.dataSource = self
self.pickerView = pickerView
But now I want to resize the content inside, the height of each row, the size of the text, and do multiline if the content is too long, but I don't know how to do.
My code:
#IBOutlet var tfProjet: UITextField!
var pvProjetData = ["-Choisir-", "Rachat de crédits", "Renégociation de crédits"]
override func viewDidLoad() {
super.viewDidLoad()
let pickerView = UIPickerView()
if DeviceType.IS_IPHONE_4_OR_LESS {
pickerView.frame=CGRectMake(0, 200, view.frame.width, 100)
} else if DeviceType.IS_IPHONE_5 {
pickerView.frame=CGRectMake(0, 200, view.frame.width, 200)
} else if DeviceType.IS_IPHONE_6 {
pickerView.frame=CGRectMake(0, 200, view.frame.width, 200)
} else if DeviceType.IS_IPHONE_6P {
pickerView.frame=CGRectMake(0, 200, view.frame.width, 250)
} else if UIDevice.currentDevice().userInterfaceIdiom == .Pad {
pickerView.frame=CGRectMake(0, 200, view.frame.width, 300)
}
// pickerView.backgroundColor = .whiteColor()
pickerView.showsSelectionIndicator = true
pickerView.delegate = self
pickerView.dataSource = self
self.pickerView = pickerView
tfProjet.inputView = pickerView
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int{
return 1
}
func selectRow(row: Int, inComponent component: Int, animated: Bool){
}
func updatePicker(){
self.pickerView!.reloadAllComponents()
pickerView.selectRow(0, inComponent: 0, animated: false)
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if tfProjet.isFirstResponder(){
return pvProjetData.count
}
return 1
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if tfProjet.isFirstResponder(){
return pvProjetData[row]
}
return ""
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if tfProjet.isFirstResponder(){
let itemselected = pvProjetData[row]
tfProjet.text = itemselected
self.tfProjet.endEditing(true)
}
}
Forget doing that by code, use autolayout. Auytolayout is indepentent from device.
Related
I'm using UIPickerView in button the only problem which I've faced I want user can select the multiple values from UIPickerView not only one values and also change background colour accordingly when user select multiple item.See my code and pic you get an idea what trying to achieve thanks.
#IBOutlet weak var buttonRole: UIButton!
var rolesPicker = UIPickerView()
var toolBar = UIToolbar()
var userRoles:\[String\] = \["Importer","Creater","Writer","Barber"\]
var selectedIndex :Int = 0
#IBAction func didTapPickRoles(_ sender: UIButton) {
rolesPicker = UIPickerView.init()
rolesPicker.delegate = self
rolesPicker.dataSource = self
rolesPicker.backgroundColor = UIColor.white
rolesPicker.autoresizingMask = .flexibleWidth
rolesPicker.contentMode = .center
rolesPicker.frame = CGRect.init(x: 0.0, y: UIScreen.main.bounds.size.height - 300, width: UIScreen.main.bounds.size.width, height: 300)
self.view.addSubview(rolesPicker)
toolBar = UIToolbar.init(frame: CGRect.init(x: 0.0, y: UIScreen.main.bounds.size.height - 300, width: UIScreen.main.bounds.size.width, height: 50))
toolBar.items = \[UIBarButtonItem.init(title: "Done", style: .done, target: self, action: #selector(onDoneButtonTapped))\]
self.view.addSubview(toolBar)
rolesPicker.selectRow(selectedIndex, inComponent: 0, animated: true)
buttonRole.layer.borderWidth = 1
buttonRole.layer.borderColor = UIColor.gray.cgColor
}
#objc func onDoneButtonTapped() {
toolBar.removeFromSuperview()
rolesPicker.removeFromSuperview()
}
}
extension PickerViewController: UIPickerViewDelegate, UIPickerViewDataSource {
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return userRoles.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
userRoles\[row\]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
selectedIndex = row
buttonRole.setTitle(userRoles\[row\], for: .normal)
}
}
I have a UITableView with 2 components for users to enter their height in feet and inches. I would like to add a button inside of the UIPicker toolbar that will give the option to change the input from 2 components (feet and inches) to only centimeters. I have added the toolbar button on the UIPickerView however I don't know what to do to make the change back and fourth from feet and inches to cm UIPickerView.
let heightTF: UITextField = {
let tf = UITextField()
tf.placeholder = " Height"
tf.translatesAutoresizingMaskIntoConstraints = false
return tf
}()
var pickerView: UIPickerView!
let feetList = Array(3...9)
let inchList = Array(0...11)
let numberOfComponents = 4
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return numberOfComponents
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if component == 0 {
return feetList.count
}else if component == 2 {
return inchList.count
}else {
return 1
}
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if component == 0 {
return "\(feetList[row])"
}else if component == 1 {
return "ft"
}else if component == 2 {
return "\(inchList[row])"
}else {
return "in"
}
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
let feetIndex = pickerView.selectedRow(inComponent: 0)
let inchIndex = pickerView.selectedRow(inComponent: 2)
heightTF.text = "\(feetList[feetIndex])'\(inchList[inchIndex])''"
}
#objc func donePicker() {
heightTF.resignFirstResponder()
}
#objc func cmAction() {
print("cm pressed")
}
func addDoneButtonOnKeyboard(){
let doneToolbar: UIToolbar = UIToolbar(frame: CGRect.init(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 50))
doneToolbar.barStyle = .default
let cmAction: UIBarButtonItem = UIBarButtonItem(title: "CM", style: .done, target: self, action: #selector(self.cmAction))
let flexSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let done: UIBarButtonItem = UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(self.doneButtonAction))
let items = [cmAction, flexSpace, done]
doneToolbar.items = items
doneToolbar.sizeToFit()
heightTF.inputAccessoryView = doneToolbar
}
#objc func doneButtonAction(){
heightTF.resignFirstResponder()
}
override func viewDidLoad() {
addDoneButtonOnKeyboard()
self.pickerView = UIPickerView(frame:CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 216))
self.pickerView.delegate = self
self.pickerView.dataSource = self
heightTF.inputView = self.pickerView
self.pickerView.backgroundColor = UIColor.white
heightTF.inputView = self.pickerView
}
First you need to save the type of unit you want to use :
enum UnitType {
case feetInches
case cm
}
var unitType = UnitType.feetInches
Then in the action you change the value between feetInches and cm, and reload all components of the pickerView.
#objc func cmAction() {
switch unitType {
case .feetInches:
// add code to convert from feet/inches to cm
unitType = .cm
self.pickerView.reloadAllComponents()
// add code to select cm row
case .cm:
// add code to convert from cm to feet/inches
unitType = .feetInches
self.pickerView.reloadAllComponents()
// add code to select feet and inches rows
}
}
In each pickerView delegate method you set up according to the value of unitType.
eg :
func numberOfComponents(in pickerView: UIPickerView) -> Int {
switch unitType {
case .feetInches:
return numberOfComponents /* =4 */
case .cm:
return 2 /* (number of cm) and cm */
}
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
switch unitType {
case .feetInches:
if component == 0 {
return "\(feetList[row])"
}else if component == 1 {
return "ft"
}else if component == 2 {
return "\(inchList[row])"
}else {
return "in"
}
case .cm:
if component == 0 {
return "\(cmList[row])"
}else if component == 1 {
return "cm"
}
}
}
...
I have two UIPickerviews that appear on one ViewController. I have tried to follow the following tutorial.
I have followed the suggestion in that I have tagged each of the UITextFields (I have 4 in total). See the the image.
Below is the code for the UIPickerViews.
extension DriverViewController: UIPickerViewDelegate, UIPickerViewDataSource {
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if pickerView.tag == 0 {
return tracks.count
} else {
return drivers.count
}
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if pickerView.tag == 0 {
return "\(tracks[row])"
} else {
return "\(drivers[row])"
}
}
The problem I am having is that the tracks array appear on all of the UITextfields.
Below is the code for each of the Arrays and the title of the UIPickerView.
override func viewDidLoad() {
super.viewDidLoad()
tracks = ["Melbourne", "Manama", "Shanghai", "Baku",
"Barcelona", "Monaco", "Montreal","Le Castellet","Spielberg",
"Silverstone","Hockenheim","Budapest","Francorchamps","Monza","Singapore","Sochi","Suzuka","Austin","Interlagos","Abu Dhabi"]
drivers = ["Lewis Hamilton","Antonio Giovinazzi","Kimi Raikkonen","Charles Leclerc","Sebastian Vettel","Romain Grosjean","Kevin Magnussen","Lando Norris",
"Carlos Sainz","Valtteri Bottas","Sergio Perez","Lance Stroll","Pierre Gasly","Max Verstappen","Nico Hulkenberg","Daniel Ricciardo","Alexander Albon","Daniil Kvyat","Robert Kubica","George Russell"]
createTrackPicker()
createDriverPicker()
createToolBar()
// Do any additional setup after loading the view.
}
func createTrackPicker() {
let trackPicker = UIPickerView()
trackPicker.delegate = self
TrackTextField.inputView = trackPicker
}
func createDriverPicker() {
let driverPicker = UIPickerView()
driverPicker.delegate = self
firstTextField.inputView = driverPicker
secondTextField.inputView = driverPicker
thirdTextField.inputView = driverPicker
}
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
TrackTextField.inputAccessoryView = toolBar
firstTextField.inputAccessoryView = toolBar
secondTextField.inputAccessoryView = toolBar
thirdTextField.inputAccessoryView = toolBar
}
#objc func dismissKeyboard() {
view.endEditing(true)
}
You forgot the tag.
func createDriverPicker() {
let driverPicker = UIPickerView()
driverPicker.tag = 1 // <—-
I see many solutions out there for the UIPickerView font size, but it seems they are all based on text based arrays and / or require a UIViewController.
I am using an Int Array within a UITableViewCell and cannot seem to find something that will work with what I am trying to accomplish.
Here is the code:
import UIKit
class AirTemperatureTableViewCell: UITableViewCell, UIPickerViewDelegate, UIPickerViewDataSource
{
let numberOfComponents: Int = 2
let temperatureComponentRows: Int = 501
let temperatureSymbolComponentRows: Int = 2
let Fahrenheit: String = "F"
let Celsius: String = "C"
let minDegrees = -250
let maxDegrees = 250
private var degrees: Array<Int> = [Int]()
var temperature: Int = 30 // our default temperature
var temperatureType: String = "C" // our default type is Celsius
#IBOutlet var airTemperaturePicker: UIPickerView!
override func awakeFromNib()
{
super.awakeFromNib()
for i in self.minDegrees ..< self.maxDegrees+1
{
self.degrees.append(i)
}
self.airTemperaturePicker.selectRow(280, inComponent: 0, animated: true)
}
override func setSelected(selected: Bool, animated: Bool)
{
super.setSelected(selected, animated: animated)
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int
{
return self.numberOfComponents
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int
{
if component == 0
{
return self.temperatureComponentRows
}
else
{
return self.temperatureSymbolComponentRows
}
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String?
{
//
// If we are component 0, the degrees, return the value for the given row.
//
if component == 0
{
return String(self.degrees[row])
}
else
{
if row == 0
{
return self.Celsius
}
else
{
return self.Fahrenheit
}
}
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int)
{
}
}
any help would be appreciated.
You can use a UILabel with the viewForRow method of the UIPickerViewDataSource. You can then configure it with all the regular label options incl. setting font size, color, etc.:
// goes in lieu of titleForRow if customization is desired
func pickerView(pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusingView view: UIView?) -> UIView {
let pickerLabel = UILabel()
if component == 0 {
pickerLabel.textColor = .darkGrayColor()
pickerLabel.textAlignment = .Center
pickerLabel.text = String(self.degrees[row])
pickerLabel.font = UIFont(name:"Helvetica", size: 28)
} else {
pickerLabel.textColor = .redColor()
pickerLabel.textAlignment = .Center
pickerLabel.font = UIFont(name:"Helvetica", size: 28)
if row == 0 {
pickerLabel.text = self.Celsius
} else {
pickerLabel.text = self.Fahrenheit
}
}
return pickerLabel
}
You should use the UIPickerViewDelegate function viewForRow inside your UITableViewCell subclass like so:
func pickerView(pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusingView view: UIView?) -> UIView {
let view = UIView(frame: picker.frame)
let label = UILabel(frame: picker.frame)
label.textAlignment = .Center
label.text = String(degrees[row])
label.font = UIFont(name: "Arial", size: 15)
label.adjustsFontSizeToFitWidth = true
view.addSubview(label)
return view
}
picker is an #IBOutlet for your UIPickerView in your UITableView subclass set using either the prototype cell or external nib and control-drag. Also, make sure to set the picker's delegate and dataSource properties inside awakeFromNib.
override func awakeFromNib() {
super.awakeFromNib()
picker.dataSource = self
picker.delegate = self
//Your Code Below
}
This should make a cell width pickerView with a UILabel of your font choice.
I'm trying to put a done button to my picker view because, when I slide to choose an item the uipickerview automatically select the slided row, so I prefer have a button done:
#IBOutlet var tfProjet: UITextField!
var pvProjetData = ["-Choisir-", "Rachat de crédits", "Renégociation de crédits"]
override func viewDidLoad() {
super.viewDidLoad()
let pickerView = UIPickerView()
if DeviceType.IS_IPHONE_4_OR_LESS {
pickerView.frame=CGRectMake(0, 200, view.frame.width, 100)
} else if DeviceType.IS_IPHONE_5 {
pickerView.frame=CGRectMake(0, 200, view.frame.width, 200)
} else if DeviceType.IS_IPHONE_6 {
pickerView.frame=CGRectMake(0, 200, view.frame.width, 200)
} else if DeviceType.IS_IPHONE_6P {
pickerView.frame=CGRectMake(0, 200, view.frame.width, 250)
} else if UIDevice.currentDevice().userInterfaceIdiom == .Pad {
pickerView.frame=CGRectMake(0, 200, view.frame.width, 300)
}
// pickerView.backgroundColor = .whiteColor()
pickerView.showsSelectionIndicator = true
pickerView.delegate = self
pickerView.dataSource = self
self.pickerView = pickerView
let pickerToolBar = UIToolbar()
pickerToolBar.barStyle = UIBarStyle.Black //you can change the style
pickerToolBar.translucent = true
pickerToolBar.tintColor = UIColor.whiteColor() // or other colours
pickerToolBar.sizeToFit()
let spaceButtonPicker = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: nil, action: nil)
let cancelButtonPicker = UIBarButtonItem(title: "Ok", style: UIBarButtonItemStyle.Plain, target: self, action: "cancelDatePicker:")
pickerToolBar.setItems([cancelButtonPicker, spaceButtonPicker], animated: false)
pickerToolBar.userInteractionEnabled = true
tfDateNaissance.inputAccessoryView = pickerToolBar
tfProjet.inputView = pickerView
tfProjet.inputAccessoryView = pickerToolBar
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int{
return 1
}
func selectRow(row: Int, inComponent component: Int, animated: Bool){
}
func updatePicker(){
self.pickerView!.reloadAllComponents()
pickerView.selectRow(0, inComponent: 0, animated: false)
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if tfProjet.isFirstResponder(){
return pvProjetData.count
}
return 1
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if tfProjet.isFirstResponder(){
return pvProjetData[row]
}
return ""
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if tfProjet.isFirstResponder(){
let itemselected = pvProjetData[row]
tfProjet.text = itemselected
self.tfProjet.endEditing(true)
}
}
I see the button Ok, but it doesn't work, when I slide the row is automatically selected.