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

发布于 2025-01-02 02:23:00 字数 311 浏览 3 评论 0原文

我正在制作一个 UITextField,它有一个 UIPickerView 作为 inputView。一切都很好,除了我可以通过复制、粘贴、剪切和选择文本进行编辑,但我不想要它。只有选取器才能修改文本字段。

我了解到,可以通过将 setEnabledsetUserInteractionEnabled 设置为 NO 来禁用编辑。好的,但是 TextField 停止响应触摸并且选择器不显示。

我可以做什么来实现它?

I'm making a UITextField that has a UIPickerView as inputView. Its all good, except that I can edit by copy, paste, cut and select text, and I don't want it. Only the Picker should modify text field.

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.

What can I do to achieve it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(17

海风掠过北极光 2025-01-09 02:23:00

使用文本字段委托,有一个方法

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

Return NO,并且用户编辑文本的任何尝试都将被拒绝。

这样,您可以使该字段保持启用状态,但仍会阻止人们将文本粘贴到其中。

Using the textfield delegate, there's a method

- (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.

国产ˉ祖宗 2025-01-09 02:23:00

Nick的答案翻译成swift:

P/S: Return false =>文本字段无法通过键盘输入、编辑。它只能通过代码设置文本。例如:textField.text = "My String Here"

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

Translate the answer of Nick to swift:

P/S: Return false => the textfields cannot input, edit by the keyboard. It just can set text by code.EX: textField.text = "My String Here"

override func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    return false
}
春花秋月 2025-01-09 02:23:00

这将是最简单的:

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

self.textfield.delegate=self;

并插入此委托函数:

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

就是这样!

This would be the simplest of all:

in viewDidLoad:(set the delegate only for textfields which should not be editable.

self.textfield.delegate=self;

and insert this delegate function:

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

Thats it!

雨轻弹 2025-01-09 02:23:00

在 swift 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
   }
}

In swift 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
   }
}
失与倦" 2025-01-09 02:23:00

只需将 UIButton 恰好放置在整个 UITextField 上,没有标签文本,这会使其“不可见”。此按钮可以代替 Textfield 接收和委托触摸,并且 TextField 的内容仍然可见。

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.

寒冷纷飞旳雪 2025-01-09 02:23:00

创建 UITextField 的自定义子类会更加优雅,该子类对所有对 canPerformAction:withSender: 的调用都返回 NO (或者至少在 code>action@selector(cut)@selector(paste)),如所述此处

此外,我还实施
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)范围 replacementString:(NSString *)string
根据尼克的建议,以禁用从蓝牙键盘输入文本。

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.

In addition, I'd also implement
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
as per Nick's suggestion in order to disable inputting text from Bluetooth keyboards.

蹲墙角沉默 2025-01-09 02:23:00

在斯威夫特:

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

In Swift:

func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
    questionField.resignFirstResponder();
    // Additional code here
    return false
}
朕就是辣么酷 2025-01-09 02:23:00

我使用了MrMage提供的解决方案。我唯一要补充的是,您应该辞去 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
    }

}

I used the solution provided by MrMage. The only thing I'd add is you should resign the UITextView as first responder, otherwise you're stuck with the text selected.

Here's my swift code:

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
    }

}
魔法少女 2025-01-09 02:23:00

为了防止在使用 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
}

To prevent editing of UITextField while using UIPickerView for selecting values(in 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
}
赠佳期 2025-01-09 02:23:00

对于处理 UIPickerView 和操作表的替代方案,请查看 ActionSheetPicker

https://github.com/TimCinel/ActionSheetPicker

已启用 cocoapods。它处理操作表上的所有取消和完成按钮。示例项目中的示例非常好。我选择 ActionSheetStringPicker,它可以轻松处理基于字符串的选项,但 API 可以处理我能想到的大多数内容。

我最初启动了一个与选中的答案非常相似的解决方案,但偶然发现了这个项目,并花了我大约 20 分钟将东西集成到我的应用程序中以供使用,包括使用 cocopods: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.
}

For an alternative that handles the UIPickerView and Action Sheets, checkout ActionSheetPicker

https://github.com/TimCinel/ActionSheetPicker

It's cocoapods enabled. It handles all of the cancel and done buttons on the Action Sheet. The examples within the sample project are great. I choose the ActionSheetStringPicker, which handles easily just String based options, but the API can handle most anything that I can think of.

I originally started a solution much like the checkmarked answer, but stumbled onto this project and took me roughly 20 minutes to get things integrated into my app for usage including using cocopods: ActionSheetPicker (~> 0.0)

Hope this helps.

Download the git project and look at the following classes:

  • ActionSheetPickerViewController.m
  • ActionSheetPickerCustomPickerDelegate.h

Here is roughly most of the code that I added, plus the *.h imports.

- (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.
}
风为裳 2025-01-09 02:23:00

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

只需覆盖上面答案中的这三个方法就足够了。至少就我测试而言。

if you are ready to create your custom textfield then you can just use this answer from another stackoverflow question.
https://stackoverflow.com/a/42698689/9369035

just override those three method as in above answer and that is enough. at least so far as I tested.

方圜几里 2025-01-09 02:23:00

此解决方法有效。在文本字段上方放置一个透明的 UIView 并实现以下代码:

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

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];
}
傲娇萝莉攻 2025-01-09 02:23:00

让您的 inputView 由隐藏的文本字段呈现,这也会更改呈现的和禁用的文本。

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

梦言归人 2025-01-09 02:23:00

不完全确定这有多黑,但在我的例子中唯一能做到这一点的是添加目标操作并调用 endEditing。由于我的选择器控制我的 UITextField.text 值,因此一旦用户单击该字段,我就可以关闭键盘。这是一些代码:

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

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

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)
}
奈何桥上唱咆哮 2025-01-09 02:23:00

如果您使用 IQKeyboardManagerSwift pod,则使用textField.enableMode = .disabled

else 如果您使用 RxSwift & RxCocoa pods 然后

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

使用 textFiled 的委托方法

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

If you are using IQKeyboardManagerSwift pod then use textField.enableMode = .disabled

else If you are using RxSwift & RxCocoa pods then

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
 }
当爱已成负担 2025-01-09 02:23:00

我用过:

[self.textField setEnabled:NO];

而且效果很好

I used :

[self.textField setEnabled:NO];

and its work fine

负佳期 2025-01-09 02:23:00

这对我有用
[textview setEditable:NO];
上述答案使情况过于复杂化。

This worked for me
[textview setEditable:NO];
The above answers are overcomplicating the situation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文