Добавить UIPickerView и кнопку в листе действий - как? - PullRequest
120 голосов
/ 12 августа 2009

Мое приложение требует добавления следующих вещей в лист действий.

  • UIToolbar
  • Кнопка на UIToolbar
  • UIPicker Control

Я включил изображение, чтобы понять мои требования.

alt text

Не могли бы вы объяснить, как это можно реализовать?

Ответы [ 11 ]

1 голос
/ 17 июля 2014

Мне понравился подход, принятый Wayfarer и flexaddicted, но я обнаружил (как aZtral), что он не работает, так как backgroundTapButton был единственным элементом, который реагировал на взаимодействие с пользователем. Это заставило меня поместить все три его подпредставления: _picker, _pickerToolbar и backgroundTapButton внутри содержащего представления (всплывающего окна), которое затем анимировалось на экране и за его пределами. Мне также нужна была кнопка «Отмена» на панели _pickerToolbar. Вот соответствующие элементы кода для всплывающего представления (вам необходимо указать собственный источник данных выбора и методы делегирования).

#define DURATION            0.4
#define PICKERHEIGHT        162.0
#define TOOLBARHEIGHT       44.0

@interface ViewController ()
@property (nonatomic, strong) UIView        *popup;
@property (nonatomic, strong) UIPickerView  *picker;
@property (nonatomic, strong) UIToolbar     *pickerToolbar;
@property (nonatomic, strong) UIButton      *backgroundTapButton;
@end

-(void)viewDidLoad {
    // These are ivars for convenience
    rect = self.view.bounds;
    topNavHeight = self.navigationController.navigationBar.frame.size.height;
    bottomNavHeight = self.navigationController.toolbar.frame.size.height;
    navHeights = topNavHeight + bottomNavHeight;
}

-(void)showPickerView:(id)sender {
    [self createPicker];
    [self createToolbar];

    // create view container
    _popup = [[UIView alloc] initWithFrame:CGRectMake(0.0, topNavHeight, rect.size.width, rect.size.height - navHeights)];
    // Initially put the centre off the bottom of the screen
    _popup.center = CGPointMake(rect.size.width / 2.0, rect.size.height + _popup.frame.size.height / 2.0);
    [_popup addSubview:_picker];
    [_popup insertSubview:_pickerToolbar aboveSubview:_picker];

    // Animate it moving up
    // This seems to work though I am not sure why I need to take off the topNavHeight
    CGFloat vertCentre = (_popup.frame.size.height - topNavHeight) / 2.0;

    [UIView animateWithDuration:DURATION animations:^{
        // move it to a new point in the middle of the screen
        [_popup setCenter:CGPointMake(rect.size.width / 2.0, vertCentre)];
    } completion:^(BOOL finished) {
        // When done, place an invisible 'button' on the view behind the picker,
        // so if the user "taps to dismiss" the picker, it will go away
        self.backgroundTapButton = [UIButton buttonWithType:UIButtonTypeCustom];
        _backgroundTapButton.frame = CGRectMake(0, 0, _popup.frame.size.width, _popup.frame.size.height);
        [_backgroundTapButton addTarget:self action:@selector(doneAction:) forControlEvents:UIControlEventTouchUpInside];
        [_popup insertSubview:_backgroundTapButton belowSubview:_picker];
        [self.view addSubview:_popup];
    }];
}

-(void)createPicker {
    // To use the default UIPickerView frame of 216px set frame to CGRectZero, but we want the 162px height one
    CGFloat     pickerStartY = rect.size.height - navHeights - PICKERHEIGHT;
    self.picker = [[UIPickerView alloc] initWithFrame:CGRectMake(0.0, pickerStartY, rect.size.width, PICKERHEIGHT)];
    _picker.dataSource = self;
    _picker.delegate = self;
    _picker.showsSelectionIndicator = YES;
    // Otherwise you can see the view underneath the picker
    _picker.backgroundColor = [UIColor whiteColor];
    _picker.alpha = 1.0f;
}

-(void)createToolbar {
    CGFloat     toolbarStartY = rect.size.height - navHeights - PICKERHEIGHT - TOOLBARHEIGHT;
    _pickerToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, toolbarStartY, rect.size.width, TOOLBARHEIGHT)];
    [_pickerToolbar sizeToFit];

    NSMutableArray *barItems = [[NSMutableArray alloc] init];
    UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancelAction:)];
    [barItems addObject:cancelButton];

    // Flexible space to make the done button go on the right
    UIBarButtonItem *flexSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
    [barItems addObject:flexSpace];

    // The done button
    UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(doneAction:)];
    [barItems addObject:doneButton];
    [_pickerToolbar setItems:barItems animated:YES];
}

// The method to process the picker, if we have hit done button
- (void)doneAction:(id)sender {
    [UIView animateWithDuration:DURATION animations:^{
        _popup.center = CGPointMake(rect.size.width / 2.0, rect.size.height + _popup.frame.size.height / 2.0);
    } completion:^(BOOL finished) { [self destroyPopup]; }];
    // Do something to process the returned value from your picker
}

// The method to process the picker, if we have hit cancel button
- (void)cancelAction:(id)sender {
    [UIView animateWithDuration:DURATION animations:^{
        _popup.center = CGPointMake(rect.size.width / 2.0, rect.size.height + _popup.frame.size.height / 2.0);
    } completion:^(BOOL finished) { [self destroyPopup]; }];
}

-(void)destroyPopup {
    [_picker removeFromSuperview];
    self.picker = nil;
    [_pickerToolbar removeFromSuperview];
    self.pickerToolbar = nil;
    [self.backgroundTapButton removeFromSuperview];
    self.backgroundTapButton = nil;
    [_popup removeFromSuperview];
    self.popup = nil;
}
...