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


107

我正在做一个UITextField具有UIPickerViewas的inputView。一切都很好,除了我可以通过复制,粘贴,剪切和选择文本进行编辑,而且我不希望这样做。仅选择器应修改文本字段。

我明白了,我可以禁用通过设置编辑setEnabledsetUserInteractionEnabledNO。好的,但是TextField停止响应触摸并且选择器不显示。

我该怎么做呢?

Answers:


131

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

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

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

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


4
如果您仍想响应触摸,请响应“向下触摸”而不是“内部向上触摸”。否则,您的事件将永远不会被调用。
拉文(

@NickLockwood有什么方法我们仍然可以允许textField成为第一响应者,但是禁用用户交互并隐藏插入符号?
onmyway133

1
@entropy我假设您希望能够选择内容,以便用户可以复制它?如果您将UITextField子类化,则几乎可以覆盖任何行为-例如,您可以强制字段在用户触摸时始终选择全部,这将有效地隐藏插入符号。
尼克·洛克伍德

1
@LoryLory一样,只是对委托方法使用Swift语法。
尼克·洛克伍德

5
更准确地说,如果需要,我们可以使用“ textFieldShouldBeginEditing”
Naveen Shan

22

尼克的答案迅速翻译成:

P / S:返回false =>文本字段无法输入,无法通过键盘进行编辑。它只能通过code.EX设置文本:textField.text =“我的字符串在这里”

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

3
这对我不起作用。只需长按文本字段,直到出现缩放并出现iOS剪切/复制/粘贴菜单,我就可以使用它来更改文本。
RowanPD

2
迅捷4:`func textField(_ textField:UITextField,shouldChangeCharactersIn范围:NSRange,replacementString字符串:String)-> Bool {return false}`
lionello,

16

这将是最简单的方法:

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

self.textfield.delegate=self;

并插入此委托函数:

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

而已!


27
这会阻止选择器出现,因此无法解决所描述的问题
Martin Lockett

6
@MartinLockett如果您UIPickerView从该委托方法触发行为,则效果很好。
Albert Bori 2015年

9

迅速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
   }
}

7

这将是更优雅创建的自定义子类UITextField是回报NO所有调用canPerformAction:withSender:(或至少是action@selector(cut)@selector(paste)),如所描述这里

另外,我还将根据Nick的建议实现-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replaceString:(NSString *)string,以禁止从蓝牙键盘输入文本。


我一生无法解决。子类canPerformActionshouldChangeCharactersInRange方法从不被调用。
Nestor 2014年

7

只需将UIButton恰好放置在整个UITextField上,而无需放置Label文本即可使其“不可见”。此按钮可以接收和委派触摸而不是文本字段,并且文本字段的内容仍然可见。


7

在Swift中:

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

3

我使用了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
    }

}

1

有关处理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.
}

吊舱的更新版本在这里。 github.com/skywinder/ActionSheetPicker-3.0
Nick N

1

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

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
}

0

此替代方法有效。在文本字段上方放置一个透明的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];
}

1
我对为什么不使用简单的透明UIButton + touchUpInside感到困惑,而是选择了UIView +手势。
陈李勇


-5

我用了 :

[self.textField setEnabled:NO];

和它的工作很好


-7

这对我 [textview setEditable:NO]; 有用。上面的答案使情况变得更加复杂。


1
OP写道:“我了解到可以通过将setEnabled或setUserInteractionEnabled:NO设置为NO来禁用编辑。确定,但是TextField停止响应触摸并且选择器不显示。” 您的答案将停止所有事件,这是不希望的结果。
maninvan

@Tolgab甚至不是此OP的相关解决方案!
阿努拉格·夏尔马
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.