UIBUTTON和uipickerview

时间:2011-06-21 18:04:56

标签: iphone uibutton uipickerview

我想在用户点击按钮时显示选择器 我将UIButton子类化并更改了它的inputview以便它是可写的。

我点了这个链接http://nomtek.com/tips-for-developers/working-with-pickers/

我点击按钮,没有任何反应。如果我将输入视图从按钮更改为UITextField,它可以很好地工作。有什么想法吗? 谢谢 萨罗

3 个答案:

答案 0 :(得分:4)

1)创建UIButton的子类

·H

#import <UIKit/UIKit.h>

@interface UIButtonAsFirstResponder : UIButton

@property (strong, nonatomic) UIView *inputView;
@property (strong, nonatomic) UIView *inputAccessoryView;

@end

的.m

#import "UIButtonAsFirstResponder.h"

@implementation UIButtonAsFirstResponder

- (BOOL) canBecomeFirstResponder
{
    return YES;
}

@end

2)在视图控制器中设置inputView(如果需要inputAccessoryView)(选择器或任何其他自定义视图)

3)在视图控制器中为您的按钮创建IBAction

- (IBAction)becom:(id)sender {
    [sender becomeFirstResponder];
}

如果您想删除键盘,请按下按钮:

[button resignFirstResponder];

或在视图控制器中:

[self.view endEditing:YES];

答案 1 :(得分:2)

这就是我在Swift 3中的做法(覆盖属性的规则与Objective-C不同)。

我想要一个显示日期的按钮,并在按钮点击时从屏幕底部显示日期选择器,以允许用户编辑显示的日期。使用固定在目标按钮上的弹出窗口相对容易,但我的应用程序仅限iPhone(而不是iPad),因此UITextField-inputView模式看起来更好(在AppStore应用程序上使用,您自担风险违反人类接口指南)。

按钮子类:

class EditableButton: UIButton {

    // This holds the assigned input view (superclass property is readonly)
    private var customInputView: UIView?

    // We override the superclass property as computed, and actually 
    // store into customInputView: 
    override var inputView: UIView? {
        get {
            return customInputView
        }
        set (newValue) {
            customInputView = newValue
        }
    }

    // Must be able to become first responder in order to 
    // get input view to be displayed:
    override var canBecomeFirstResponder: Bool {
        return true
    }

    // Setup becoming first responder on tap:
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        self.addTarget(self, action: #selector(EditableButton.tap(_:)), for: .touchDown)
        // (Not sure if this creates a retain cycle; must investigate)
    }

    @IBAction func tap(_ sender: UIButton) {
        self.becomeFirstResponder()
    }
} 

查看控制器代码:

class ViewController: UIViewController {

    // Set the appropriate subclass in the storyboard too!
    @IBOutlet weak var todayButton: EditableButton!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.

        let datePicker = UIDatePicker()
        datePicker.datePickerMode = .date
        todayButton.inputView = datePicker

        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd"
        todayButton.setTitle(dateFormatter.string(from: Date()), for: .normal)

        // Also hook an a target/action to the date picker's 
        // valueChanged event, to get notified of the user's input
        datePicker.addTarget(self, action: #selector(ViewController.changeDate(_:)), for: .valueChanged)
    }

    @IBAction func changeDate(_ sender: UIDatePicker) {
        // (update button title with formatted date)
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd"
        todayButton.setTitle(dateFormatter.string(from: sender.date), for: .normal)  

        // Dismiss picker:
        todayButton.resignFirstResponder()
    }
}

注意: 为简单起见,只要您指定日期-I.e.,只要您滚动任何轮子,此代码就会关闭日期选择器。这可能不是您想要的:通常,用户一次指定一个组件的日期(年,月等)。此实现不允许用户在解除日期选择器之前完成指定所有日期组件。

理想情况下,您可以添加UIToolbar作为输入附件视图,并使用“完成”按钮来取消输入视图(即,使按钮重新签名第一响应者)。这需要进一步修改UIButton子类(也适用于inputAccessoryView),但应该是可行的。

编辑:我可以确认输入附件视图也可以以与输入视图完全相同的方式附加到自定义UIButton子类:

private var customInputAccessoryView: UIView?

override var inputAccessoryView: UIView? {
    get {
        return customInputAccessoryView
    }
    set (newValue) {
        customInputAccessoryView = newValue
    }
}

现在,我这样设置:

let datePicker = UIDatePicker()
datePicker.datePickerMode = .date
todayButton.inputView = datePicker

let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
todayButton.setTitle(dateFormatter.string(from: Date()), for: .normal)

datePicker.addTarget(self, action: #selector(ViewController.changeDate(_:)), for: .valueChanged)

let dateToolbar = UIToolbar(frame: CGRect.zero)
dateToolbar.barStyle = .default

let dateDoneButton = UIBarButtonItem(
        barButtonSystemItem: .done,
        target: self,
        action: #selector(ViewController.dateDone(_:)))
let dateSpacer = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)

dateToolbar.items = [dateSpacer, dateDoneButton]
dateToolbar.sizeToFit()
todayButton.inputAccessoryView = dateToolbar

并采取两个单独的行动:

@IBAction func changeDate(_ sender: UIDatePicker) {
    // Update button title in real time:
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "yyyy-MM-dd"
    todayButton.setTitle(dateFormatter.string(from: sender.date), for: .normal)
}

@IBAction func dateDone(_ sender: UIBarButtonItem) {
    // ...but dismiss picker only on 'Done': 
    todayButton.resignFirstResponder()
}

同样,当视图控制器弹出导航时,我的自定义按钮子类的deinit()方法会被调用,因此UIButton不再(?)保留它的目标,或者Swift运行时比我想象的要聪明......

更新:我整理了一个Xcode project demonstrating this custom button(Github存储库)。修改它以使用自定义UIPickerView(而不是UIDatePicker)应该非常简单。什么是立即明显(至少对我而言)是如何使用键盘作为输入视图。

答案 2 :(得分:-3)

inputView属性只是UITextFieldUITextView而非UIButton的一部分。

   @property (readwrite, retain) UIView *inputView;

虽然您可以使用UIButton实现相同的目标。

创建一个UIButton对象,然后设置操作方法,并在UIButton的操作方法中将您的选择器视图添加到按钮的父视图中。

应该是那样的。

-(void) buttonClicked:(id) sender
{
    [self.view addSubview:myPickerView];
}