I am looking to create a date scroller in iOS. I am trying to reproduce the scroller found in the native calendar app in day view with the sun-sat days and the ability to scroll left and right to view other weeks.
What is the best way to go about achieving this?
I have tried a ContainerView with swipe gestures and then I thought I would replace the view in the container with a new one (copy of the same view but the previous/next weeks dates). However when adding a new view it takes over the whole view and not just the view container.
The design of the app is:
NavViewController -> ViewController -> Container ->
SwipeViewController
Inside the View Controller I have this in the swipe action method:
let viewController = self.storyboard!.instantiateViewController(withIdentifier: "swipeViewControllerStoryboard") as! SwipeViewController
self.swipeContainer.addSubview(viewController.view)
I am not sure I understand it very well but creating custom PickerView is more or less the same as creating any other component i.e tableViews. create an IBOutlet pickerView. Create class that inherits from UIPickerView and implement:
UIPickerViewDataSource
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1 //maybe more?
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return yourArray.count
}
UIPickerViewDelegate
func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat {
return (CGFloat)70
}
func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
let view = UIView(frame: CGRect(x: 0, y: 0, width: customWidth, height: 100)) //height CGFloat
//And create your labels here and add to view.addSubView(label)
//let label = UILabel(frame: CGRect(x: 0, y: 0, width: customWidth, height: 70))
//...
//..
//.
//use CGAffineTransform and rotate the picker to horizontal
view.transform = CGAffineTransform(rotationAngle: 90 * (.pi/180))
return view
}
Back to your ViewController instantiate the CustomPicker. Set the delegate and datasource of the pickerView to your CustomPicker instance.
I am sure there are many ways of doing this and it can be a hack. Maybe rather find a way to customise the UIDatePicker, but should you want to customise your pickerViews with any other data, I would go this route.
Related
I have a UIPickerView with 2 components:
The hidden rows however are shifted towards the center. I think it has to do with the space that UIPickerView places between the 'wheels'.
I don't see anything in iOS' rather brief documentation discussing how to prevent this.
Here's my code:
func pickerView(_ pickerView: UIPickerView, widthForComponent component: Int) -> CGFloat
{
return self.currenciesPicker.width / 2
}
func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat
{
return 50.0
}
func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView
{
var cell: CurrencyPickerCell
if view == nil
{
let width = self.pickerView(pickerView, widthForComponent: component)
let height = self.pickerView(pickerView, rowHeightForComponent: component)
cell = CurrencyPickerCell(frame: CGRect(x: 0.0, y: 0.0, width: width, height: height))
}
else
{
cell = view as! CurrencyPickerCell
}
let code = self.codes[row]
cell.nameLabel.text = Currency.names[code]
cell.symbolLabel.text = Currency.symbols[code]
return cell
}
When I let widthForComponent return half the picker's size minus 20, the cells just show up 20 point smaller. This creates empty borders on the left and right ends of the picker view. It does not change this weird 'parallax'.
Does anyone have an idea what's causing this and how to prevent it?
How should I calculate widthForComponent (is half the width of the picker correct)?
Unfortunately this is how the UIPickerView control is designed. It's supposed to look like a couple of wheels sitting side by side that you are looking at from directly above. It's a bit of a strange one considering all the push towards a flat design style Apple has made but there is no way to change it.
The only real options are to do it yourself, either completely manually or possibly subclassing UIPickerView and handling the drawing yourself, or to use a 3rd party control.
I tried to put a UIPickerView in a UIViewController and show a simple items in it with this code:
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 3
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return 10
}
func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
let pickerLabel = UILabel()
pickerLabel.textColor = UIColor.black
pickerLabel.text = "10"
pickerLabel.textAlignment = NSTextAlignment.center
pickerLabel.sizeToFit()
return pickerLabel
}
everything is fine but when I changed numberOfComponents to 2 picker view didn't show correct. Why this is happening?(Xcode 8 iOS 10)
There are two things to notice here:
You have used: pickerLabel.sizeToFit() which would size the label to its content.
Next is that if you comment pickerLabel.sizeToFit() and put a background color to your label. You'd get the following result
As you can see in here that PickerView has a curvature and a distance in between cells which is causing this issue. So solution is you can give a width to your label & no size to fit and apply a background while testing your result and come to the best possible combination.
For instance, check the iOS Native clock timer:
"They have tried playing around with width of label and index"
Please note:
The curvature is causing the width to decrease and label is center aligned so it is taking it along the path of decreasing width, if you get what i'm trying to say here.
This should explain it.
Cheers!
I am implementing a custom picker view only with images. The problem is, the images are overlayed over each other like that:
This is the code configuring the images in the picker view:
func pickerView(pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusingView view: UIView!) -> UIView {
let chosenImage: UIImageView = UIImageView(image: UIImage(named: iconArray[row]))
NSLog("choosen image \(iconArray[row])")
let workaroundImageView: UIImageView = UIImageView(frame: chosenImage.frame)
workaroundImageView.backgroundColor = UIColor(patternImage: chosenImage.image!)
return workaroundImageView
}
What am I missing? Any suggestions?
Utilize the rowHeightForComponent in the delegate for the UIPickerView.
pickerView:rowHeightForComponent:
Give the desired row height for component as such.
func pickerView(pickerView: UIPickerView!, rowHeightForComponent component: Int) -> CGFloat
So I have UIPickerView that isn't working the way I want it to. It works correctly about 3/4 of the time, but the other 1/4 it doesn't.
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return listsArray.count
}
func pickerView(pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusingView view: UIView!) -> UIView
{
activeQuizPlace = row
var pickerLabel = UILabel()
pickerLabel.textColor = UIColor.whiteColor()
pickerLabel.text = listsArray[row]
pickerLabel.font = UIFont(name: "Georgia", size: 22)
pickerLabel.textAlignment = NSTextAlignment.Center
return pickerLabel
}
The listsArray contains 5 items(which are strings). Rows 0-2 work correctly 100% of the time. However when row 3 is selected it occasionally says that row 1 was, and when row 4 is selected it sometimes says that row 2 was. I think the problem has something to do with the last function I have that controls the UIPickerView. I just copied that code from this website as a way to change the color and font of the text. Before I was using this function I never had a problem with it, or at least never noticed one. Side note: I am using Xcode 6.3.2
I need a way for the picker view to work correctly, as well as to be able to change its font and color. I would love help with this I've been looking for answers online for 2 hours and can't figure out what I'm doing wrong, thanks in advance!
I think you need to remove the line activeQuizPlace = row from the code you have shown and then add this function below.
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
activeQuizPlace = row
}
The function you were using is not called with the index that the user selects, it is called with the index that the system needs for drawing the views.
The suggested function should be the one you are after (hopefully).
I am currently working on a small project and i have a viewController that has 4 textFields which 3 work ok. They take String objects. However, the 4th textField is supposed to bring up a UIPickerView with 4 selectable items.
So far this is what i have in my controller that implements this:
#IBOutlet var pickerTextfield: UITextField!
#IBOutlet var itemPicker: UIPickerView! = UIPickerView()
The pickerTextfield is the UITextField object that is the 4th field.
The itemPicker is an unlinked UIPickerView that i want to create programatically.
Right below these properties, i have an array of items for the UIPickerView object:
var seasonalItems = ["Spring", "Summer", "Fall", "Winter"]
In my viewDidLoad method i have this as follow:
itemPicker.hidden = true;
pickerTextfield.text = seasonalItems[0]
pickerTextfield.delegate = self
And the rest of the implementation:
// Below these lines is the implementation of the Picker
func numberOfComponentsInPickerView(pickerView: UIPickerView!) -> Int{
return 1
}
// returns the # of rows in each component..
func pickerView(pickerView: UIPickerView!, numberOfRowsInComponent component: Int) -> Int{
return seasonalItems.count
}
func pickerView(pickerView: UIPickerView!, titleForRow row: Int, forComponent component: Int) -> String! {
return seasonalItems[row]
}
func pickerView(pickerView: UIPickerView!, didSelectRow row: Int, inComponent component: Int)
{
pickerTextfield.text = seasonalItems[row]
itemPicker.hidden = true;
}
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
itemPicker.hidden = false
return false
}
So the end result from this is when i tap the pickerTextfield object in the app, it shows the first item of the array (Spring) but in text within the UITextField object but it does not show the UIPickerView object with the other selectable items where i could select one and then hide it when selected.
My question is, where or what am i doing wrong here? i been trying to figure this out on my own but i do not seem to get good clear examples with Swift and storyboards. I much rather not drag a UIPickerView in the storyboard but rather the way i attempted to implement. Thanks
You can give UIPickerView as inputView for your TextField in which you want to show picker view.
You also do not need to initially hide picker view in this case.
pickerTextfield.inputView = itemPicker
When you use UIPickerView as inputView of any UITextField then when you tap on the TextField instead of default keypad PickerView will show.