Search code examples
objective-ciosuipickerviewuitoolbaruiactionsheet

odd behavior of UIPickerView on ActionSheet


- (void) actionsheetstart
{
    actionSheet=[[UIActionSheet alloc] initWithTitle:@"" delegate:self cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil];
    [actionSheet showInView:self.view];
    UIToolbar *pickerToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 480, 32)];
    [pickerToolbar sizeToFit];
    pickerToolbar.barStyle = UIBarStyleBlackTranslucent;
    NSMutableArray *barItems = [[NSMutableArray alloc] init];

    UIBarButtonItem *cancelBtn = [[UIBarButtonItem alloc] initWithTitle:@"Cancel" style:UIBarButtonSystemItemCancel target:self action:@selector(cancel_clicked:)];
    [barItems addObject:cancelBtn];
    UIBarButtonItem *flexSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
    [barItems addObject:flexSpace];
    UIBarButtonItem *doneBtn = [[UIBarButtonItem alloc] initWithTitle:@"Done" style:UIBarButtonItemStyleDone target:self action:@selector(done_clicked:)];
    [barItems addObject:doneBtn];
    [pickerToolbar setItems:barItems animated:YES];
    [actionSheet addSubview:pickerToolbar];

    UIPickerView *picker = [[UIPickerView alloc] init];
    picker.frame = CGRectMake(0, 44, 320, 216);
    picker.delegate  = self;
    picker.dataSource = self;
    picker.showsSelectionIndicator = YES;
    [actionSheet addSubview:picker];
}

-(void)done_clicked:(id)sender
{
    [actionSheet dismissWithClickedButtonIndex:0 animated:YES];
}
-(void)cancel_clicked:(id)sender
{
    [actionSheet dismissWithClickedButtonIndex:0 animated:YES];
}

for some reason, the actionsheet is fine, but the UIPickerView and the UIToolBar gone crazy. I've try to set the frame to -px but without any success. what seems to be the problem?

Thanks alot.

dismissing pickerview


Solution

  • Don't insert UIPickerView inside UIActionSheet, you won't get correct behaviour this way. My solution:

    1. Subclass UIButton, implement method canBecomeFirstResponder:, return YES.
    2. Implement inputView method in your subclassed UIButton, return UIPickerView.
    3. Optionally, implement inputAccessoryView method in your subclassed button to return toolbar above your picker.
    4. Make your button becomeFirstResponder: when tapped.

    Voila, you have picker shown modally like a keyboard when button is tapped.

    EDIT:

    MyButton.h

    #import <UIKit/UIKit.h>
    
    @interface MyButton : UIButton
    
    @end
    

    MyButton.m

    #import "MyButton.h"
    
    @implementation MyButton {
        UIDatePicker *_pv;
    }
    
    - (BOOL)canBecomeFirstResponder {
        return YES;
    }
    
    #pragma mark - Picker
    
    - (UIView *)inputView {
        // set up your UIPickerView here
        _pv = [[UIDatePicker alloc] init];
        [_pv setDatePickerMode:UIDatePickerModeTime];
        [_pv setMinuteInterval:30];
        return _pv;
    }
    
    - (UIView *)inputAccessoryView {
        // set up your toolbar here
        UIToolbar *tb = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
        UIBarButtonItem *flex = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
        UIBarButtonItem *ok = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(pick:)];
        [tb setItems:[NSArray arrayWithObjects:flex, ok, nil]];
        return tb;
    }
    
    - (void)pick:(id)sender {
        // store picker value here before closing inputView
        [self resignFirstResponder];
    }
    @end