UILabel doesn't show inputView

前端 未结 7 1277
长发绾君心
长发绾君心 2020-12-18 07:14

I would use a UILabel to allow users to select a date with UIDatePicker.

To do this, I created an UILabel subclass overwriting the inputView and the inputAccessoryVi

相关标签:
7条回答
  • 2020-12-18 07:27

    Thanks to the suggestions (especially the comment from NeverBe and the answer proposed by rdelmar) I found the problem in my code. In brief, in order to show the input label, a call to the becomeFirstResponder method when the user tap the label is needed.

    Following the UILabel subclass implementation corrected (the header file remains the same):

    @implementation YPInteractiveUILabel
    
    - (id)initWithCoder:(NSCoder *)aDecoder
    {
        self = [super initWithCoder:aDecoder];
    
        if (self)
        {
            UIDatePicker *datePicker = [[UIDatePicker alloc] init];
            [self  setInputView:datePicker];
    
            UITapGestureRecognizer *tapper = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(launchPicker:)];
            [self addGestureRecognizer:tapper];
    
        }
    
        return self;
    }
    
    - (BOOL)isUserInteractionEnabled
    {
        return YES;
    }
    
    - (BOOL)canBecomeFirstResponder
    {
        return YES;
    }
    
    -(void)launchPicker:(UITapGestureRecognizer *) tapper
    {
        [self becomeFirstResponder];
    }
    
    
    @end
    
    0 讨论(0)
  • 2020-12-18 07:30

    How about something like this. Rather than subclass the label, just add a gesture recognizer to it, and bring up the picker in the tap recognizer's handler. In the picker's action method, populate the label and dismiss the picker. This example works, but you'd probably want to add some animation to make it look better:

    - (void)viewDidLoad {
        [super viewDidLoad];
        self.label.userInteractionEnabled = YES;
        UITapGestureRecognizer *tapper = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(launchPicker:)];
        [self.label addGestureRecognizer:tapper];
    }
    
    -(void)launchPicker:(UITapGestureRecognizer *) tapper {
        UIDatePicker *picker = [[UIDatePicker alloc] initWithFrame:CGRectMake(5, 150, 300, 200)];
        [picker addTarget:self action:@selector(updateLabel:) forControlEvents:UIControlEventValueChanged];
        [self.view addSubview:picker];
    }
    
    -(IBAction)updateLabel:(UIDatePicker *)sender {
        self.label.text = [NSString stringWithFormat:@"%@",sender.date ];
        [sender removeFromSuperview];
    }
    
    0 讨论(0)
  • 2020-12-18 07:32

    I know this is an old question but this might still be useful to someone.

    There is another way to solve this - there is no need to complicate things with gesture recognizers...

    GTPDateLabel.h

    @interface GTPDateLabel : UILabel
    
    @property (readonly, retain) UIView *inputView;
    
    @end
    

    GTPDateLabel.m

    #import "GTPDateLabel.h"
    
    @implementation GTPDateLabel
    
    @synthesize inputView = _inputView;
    
    - (id)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
    
        if (self)
        {
            self.userInteractionEnabled = YES;
        }
    
        return self;
    }
    
    - (id)initWithCoder:(NSCoder *)aDecoder
    {
        self = [super initWithCoder:aDecoder];
    
        if (self)
        {
            self.userInteractionEnabled = YES;
        }
    
        return self;
    }
    
    -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
    {
        [super touchesEnded:touches withEvent:event];
    
        [self becomeFirstResponder];
    }
    
    - (BOOL)canBecomeFirstResponder
    {
        return YES;
    }
    
    -(UIView *)inputView
    {
        if (!_inputView)
        {
            UIDatePicker *datePicker = [[UIDatePicker alloc] init];
    
            _inputView = datePicker;
        }
    
        return _inputView;
    }
    
    @end
    

    Note that you should also set the delegate and in case of custom UIPicker also dataSource...

    0 讨论(0)
  • 2020-12-18 07:34

    Here is the UILabel that shows PickerView, in Swift 4

    final class DatePickerLabel: UILabel {
      private let pickerView: UIPickerView
      private let toolbar: UIToolbar
    
      required init(pickerView: UIPickerView, toolbar: UIToolbar) {
        self.pickerView = pickerView
        self.toolbar = toolbar
        super.init(frame: .zero)
    
        let recogniser = UITapGestureRecognizer(target: self, action: #selector(tapped))
        addGestureRecognizer(recogniser)
      }
    
      required init?(coder aDecoder: NSCoder) {
        fatalError()
      }
    
      override var inputView: UIView? {
        return pickerView
      }
    
      override var inputAccessoryView: UIView? {
        return toolbar
      }
    
      override var canBecomeFirstResponder: Bool {
        return true
      }
    
      @objc private func tapped() {
        becomeFirstResponder()
      }
    }
    
    0 讨论(0)
  • 2020-12-18 07:36

    You can just ovveride inputView getter method, like explained in Apple documentation:

    - (UIView *)inputView {
        return myInputView;
    }
    - (BOOL)canBecomeFirstResponder {
        return YES;
    }
    

    Then add a gesture or a button to call becomeFirstResponder:

    - (void)showInputView:(id)sender {
         [self becomeFirstResponder];
    }
    
    0 讨论(0)
  • 2020-12-18 07:49

    UILabel + UIDatePicker -- Swift version with Done button.

    import UIKit
    
    class DatePickerLabel: UILabel {
    
        private let _inputView: UIView? = {
            let picker = UIDatePicker()
            return picker
        }()
    
        private let _inputAccessoryToolbar: UIToolbar = {
            let toolBar = UIToolbar()
            toolBar.barStyle = UIBarStyle.Default
            toolBar.translucent = true
    
            toolBar.sizeToFit()
    
            return toolBar
        }()
    
        override var inputView: UIView? {
            return _inputView
        }
    
        override var inputAccessoryView: UIView? {
            return _inputAccessoryToolbar
        }
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
    
            let doneButton = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Plain, target: self, action: #selector(doneClick))
            let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: nil, action: nil)
    
            _inputAccessoryToolbar.setItems([ spaceButton, doneButton], animated: false)
    
            let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(launchPicker))
            self.addGestureRecognizer(tapRecognizer)
        }
    
        override func canBecomeFirstResponder() -> Bool {
            return true
        }
    
        @objc private func launchPicker() {
            becomeFirstResponder()
        }
    
        @objc private func doneClick() {
            resignFirstResponder()
        }
    
    }
    
    0 讨论(0)
提交回复
热议问题