UIPickerView doesn't "snap" to rows and moves out of bounds - ios

I have a problem with UIPickerView. Following a tutorial on YT I created a UIPickerView in a popover after tapping on a textfield.
Everything looks fine, but the UIPickerView acts kind of strange. If I just tap on a row i want to select, it rolls up/down normally to this specific row and makes a selection. But if I try to scroll with my finger it doesn't roll as smooth as it should with a momentum and it doesn't snap on any of the rows. It also doesn't make a selection, but it makes a sound like it does. Worst of all, the picker doesn't seem to care about the number of rows and I can roll up and down as far as I want, although there are no selectable rows anymore.
Here is my code.
decayStatesArray contains four simple String-objects. The UITextfield und the activeDecayString are used in the "donePressed"-methode.
The main function:
-(void)showPicker:(UITextField *)textField {
activeTextfield = textField;
//for the default sizes of a UIPickerView
decayStatePicker = [[UIPickerView alloc] init];
UIViewController *popOverContent = [[UIViewController alloc] init];
UIView *popOverView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, [decayStatePicker frame].size.width, [decayStatePicker frame].size.height+44)];
decayStatePicker = [[UIPickerView alloc] initWithFrame:CGRectMake([popOverView frame].origin.x, [popOverView frame].origin.y + 44, 0, 0)];
pickerToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake([popOverView frame].origin.x, [popOverView frame].origin.y, [popOverView frame].size.width, 44)];
[decayStatePicker setDataSource:self];
[decayStatePicker setDelegate:self];
[decayStatePicker setShowsSelectionIndicator:YES];
[decayStatePicker selectRow:0 inComponent:0 animated:YES];
//Create Toolbar
[pickerToolbar setBarStyle:UIBarStyleBlackTranslucent];
UIBarButtonItem *flexibleSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithTitle:#"Done" style:UIBarButtonItemStyleBordered target:self action:#selector(donePressed)];
UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithTitle:#"Cancel" style:UIBarButtonItemStyleBordered target:self action:#selector(cancelPressed)];
[pickerToolbar setItems:[NSArray arrayWithObjects:flexibleSpace, doneButton, cancelButton, nil]];
[popOverView addSubview:decayStatePicker];
[popOverView addSubview:pickerToolbar];
[popOverContent setView:popOverView];
pickerPopoverController = [[UIPopoverController alloc] initWithContentViewController:popOverContent];
pickerPopoverController.popoverContentSize = CGSizeMake([popOverView frame].size.width, [popOverView frame].size.height);
[pickerPopoverController presentPopoverFromRect:[textField frame] inView:[self view] permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
The delegate methodes:
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent: (NSInteger)component {
return [decayStatesArray count];
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
return [decayStatesArray objectAtIndex:row];
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
if ([pickerView isEqual:decayStatePicker]) {
NSLog(#"The Picker is: %#", pickerView);
NSLog(#"The item is: %#", [decayStatesArray objectAtIndex:row]);
}
activeDecayString = [decayStatesArray objectAtIndex:row];
}

Related

Adding IB constraints breaks UIPickerview - ObjC

I have a view built with interface builder. Whenever I add a pickerview (either via IB or programmatically) on top of the existing IB view, the pickerview will not work. The elements within the pickerview won't scroll properly... the spinner wheel always bounces back to the '0 position' & nothing can be selected. Also, the wheel no longer 'clicks'... and the wheel moves in horizontally as well as vertically... but nothing can be selected.
I even tried to add the pickerview to an actionsheet... same result.
If I completely remove ALL of the constraints in the view, the pickerview works as it should.
Any ideas on what's causing this and/or how to fix?
screen shot
Here's the code:
- (void)viewDidLoad {
[super viewDidLoad];
self.tabBarController.tabBar.hidden = YES;
[self.view setBackgroundColor:[UIColor clearColor]];
letterArray = #[#"",#"A",#"B",#"C",#"D"];
UIBarButtonItem *pBtn = [[UIBarButtonItem alloc] initWithTitle:#"picker"
style:UIBarButtonItemStylePlain
target:self
action:#selector(launchPicker:)];
self.navigationItem.rightBarButtonItem = pBtn;
}
- (void)launchPicker:(id)sender {
self.viewForMainPicker = [[UIView alloc]initWithFrame:CGRectMake(0, 400, [[UIScreen mainScreen] bounds].size.width, 220)];
UIToolbar *toolBar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, [[UIScreen mainScreen] bounds].size.width, 44)];
UIPickerview *mainPicker = [[UIPickerView alloc] initWithFrame:CGRectMake(0, 0, [[UIScreen mainScreen] bounds].size.width, 220)];
UIFont *arrowfont = [UIFont boldSystemFontOfSize:40];
UIFont *titlefont = [UIFont boldSystemFontOfSize:28];
UIBarButtonItem *doneBtn = [[UIBarButtonItem alloc] initWithTitle:#"→"
style:UIBarButtonItemStylePlain
target:self
action:#selector(fakeEvent)];
UIBarButtonItem *title = [[UIBarButtonItem alloc] initWithTitle:#"Select Gender"
style:UIBarButtonItemStylePlain
target:nil
action:nil];
UIBarButtonItem *flex = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
target:self
action:nil];
[doneBtn setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
[UIColor colorWithRed:0.933 green:0.122 blue:0.145 alpha:1.00], NSForegroundColorAttributeName,
arrowfont, NSFontAttributeName, nil] forState:UIControlStateNormal];
[title setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
[UIColor colorWithRed:0.933 green:0.122 blue:0.145 alpha:1.00], NSForegroundColorAttributeName,
titlefont, NSFontAttributeName, nil] forState:UIControlStateNormal];
NSArray *btnArray = [[NSArray alloc] initWithObjects:flex,flex,title,flex,doneBtn,nil];
mainPicker.delegate = self;
mainPicker.dataSource = self;
[toolBar setItems:btnArray];
[viewForMainPicker addSubview:mainPicker];
[viewForMainPicker addSubview:toolBar];
[self.view addSubview:viewForMainPicker];
}
- (void)fakeEvent {
NSLog(#"selected");
}
- (NSInteger)numberOfComponentsInPickerView:(nonnull UIPickerView *)pickerView {
return 1;
}
- (NSInteger)pickerView:(nonnull UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
return letterArray.count;
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
return letterArray[row];
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
NSString *newString = [NSString stringWithFormat:#"%#", letterArray[row]];
NSLog(#"passing: %#",newString);
}

Multiple UIPickerView in the one TableViewController Programatically

I've been trying to do this now for several days but I can't find a way that works. The ways I've tried to set it up loads up the pickerviews as keyboards for the textfields which is what I want but it doesn't show any of the data I've put into them. Can someone help me through the setps of this or give me a link to and example of it. Thank you to any helper.
UIToolbar *toolbar = [[UIToolbar alloc] init];
[toolbar setBarStyle:UIBarStyleBlack];
[toolbar setBarTintColor:[UIColor colorWithRed:237.0/255.0 green:30.0/255.0 blue:36.0/255.0 alpha:1.0]];
[toolbar sizeToFit];
UIBarButtonItem *flexButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
UIBarButtonItem *doneButton =[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(resignKeyboard)];
doneButton.tintColor = [UIColor whiteColor];
NSArray *itemsArray = [NSArray arrayWithObjects:flexButton, doneButton, nil];
[toolbar setItems:itemsArray];
yourTextField.inputAccessoryView = toolbar;
UIPickerView *categoryPicker = [[UIPickerView alloc] initWithFrame:CGRectMake(0, 210, 320, 216)];
categoryPicker.backgroundColor = [UIColor whiteColor];
categoryPicker.delegate = self;
categoryPicker.dataSource = self;
categoryPicker.tag = 1;
yourTextField.inputView = categoryPicker;
after writing all this code in your viewdidappear, implement the delegate and datasource of your pickerview
pragma mark -UIPickerView Delegate and DataSource
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
return yourDataSource.count;
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
return [yourDataSource objectAtIndex:row];
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
yourTextField.text = [yourDataSource objectAtIndex:row];
}
and implement a selector for the done button like that
- (void)resignKeyboard
{
[bloodGroupField resignFirstResponder];
}

how to pass two NSAarray to One UIPickerView Based on UITextFields

I did when I click when textField ,Open UIPickerView and then select PickerView Data it's display on UITextField.
But now i Have 3 text_Filed(city,typeofcars,branches) but I don't know about three TextFileds on Single UIPickerView. So Please give me any idea .
single text-Filed one UIPickerview code is:-
Businessname=[[UITextField alloc]init];
Businessname.frame=CGRectMake(0, 0, 221, 33);
Businessname.placeholder=#"Business Name";
[Businessname setFont:[UIFont fontWithName:#"Times New Roman" size:13]];
Businessname.backgroundColor=[UIColor whiteColor];
[Businessname setBorderStyle:UITextBorderStyleBezel];
Businessname.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
Businessname.layer.borderColor=[[UIColor yellowColor]CGColor];
Businessname.layer.borderWidth= 2.0f;
Businessname.textColor=[UIColor blackColor];
[scrol addSubview:Businessname];
yourpicker = [[UIPickerView alloc] initWithFrame:CGRectMake(0, 400, 100, 150)];
[yourpicker setDataSource: self];
[yourpicker setDelegate: self];
yourpicker.showsSelectionIndicator = YES;
Businessname.inputView = yourpicker;
[yourpicker setShowsSelectionIndicator:YES];
mypickerToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 300, 100, 56)];
mypickerToolbar.barStyle = UIBarStyleBlackOpaque;
[mypickerToolbar sizeToFit];
NSMutableArray *barItems = [[NSMutableArray alloc] init];
UIBarButtonItem *flexSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
[barItems addObject:flexSpace];
UIBarButtonItem *doneBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(pickerDoneClicked)];
[barItems addObject:doneBtn];
[mypickerToolbar setItems:barItems animated:YES];
Businessname.inputAccessoryView = mypickerToolbar;
-(void)pickerDoneClicked
{
NSLog(#"Done Clicked");
[Businessname resignFirstResponder];
mypickerToolbar.hidden=YES;
yourpicker.hidden=YES;
}
- (NSInteger)numberOfComponentsInPickerView:
(UIPickerView *)pickerView
{
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView
numberOfRowsInComponent:(NSInteger)component
{
return [pickarray count];
}
Above code is output is when I click text-filed and then open UIPIckerView and then choose the data. But now I have three TextFields and 3 NSArrays on Please how to pass data data to UIPickerView based on UITextField.
So please give me any idea about my problem
Thanks in Advanced
You can do this by setting tag value for each textfield. Also set delegate of UITextField for each textfield.
In delegate method of UITextField
- (void)textFieldDidBeginEditing:(UITextField *)textField
recongnize textfield by it's tag value.
Based on tag value do something like
// Assumed taht 100, 101, 102 is the tag values for textfield's
NSInteger tag = textField.tag;
switch(tag)
{
case 100:
pickarray = #[#"1",#"2",#"3",#"4"];
break;
case 101:
pickarray = #[#"10",#"20",#"30",#"40"];
break;
case 102:
pickarray = #[#"11",#"21",#"31",#"41"];
break;
default:
break;
}
by this you can assign different values to "pickarray" according to selected textfield and reload your UIPickerView.

UIPicker subview not recognizing input

I am trying to dismiss a UIPickerView using a toolbar similar to the inputAccessoryView on keyboards.
I am using the same UIToolbar for both my text field and my picker, the textfield will dismiss properly, but the picker doesn't even recognize my touch on the button.
This is the code I am using to create the toolbar:
UIToolbar *tipToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 320, 50)];
tipToolbar.barStyle = UIBarStyleDefault;
UIBarButtonItem *donebtn = [[UIBarButtonItem alloc] initWithTitle:#"Done" style:UIBarButtonItemStyleDone target:self action:#selector(resignResponder:)];
tipToolbar.items = [NSArray arrayWithObjects:
[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil],
donebtn, nil
];
[tipToolbar sizeToFit];
_outlet_txt_ipaddr.inputAccessoryView = tipToolbar;
[_outlet_picker addSubview:tipToolbar];
And this is the action that will dismiss the keyboard or the picker:
- (IBAction)resignResponder:(id)sender{
[_outlet_txt_ipaddr resignFirstResponder];
[_outlet_picker resignFirstResponder];
}
The toolbar appears on the picker view, but my tap on the done button isn't even showing the animation let alone call the resignResonder action.
for picker view [_outlet_picker resignFirstResponder]; will not work.
you need to implement the delegate for picker view.
try this code
UIToolbar *tipToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 320, 50)];
tipToolbar.barStyle = UIBarStyleDefault;
UIBarButtonItem *donebtn = [[UIBarButtonItem alloc] initWithTitle:#"Done" style:UIBarButtonItemStyleDone target:self action:#selector(resignResponder:)];
tipToolbar.items = [NSArray arrayWithObjects:
[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil],
donebtn, nil
];
[tipToolbar sizeToFit];
_outlet_txt_ipaddr.inputAccessoryView = tipToolbar;
_outlet_picker.delegate=self;
_outlet_picker.dataSource=self;
_outlet_picker.showsSelectionIndicator=YES;
[self.view addSubview:outlet_picker];
-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component;
{
return [pickerValueAry count];
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component;
{
NSMutableArray *ary = [[NSMutableArray alloc] initWithArray:pickerValueAry];
id str=[ary objectAtIndex:row];
return str;
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
NSLog(#"selectedRowInPicker >> %d",row);
}
you can dismiss the picker view on row select.

change button image from UIPickerView

I have a question about something I've been working on for a while. I have a UIPickerView that lists different types of food. My array looks like such:
food = [[NSMutableArray alloc] init];
[activities addObject:#"Pasta"];
[activities addObject:#"Pizza"];
[activities addObject:#"Spaghetti"];
[activities addObject:#"Salad"];
And my image array is:
foodImages = [[NSMutableArray alloc] init];
[activities addObject:#"Pasta.png"];
[activities addObject:#"Pizza.png"];
[activities addObject:#"Spaghetti.png"];
[activities addObject:#"Salad.png"];
What I am trying to find out is if when the user selects an item from the picker view if I can change the image of a button. So if pasta is selected from the UIPickerView it would change the image of the button to "Pasta.png". How could I go about achieving this in Xcode?
You can certainly do that. First of all though, it would be much better to store the image links and the food name in one array. This will make your app more scalable and changes to the code are less likely to cause errors.
You could do this like so:
food = [[NSMutableArray alloc] init];
[food insertObject:[NSMutableArray arrayWithObjects:#"Pasta",#"Pasta.png",nil] atIndex:[food count]];
[food insertObject:[NSMutableArray arrayWithObjects:#"Pizza",#"Pizza.png",nil] atIndex:[food count]];
Though if your images are the same as your names but with .png extension then do you really need two objects?
As for setting the images for a UIPicker you would do something like this (You need to add UIPickerViewDelegate to the .h and call [self setPickerValue]; where ever you want to show your UIPicker - perhaps a button or text field?):
-(void)setPickerValue {
pickerActionSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:nil cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil, nil];
[pickerActionSheet setActionSheetStyle:UIActionSheetStyleBlackTranslucent];
CGRect pickerFrame = CGRectMake(0, 44, 0, 0);
UIPickerView *valuesPicker = [[UIPickerView alloc] initWithFrame:pickerFrame];
[valuesPicker setDataSource: self];
[valuesPicker setDelegate: self];
valuesPicker.showsSelectionIndicator = YES;
[pickerActionSheet addSubview:valuesPicker];
UIToolbar *controlToolBar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
[controlToolBar setBarStyle:UIBarStyleBlack];
[controlToolBar sizeToFit];
UIBarButtonItem *spacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *setButton = [[UIBarButtonItem alloc] initWithTitle:#"Set" style:UIBarButtonItemStyleDone target:self action:#selector(dismissPicker)];
UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithTitle:#"Cancel" style:UIBarButtonItemStyleBordered target:self action:#selector(cancelPicker)];
[controlToolBar setItems:[NSArray arrayWithObjects:cancelButton, spacer, setButton, nil] animated:NO];
[pickerActionSheet addSubview:controlToolBar];
[pickerActionSheet showInView:self.view];
[pickerActionSheet setBounds:CGRectMake(0, 0, 320, 485)];
}
-(void)cancelPicker {
[pickerActionSheet dismissWithClickedButtonIndex:0 animated:YES];
}
// Number of components.
-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{
return 1;
}
// Total rows in our component.
-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
return [food count];
}
// Display each row's data.
-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component{
return [[food objectAtIndex: row] objectAtIndex:0];
}
The above code makes a nice picker view with a cancel and ok button as a toolbar. The final function you need is (presuming you have a UIButton named "button1"):
-(void)dismissPicker {
[button1 setImage:[UIImage imageNamed: [[food objectAtIndex:row] objectAtIndex:1]] forState:UIControlStateNormal];
[pickerActionSheet dismissWithClickedButtonIndex:0 animated:YES];
}
[yourButton setImage:[UIImage imageNamed:[foodImages objectAtIndex:0]] forState:UIControlStateNormal]; // objectAtIndex 0 will return "Pasta.PNG", 1 will return Pizza, etc.
Implement the UIPickerViewDelegate method (docs):
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
NSString *imageName = foodImages[row];
[button setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
}
Set your picker's delegate:
pickerView.delegate = self;
Then add your images to your Xcode project (if you haven't done so already).
You may also want to set the image for different states, or use setBackgroundImage:forState if you also want text on the button (see UIButton docs for more info).
I'd use a NSDictionary with the food's name being the Key and the food's picture file being the value. Then when it is selected, just load the Key's value as the picture.
If you want to stick with two arrays, then get the index of the selected food and as long as your foodImages array mirrors the food array, you can use that value for the objectAtIndex to load the image.

Resources