我会使用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
答案 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()
}
}