如何禁用 UITextField 编辑,但仍然接受触摸?

我正在制作一个 UITextField,它的 UIPickerViewinputView是一样的。这一切都很好,除了我可以编辑复制,粘贴,剪切和选择文本,我不想要它。只有选择器应该修改文本字段。

I've learned that I can disable editing by setting setEnabled or setUserInteractionEnabled to NO. Ok, but the TextField stop responding to touching and the picker don't show up.

我能做些什么来实现它?

94507 次浏览

使用 textfield 委托,有一个方法

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string

Return NO from this, and any attempt by the user to edit the text will be rejected.

That way you can leave the field enabled but still prevent people pasting text into it.

This workaround works. Put a transparent UIView above the text field and implement the following code:

- (void)viewDidLoad
{
[super viewDidLoad];


UILongPressGestureRecognizer *press = [[UILongPressGestureRecognizer alloc]             initWithTarget:self action:@selector(longPress)];
[transparentView addGestureRecognizer:press];
[press release];
press = nil;
}


-(void)longPress
{
txtField.userInteractionEnabled = NO;
}


-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
txtField.userInteractionEnabled = YES;
}


-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[txtField becomeFirstResponder];
}

It would be more elegant to create a custom subclass of UITextField that returns NO for all calls to canPerformAction:withSender: (or at least where action is @selector(cut) or @selector(paste)), as described here.

此外,我还将实现 - (BOOL) textField: (UITextField *) textField should dChangeAttritersInRange: (NSRange) range replacementString: (NSString *) string 按照尼克的建议,为了禁用从蓝牙键盘输入文本。

这是最简单的:

在 viewDidLoad 中: (仅为不应该编辑的文本字段设置委托。

self.textfield.delegate=self;

并插入这个委托函数:

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
return NO;
}

够了!

我用:

[self.textField setEnabled:NO];

而且工作得很好

Make your inputView be presented by an hidden textfield which also change the text of the presented and disabled one.

有关处理 UIPickerView 和 ActionSheetPicker 的替代方法,请签出 ActionSheetPicker

Https://github.com/timcinel/actionsheetpicker

启用了 cocoapods。它处理操作工作表上的所有取消和完成按钮。示例项目中的示例非常棒。我选择 ActionSheetStringPicker,它可以轻松地处理基于 String 的选项,但是 API 可以处理我能想到的大部分内容。

我最初开始了一个解决方案,很像选中的答案,但无意中发现了这个项目,我花了大约20分钟的时间把东西集成到我的应用程序使用,包括使用 cocopod: ActionSheetPicker (~ > 0.0)

希望这个能帮上忙。

下载 git 项目并查看以下类:

  • ActionSheetPickerViewController.m
  • ActionSheetPickerCustomPickerDelegate.h

下面是我添加的大部分代码,加上 * . h 导入。

- (IBAction)gymTouched:(id)sender {
NSLog(@"gym touched");


[ActionSheetStringPicker showPickerWithTitle:@"Select a Gym" rows:self.locations initialSelection:self.selectedIndex target:self successAction:@selector(gymWasSelected:element:) cancelAction:@selector(actionPickerCancelled:) origin:sender];
}




- (void)actionPickerCancelled:(id)sender {
NSLog(@"Delegate has been informed that ActionSheetPicker was cancelled");
}




- (void)gymWasSelected:(NSNumber *)selectedIndex element:(id)element {
self.selectedIndex = [selectedIndex intValue];


//may have originated from textField or barButtonItem, use an IBOutlet instead of element
self.txtGym.text = [self.locations objectAtIndex:self.selectedIndex];
}




-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
return NO;  // Hide both keyboard and blinking cursor.
}

Simply place a UIButton exactly over the entire UITextField with no Label-text which makes it "invisible". This button can receive and delegate touches instead of the Textfield and the content of the TextField is still visible.

我用了法师先生提供的溶液。我要补充的唯一一点是,您应该将 UITextView 放弃作为第一响应者,否则您将无法选择所选的文本。

这是我的快速代码:

class TouchableTextView : UITextView {


override func canPerformAction(action: Selector, withSender sender: AnyObject?) -> Bool {
self.resignFirstResponder()
return false
}


override func shouldChangeTextInRange(range: UITextRange, replacementText text: String) -> Bool {
self.resignFirstResponder()
return false
}


}

为了防止在使用 UIPickerView 选择值时编辑 UITextField (在 Swift 中) :

self.txtTransDate = self.makeTextField(self.transDate, placeHolder: "Specify Date")
self.txtTransDate?.addTarget(self, action: "txtTransDateEditing:", forControlEvents: UIControlEvents.EditingDidBegin)


func makeTextField(text: String?, placeHolder: String) -> UITextField {
var textField = UITextField(frame: CGRect(x: 140, y: 0, width: 220.00, height: 40.00));
textField.placeholder = placeHolder
textField.text = text
textField.borderStyle = UITextBorderStyle.Line
textField.secureTextEntry = false;
textField.delegate = self
return textField
}




func txtTransDateEditing(sender: UITextField) {
var datePickerView:UIDatePicker = UIDatePicker()
datePickerView.datePickerMode = UIDatePickerMode.Date
sender.inputView = datePickerView
datePickerView.addTarget(self, action: Selector("datePickerValueChanged:"), forControlEvents: UIControlEvents.ValueChanged)
}


func datePickerValueChanged(sender: UIDatePicker) {
var dateformatter = NSDateFormatter()
dateformatter.dateStyle = NSDateFormatterStyle.MediumStyle
self.txtTransDate!.text = dateformatter.stringFromDate(sender.date)
}


func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool  {
self.resignFirstResponder()
return false
}

Nick的答案翻译成迅速:

返回 false = > 文本字段无法输入,由键盘编辑。它只能通过 code.EX: textField.text = “ My String Here”设置文本

override func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
return false
}

这招对我很管用 [textview setEditable:NO]; 上述答案使情况变得过于复杂。

In Swift:

func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
questionField.resignFirstResponder();
// Additional code here
return false
}

速度3 + :

class MyViewController: UIViewController, UITextFieldDelegate {


override func viewDidLoad() {
self.myTextField.delegate     = self
}


func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
if textField == myTextField {
// code which you want to execute when the user touch myTextField
}
return false
}
}

Not completely sure about how hacky this is but the only thing that did the trick in my case was adding a target action and calling endEditing. Since my picker controls my UITextField.text value, I could dismiss the keyboard as soon as the user clicks on the field. Here's some code:

uiTextFieldVariable.addTarget(self, action: #selector(dismissKeyboard), for: .editingDidBegin)


@objc private func dismissKeyboard() {
endEditing(true)
}

如果您准备创建自定义文本域,那么您可以使用来自另一个 stackoverflow 问题的答案。 Https://stackoverflow.com/a/42698689/9369035

只要像上面的答案那样覆盖这三个方法就足够了。至少到目前为止我测试过了。

如果您使用的是 强 > IQKeyboardManagerSwift豆荚,那么使用 textField.enableMode = .disabled

否则,如果您使用的是 强 > RxSwift & RxCocoa豆荚

textField.rx.controlEvent(.editingDidBegin)
.subscribe(onNext: {
[weak self] _ in let _ = self?.textField.endEditing(true)
}).disposed(by: bag)

else use delegate method of TextFiled

 func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
return false
}