Search code examples
objective-ciphoneipaduipickerviewactionsheetpicker

UIPickerView with a Done button in Ipad


I have faced one issue to display UIPickerView with a Done button in Ipad. I done detailed researches though many links and blogs and got the suggestion as "display the UIPickerView from an UIActionSheet"

I saw many posts related this, however there is no good answers.So please dont close it as a duplicate.

Also i was able to get some good codes to do it and it worked fine in my Iphone devices. However i were found a difficulty in Ipad devices. The Action-Sheet is not displaying as a full view. Please see the below screenshot.this was the result!!!

UIPickerView with a Don button in Ipad

The code is used to do this is pasted below.

UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil
                                                    delegate:nil
                                                    cancelButtonTitle:nil
                                                    destructiveButtonTitle:nil
                                                    otherButtonTitles:nil];

[actionSheet setActionSheetStyle:UIActionSheetStyleBlackTranslucent];

CGRect pickerFrame = CGRectMake(0, 40, 0, 0);

UIPickerView *pickerView = [[UIPickerView alloc] initWithFrame:pickerFrame];
pickerView.showsSelectionIndicator = YES;
pickerView.dataSource = self;
pickerView.delegate = self;

[actionSheet addSubview:pickerView];
[pickerView release];

UISegmentedControl *closeButton = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObject:@"Close"]];
closeButton.momentary = YES;
closeButton.frame = CGRectMake(260, 7.0f, 50.0f, 30.0f);
closeButton.segmentedControlStyle = UISegmentedControlStyleBar;
closeButton.tintColor = [UIColor blackColor];
[closeButton addTarget:self action:@selector(dismissActionSheet:) forControlEvents:UIControlEventValueChanged];
[actionSheet addSubview:closeButton];
[closeButton release];

[actionSheet showInView:[[UIApplication sharedApplication] keyWindow]];

[actionSheet setBounds:CGRectMake(0, 0, 320, 485)];

Then I have downloaded a excellent sample application from github through sample pickers

After the download, i have copied the classes only mandatory for me to my application.

The method they are using to show the UIPickerView+Done button through Action-Sheet is described below

ActionStringDoneBlock done = ^(ActionSheetStringPicker *picker, NSInteger selectedIndex, id selectedValue) {

        if ([myLabel respondsToSelector:@selector(setText:)]) {
            [myLabel performSelector:@selector(setText:) withObject:selectedValue];
        }
    };

    ActionStringCancelBlock cancel = ^(ActionSheetStringPicker *picker) {

        NSLog(@"Block Picker Canceled");
    };

    NSArray *colors = [NSArray arrayWithObjects:@"Red", @"Green", @"Blue", @"Orange", nil];//picker items to select


    [ActionSheetStringPicker showPickerWithTitle:@"Select a Block" rows:colors initialSelection:0 doneBlock:done cancelBlock:cancel origin:myButton];

In the last line of code they have used the parameter as origin: and we can pass any objects (button,label etc) to it.

The Action-sheet will take origin as the passed object.

Here my issue came again :). I have used segment control to pick the time as per my conditions.

if i give mySegment as the origin parameter,the Action-sheet origin arrow will display from middle of my segment control.Not from the selected tab ,which is too bad and will give confusion to my valuable users.

So i have added individual labels under the segment sections and given it for the origin parameter of the mentioned method and i fixed my issue.

However i know its not a good fix :)

May i know is there any easy way to do it?

Is Apple support ActionSheet+UIPickerView+DoneButton in Ipad?

Any help on this issue is Appreciated


Solution

  • You have to use UIPopOverController.

    First, create a UIPickerViewController for iPhone. You need it for the nib, which will be pushed into the popOver. Initialize the picker in ViewWithPicker

    .h

    #import <UIKit/UIKit.h>
    
    @class ViewWithPickerController;
    
    @protocol PopoverPickerDelegate
    
    @required
    
    - (void) viewWithPickerController:(ViewWithPickerController*) viewWithPickerController didSelectValue:(NSString*) value;
    
    @end
    
    @interface ViewWithPickerController : UIViewController <UIPickerViewDelegate, UIPickerViewDataSource> {
        IBOutlet UIPickerView *pickerView;
        id<PopoverPickerDelegate> delegate;
        NSMutableArray *array;  
    }
    @property(nonatomic, retain) IBOutlet UIPickerView *pickerView;
    @property(nonatomic, assign) id<PopoverPickerDelegate> delegate;
    @end
    

    .m, after you initialized the array in viewDidLoad, picker methods:

    // returns the number of 'columns' to display.
    - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)picker {
        return 1;
    }
    
    // returns the number of rows in each component.
    
    
    - (NSInteger)pickerView:(UIPickerView *)picker numberOfRowsInComponent:(NSInteger)component {
        return [array count];
    }
    
    //returns the string value for the current row
    - (NSString *)pickerView:(UIPickerView *)picker titleForRow:(NSInteger)row forComponent:(NSInteger)component {
       return [array objectAtIndex:row];
    }
    
    //handle selection of a row
    - (void)pickerView:(UIPickerView *)picker didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
        NSString *value = [pickerView.delegate pickerView:picker titleForRow:row forComponent:component];
    
        //notify the delegate about selecting a value
        if(delegate != nil)
            [delegate viewWithPickerController:self didSelectValue:value];
    }
    

    Then, import the viewWithPicker into your main class, create a button and give it this action:

    - (IBAction) showPickerPopupAction:(id) sender {
        self.viewWithPickerController = [[[ViewWithPickerController alloc] initWithNibName:@"ViewWithPicker" bundle:[NSBundle mainBundle]] autorelease];
    
    
        viewWithPickerController.contentSizeForViewInPopover = 
        CGSizeMake(viewWithPickerController.view.frame.size.width, viewWithPickerController.view.frame.size.height);
    
        viewWithPickerController.delegate = self;
    
        self.popoverController = [[[UIPopoverController alloc]
                                   initWithContentViewController:viewWithPickerController] autorelease];
    
    
        [self.popoverController presentPopoverFromRect:popoverButtonForPicker.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
        popoverController.delegate = self;
    
    }
    

    And to select a specific value

    - (void) viewWithPickerController:(ViewWithPickerController*) viewWithPickerController didSelectValue:(NSString*) value
    {   
        yourLabel.text = [NSString stringWithFormat:@"%@ ",value];
    
    }