UILabel不显示inputView

时间:2012-10-11 21:54:52

标签: objective-c ios xcode

我会使用UILabel来允许用户使用UIDatePicker选择日期。

为此,我创建了一个UILabel子类,覆盖了inputView和inputAccessoryView属性,使它们可写;我还实现了 - (BOOL)canBecomeFirstResponder和 - (BOOL)isUserInteractionEnabled方法,两者都返回YES。 然后我将一个UIDatePIcker实例分配给inputView属性。

此时我的期望是,当点击标签时,应该出现UIDatePicker,但没有任何反应。

任何帮助?

这是代码:

YPInteractiveUILabel.h

@interface YPInteractiveUILabel : UILabel
    @property (readwrite) UIView *inputView;
    @property (readwrite) UIView *inputAccessoryView;

- (BOOL) canBecomeFirstResponder;
- (BOOL) isUserInteractionEnabled;
@end


YPInteractiveUILabel.h

#import "YPInteractiveUILabel.h"

@implementation YPInteractiveUILabel

- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];

    if (self)
    {
        UIDatePicker *datePicker = [[UIDatePicker alloc] init];
        [self  setInputView:datePicker];
    }

    return self;
}

- (BOOL)isUserInteractionEnabled
{
    return YES;
}

- (BOOL)canBecomeFirstResponder
{
    return YES;
}

@end

7 个答案:

答案 0 :(得分:8)

UILabel + UIDatePicker - 带有完成按钮的Swift版本。

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()
    }

}

答案 1 :(得分:4)

这样的事情怎么样?而不是对标签进行子类化,只需向其添加手势识别器,并在点击识别器的处理程序中调出选择器。在选择器的操作方法中,填充标签并关闭选择器。这个例子有效,但你可能想添加一些动画来使它看起来更好:

- (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];
}

答案 2 :(得分:4)

你可以直接使用inputView getter方法,如Apple documentation中所述:

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

然后添加一个手势或按钮来调用becomeFirstResponder:

- (void)showInputView:(id)sender {
     [self becomeFirstResponder];
}

答案 3 :(得分:3)

感谢这些建议(尤其是NeverBe的评论和rdelmar提出的答案)我在代码中发现了问题。 简而言之,为了显示输入标签,需要在用户点击标签时调用becomeFirstResponder方法。

更正UILabel子类实现后(头文件保持不变):

@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

答案 4 :(得分:0)

我知道这是一个老问题,但这可能对某人有用。

还有另一种方法可以解决这个问题 - 没有必要用手势识别器来复杂化......

<强> 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

请注意,您还应设置delegate,如果是自定义UIPicker,还应设置dataSource ...

答案 5 :(得分:0)

以下是在{Swift 4

中显示PickerView的{​​{1}}
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()
  }
}

答案 6 :(得分:0)

这是@ dmitriy-kirakosyan的代码片段,已更新为Swift 5

class DatePickerLabel: UILabel {

    private let _inputView: UIView? = {
        let picker = UIDatePicker()
        return picker
    }()

    private let _inputAccessoryToolbar: UIToolbar = {
        let toolBar = UIToolbar()
        toolBar.barStyle = UIBarStyle.default
        toolBar.isTranslucent = 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: UIBarButtonItem.Style.plain, target: self, action: #selector(doneClick))
        let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: nil, action: nil)

        _inputAccessoryToolbar.setItems([ spaceButton, doneButton], animated: false)

        let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(launchPicker))
        self.addGestureRecognizer(tapRecognizer)
    }

    override var canBecomeFirstResponder: Bool {
        return true
    }

    @objc private func launchPicker() {
        becomeFirstResponder()
    }

    @objc private func doneClick() {
        resignFirstResponder()
    }

}