【问题标题】:Objective C implementing a UIPickerView with a "Done" buttonObjective C 使用“完成”按钮实现 UIPickerView
【发布时间】:2012-05-22 14:56:40
【问题描述】:

我正在尝试在 UIPickerView 中实现一个“完成”按钮,类似于 link 下的按钮

我查看了类参考,但找不到它

谢谢

【问题讨论】:

    标签: objective-c ios uipickerview xcode4.3


    【解决方案1】:

    最简单的方法是在 Interface Builder 中对其进行建模。它是一个UIView,包含一个UIToolbar 和一个UIPickerView

    然后为UIView 创建一个插座并连接它。

    如果您有UITextField,您可以将您的自定义视图分配给它的inputView 属性。

    [self.textField setInputView:self.customPicker];
    

    或者,您可以将选择器添加到主视图...

    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        self.customPicker.frame = CGRectMake(0, CGRectGetMaxY(self.view.frame), CGRectGetWidth(self.customPicker.frame), CGRectGetHeight(self.customPicker.frame));
        [self.view addSubview:self.customPicker];
    }
    

    ...然后使用此方法显示或隐藏选择器。

    - (void)setPickerHidden:(BOOL)hidden
    {
        CGAffineTransform transform = hidden ? CGAffineTransformIdentity : CGAffineTransformMakeTranslation(0, -CGRectGetHeight(self.customPicker.frame));
    
        [UIView animateWithDuration:0.3 animations:^{
            self.customPicker.transform = transform;
        }];
    }
    

    【讨论】:

    【解决方案2】:

    我在我的 xib 中为“完成”按钮添加了一个带有 UIBarButtonItem 的 UIToolbar,并设置了框架,使其最初不可见(y 值等于父视图的高度)。

    每次用户访问选择器时,我都会用动画更改 UIDatePicker 和 UIToolbar 的框架(y 值),使其与选择器一起从屏幕底部向上滑动,类似于键盘。

    在下面查看我的代码。

    - (IBAction)showPicker
    {
        if(pickerVisible == NO)
        {
            // create the picker and add it to the view
            if(self.datePicker == nil) self.datePicker = [[[UIDatePicker alloc] initWithFrame:CGRectMake(0, 460, 320, 216)] autorelease];
            [self.datePicker setMaximumDate:[NSDate date]];
            [self.datePicker setDatePickerMode:UIDatePickerModeDate];
            [self.datePicker setHidden:NO];
            [self.view addSubview:datePicker];
    
            // the UIToolbar is referenced 'using self.datePickerToolbar'
            [UIView beginAnimations:@"showDatepicker" context:nil];
            // animate for 0.3 secs.
            [UIView setAnimationDuration:0.3];
    
            CGRect datepickerToolbarFrame = self.datePickerToolbar.frame;
            datepickerToolbarFrame.origin.y -= (self.datePicker.frame.size.height + self.datePickerToolbar.frame.size.height);
            self.datePickerToolbar.frame = datepickerToolbarFrame;
    
            CGRect datepickerFrame = self.datePicker.frame;
            datepickerFrame.origin.y -= (self.datePicker.frame.size.height + self.datePickerToolbar.frame.size.height);
            self.datePicker.frame = datepickerFrame;
    
            [UIView commitAnimations];
            pickerVisible = YES;
        }
    }
    
    - (IBAction)done
    {
        if(pickerVisible == YES)
        {
            [UIView beginAnimations:@"hideDatepicker" context:nil];
            [UIView setAnimationDuration:0.3];
    
            CGRect datepickerToolbarFrame = self.datePickerToolbar.frame;
            datepickerToolbarFrame.origin.y += (self.datePicker.frame.size.height + self.datePickerToolbar.frame.size.height);
            self.datePickerToolbar.frame = datepickerToolbarFrame;
    
            CGRect datepickerFrame = self.datePicker.frame;
            datepickerFrame.origin.y += (self.datePicker.frame.size.height + self.datePickerToolbar.frame.size.height);
            self.datePicker.frame = datepickerFrame;
            [UIView commitAnimations];
    
            // remove the picker after the animation is finished
            [self.datePicker performSelector:@selector(removeFromSuperview) withObject:nil afterDelay:0.3];
        }
    }
    

    【讨论】:

    • 你应该看看@Paul-Hunter's answer for create the xib components。
    【解决方案3】:

    我创建了一个自定义类,它支持多方向:

    日期时间选择器.h

        @interface DateTimePicker : UIView {
    }
    
    @property (nonatomic, assign, readonly) UIDatePicker *picker;
    
    - (void) setMode: (UIDatePickerMode) mode;
    - (void) addTargetForDoneButton: (id) target action: (SEL) action;
    
    @end
    

    日期时间选择器.m

    #define MyDateTimePickerToolbarHeight 40
    
    @interface DateTimePicker()
    
    @property (nonatomic, assign, readwrite) UIDatePicker *picker;
    
    @property (nonatomic, assign) id doneTarget;
    @property (nonatomic, assign) SEL doneSelector;
    
    - (void) donePressed;
    
    @end
    
    
    @implementation DateTimePicker
    
    @synthesize picker = _picker;
    
    @synthesize doneTarget = _doneTarget;
    @synthesize doneSelector = _doneSelector;
    
    - (id) initWithFrame: (CGRect) frame {
        if ((self = [super initWithFrame: frame])) {
            self.backgroundColor = [UIColor clearColor];
    
            UIDatePicker *picker = [[UIDatePicker alloc] initWithFrame: CGRectMake(0, MyDateTimePickerToolbarHeight, frame.size.width, frame.size.height - MyDateTimePickerToolbarHeight)];
            [self addSubview: picker];
    
            UIToolbar *toolbar = [[UIToolbar alloc] initWithFrame: CGRectMake(0, 0, frame.size.width, MyDateTimePickerToolbarHeight)];
            toolbar.barStyle = UIBarStyleBlackOpaque;
            toolbar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
    
            UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithTitle: @"Done" style: UIBarButtonItemStyleBordered target: self action: @selector(donePressed)];
            UIBarButtonItem* flexibleSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
            toolbar.items = [NSArray arrayWithObjects:flexibleSpace, doneButton, nil];
    
            [self addSubview: toolbar];
    
            self.picker = picker;
            picker.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleBottomMargin;
    
            self.autoresizesSubviews = YES;
            self.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleBottomMargin;
        }
        return self;
    }
    
    - (void) setMode: (UIDatePickerMode) mode {
        self.picker.datePickerMode = mode;
    }
    
    - (void) donePressed {
        if (self.doneTarget) {
            [self.doneTarget performSelector:self.doneSelector withObject:nil afterDelay:0];
        }
    }
    
    - (void) addTargetForDoneButton: (id) target action: (SEL) action {
        self.doneTarget = target;
        self.doneSelector = action;
    }
    

    在视图控制器中使用自定义视图:

    - (void)viewDidLoad
    {
        [super viewDidLoad];
        UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        [button addTarget:self
                   action:@selector(buttonPressed:)
         forControlEvents:UIControlEventTouchDown];
        [button setTitle:@"Show picker" forState:UIControlStateNormal];
        button.frame = CGRectMake(100, 50, 100, 40.0);
        [self.view addSubview:button];
    
        CGRect screenRect = [[UIScreen mainScreen] bounds];
        CGFloat screenWidth = screenRect.size.width;
        CGFloat screenHeight = screenRect.size.height;
        picker = [[DateTimePicker alloc] initWithFrame:CGRectMake(0, screenHeight/2 - 35, screenWidth, screenHeight/2 + 35)];
        [picker addTargetForDoneButton:self action:@selector(donePressed)];
        [self.view addSubview:picker];
        picker.hidden = YES;
        [picker setMode:UIDatePickerModeDate];
    }
    
    -(void)donePressed {
        picker.hidden = YES;
    }
    
    -(void)buttonPressed:(id)sender {
        picker.hidden = NO;
    }
    

    希望这会有所帮助。 :)

    【讨论】:

    • 我在尝试你的方法。我创建了一个自定义类,并将 .h 文件导入到一个新类中。但它说未定义的标识符选择器。我做错了吗?
    • #import #import "DateTimePicker.h" @interface ViewController : UIViewController { DateTimePicker *dateTimePicker; }
    【解决方案4】:

    有一个更优雅的解决方案。我不确定这是否是最近的(从 iOS7 开始),但这对我来说非常有用。

    TJDatePicker.h

    @protocol TJDatePickerActionDelegate <NSObject>
    - (void)cancel:(id)sender;
    - (void)done:(id)sender;
    @end
    
    @interface TJDatePicker : UIDatePicker
    @property (strong, nonatomic) UIView *navInputView;
    @property (weak, nonatomic) id<TJDatePickerActionDelegate> actionDelegate;
    @end
    

    TJDatePicker.m

    #import "TJDatePicker.h"
    
    @interface TJDatePicker ()
    @property (strong, nonatomic) TJButton *cancelButton;
    @property (strong, nonatomic) TJButton *doneButton;
    @end
    
    @implementation TJDatePicker
    
    - (id)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self)
        {
            [self updateSubviews];
        }
    
        return self;
    }
    
    - (void)layoutSubviews
    {
        [super layoutSubviews];
    
        [self updateSubviews];
    }
    
    - (void)updateSubviews
    {
        self.navInputView.frame = CGRectMake(0, 0, self.width, 45);
        self.cancelButton.frame = CGRectMake(5, 5, 80, 35);
        CGFloat width = 80;
        self.doneButton.frame = CGRectMake(CGRectGetMaxX(self.navInputView.frame) - width, self.cancelButton.frame.origin.y, width, self.cancelButton.height);
    }
    
    - (UIView *)navInputView
    {
        if (!_navInputView)
        {
            _navInputView = [[UIView alloc] init];
            _navInputView.backgroundColor = [UIColor whiteColor];
    
            self.cancelButton = [UIButton buttonWithType:UIButtonTypeCustom];
            [self.cancelButton setTitle:@"CANCEL" forState:UIControlStateNormal];
            [self.cancelButton addTarget:self action:@selector(cancelButtonPressed) forControlEvents:UIControlEventTouchUpInside];
            [_navInputView addSubview:self.cancelButton];
    
            self.doneButton = [UIButton buttonWithType:UIButtonTypeCustom];
            [self.doneButton setTitle:@"DONE" forState:UIControlStateNormal];
            [self.doneButton addTarget:self action:@selector(doneButtonPressed) forControlEvents:UIControlEventTouchUpInside];
            [_navInputView addSubview:self.doneButton];
        }
    
        return _navInputView;
    }
    
    - (void)cancelButtonPressed
    {
        [self.actionDelegate cancel:self];
    }
    
    - (void)doneButtonPressed
    {
        [self.actionDelegate done:self];
    }
    

    然后在实施时...

    self.datePicker = [[TJDatePicker alloc] init];
    self.datePicker.actionDelegate = self;
    self.textField.inputAccessoryView = self.datePicker.navInputView;
    

    这里的关键是使用您计划将UIDatePicker 设置为的UITextField 中的inputAccessoryView

    【讨论】:

      【解决方案5】:

      您可以使用 ActionSheetPicker 获得工具栏中的“完成”按钮。它是您自己构建的绝佳选择。

      https://github.com/skywinder/ActionSheetPicker-3.0

      【讨论】:

      • 请帮助我理解它是如何不友好的?我在寻找答案时遇到了这个问题,发现对我来说最好的答案是使用图书馆。为什么其他人不想知道这个?
      【解决方案6】:

      成功!好的,我从不建议这样做,但这里是在您的特定教程代码中创建完成按钮的位置:

      查看故事板,我们可以看到,当您单击“AddPersonTVC.h”(故事板右上角的类)中的“角色”框时,会弹出一个名为“RollPickerTVCell.h”的类

      查看 RollPickerTVCell.h,我们注意到整个类是“CoreDataTableViewCell”的子类

      @interface RolePickerTVCell : CoreDataTableViewCell <UIPickerViewDataSource, UIPickerViewDelegate>
      

      查看类“CoreDataTableViewCell.m”,我们终于找到了我们的uibarbuttonitem!

      UIBarButtonItem *doneBtn =[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(done:)];
      

      【讨论】:

        【解决方案7】:

        如果您正在处理表格视图单元格并且您没有使用 UITextField(因此您不会使用附件视图),这就是我所做的:

        我创建了一个名为 GWDatePickerCell 的表格视图单元格,看起来像这样(不涉及 .nib 文件)。

        GWDatePickerCell.h:

        #import <UIKit/UIKit.h>
        
        @interface GWDatePickerCell : UITableViewCell
        
        @property (nonatomic, strong) UIDatePicker *datePicker;
        @property (nonatomic, strong) UIToolbar *toolbar;
        @property (nonatomic, strong) UIBarButtonItem *buttonDone;
        
        @end
        

        GWDatePickerCell.m:

            #import "GWDatePickerCell.h"
        
            @implementation GWDatePickerCell
        
            - (id) initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
                if(!(self=[super initWithStyle:style reuseIdentifier:reuseIdentifier])) return nil;
        
            _datePicker = [[UIDatePicker alloc] init];
            [_datePicker setMinuteInterval:5];
            [_datePicker setDatePickerMode:UIDatePickerModeDateAndTime];
            [self.contentView addSubview:_datePicker];
        
            _toolbar = [[UIToolbar alloc] init];
            _buttonDone = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:nil action:nil];
            _toolbar.items = @[[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil], _buttonDone];
            [self.contentView addSubview:_toolbar];
        
            return self;
        }
        
        - (void)layoutSubviews{
            [super layoutSubviews];
            CGRect r = self.contentView.bounds;
            r.origin.y +=44;
            r.size.height = 216;
            CGRect tb = self.contentView.bounds;
            tb.size.height = 44;
            _datePicker.frame = r;
            _toolbar.frame = tb;
        }
        
        @end
        

        现在在表格视图中创建单元格时我要做的就是:

        • 为“完成”按钮指定 @selector
        • heightForRowAtIndexPath 中设置正确的单元格高度

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-01-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多