Làm cách nào để tắt chỉnh sửa UITextField nhưng vẫn chấp nhận cảm ứng?


107

Tôi đang tạo ra một UITextFieldcái có UIPickerViewnhư inputView. Tất cả đều tốt, ngoại trừ việc tôi có thể chỉnh sửa bằng cách sao chép, dán, cắt và chọn văn bản, và tôi không muốn điều đó. Chỉ Bộ chọn mới nên sửa đổi trường văn bản.

Tôi đã biết rằng tôi có thể tắt chỉnh sửa bằng cách đặt setEnabledhoặc setUserInteractionEnabledđể NO. Được, nhưng Trường văn bản ngừng phản hồi khi chạm và bộ chọn không hiển thị.

Tôi có thể làm gì để đạt được nó?

Câu trả lời:


131

Sử dụng đại biểu trường văn bản, có một phương pháp

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

Trả lại KHÔNG từ điều này, và bất kỳ nỗ lực nào của người dùng để chỉnh sửa văn bản sẽ bị từ chối.

Bằng cách đó, bạn có thể để trường được bật nhưng vẫn ngăn mọi người dán văn bản vào đó.


4
Nếu bạn vẫn muốn phản hồi khi chạm vào, hãy trả lời "chạm xuống" chứ không phải "chạm vào bên trong". Nếu không, sự kiện của bạn sẽ không bao giờ được gọi.
radven

@NickLockwood có bất kỳ cách nào mà chúng tôi vẫn có thể cho phép textField trở thành người phản hồi đầu tiên, nhưng vô hiệu hóa tương tác của người dùng và ẩn dấu mũ không?
onmyway133

1
@entropy Tôi giả sử bạn muốn có thể chọn nội dung để người dùng có thể sao chép nó? Nếu bạn phân lớp UITextField, bạn có thể ghi đè lên khá nhiều hành vi - ví dụ: bạn có thể buộc trường luôn chọn tất cả bất cứ khi nào người dùng chạm vào, điều này sẽ ẩn dấu mũ một cách hiệu quả.
Nick Lockwood

1
@LoryLory cũng vậy, thay vào đó chỉ sử dụng cú pháp Swift cho phương thức ủy nhiệm.
Nick Lockwood

5
Chính xác hơn, chúng tôi có thể sử dụng "textFieldShouldBeginE Chỉnh sửa" nếu cần
Naveen Shan

22

Dịch nhanh câu trả lời của Nick :

P / S: Trả về false => các trường văn bản không thể nhập liệu, chỉnh sửa bằng bàn phím. Nó chỉ có thể đặt văn bản bằng code.EX: textField.text = "Chuỗi của tôi ở đây"

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

3
Điều này không hiệu quả với tôi. Chỉ cần nhấp và giữ trường văn bản cho đến khi thu phóng xuất hiện và menu cắt / sao chép / dán iOS xuất hiện và tôi có thể sử dụng thao tác đó để thay đổi văn bản.
RowanPD

2
nhanh chóng 4: `func TextField (_ TextField: UITextField, phạm vi shouldChangeCharactersIn: NSRange, replacementString chuỗi: String) -> Bool {return false}`
lionello

16

Đây là cách đơn giản nhất:

trong viewDidLoad: (chỉ đặt ủy quyền cho các trường văn bản không thể chỉnh sửa được.

self.textfield.delegate=self;

và chèn hàm đại biểu này:

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

Đó là nó!


27
Ngăn chặn này bảng chọn từ được trình bày và như vậy không giải quyết vấn đề được mô tả
Martin Lockett

6
@MartinLockett Nếu bạn kích hoạt UIPickerViewhành vi từ phương thức ủy quyền đó, nó hoạt động tốt.
Albert Bori

9

Trong 3+ nhanh chóng:

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

Nó sẽ là tao nhã hơn để tạo ra một lớp con tùy chỉnh của UITextFieldlợi nhuận mà NOcho tất cả các cuộc gọi đến canPerformAction:withSender:(hoặc ít nhất là nơi action@selector(cut)hay @selector(paste)), như mô tả ở đây .

Ngoài ra, tôi cũng sẽ triển khai chuỗi - (BOOL) textField: (UITextField *) textField shouldChangeCharactersInRange: (NSRange) range ReplaceString: (NSString *) theo gợi ý của Nick để tắt tính năng nhập văn bản từ bàn phím Bluetooth.


Cả đời tôi không thể tìm ra cách làm điều đó. Các phương thức canPerformActionvà lớp con shouldChangeCharactersInRangekhông bao giờ được gọi.
Nestor

7

Chỉ cần đặt chính xác một UIButton trên toàn bộ UITextField mà không có văn bản Nhãn nào làm cho nó "vô hình". Nút này có thể nhận và ủy quyền các lần chạm thay vì Trường văn bản và nội dung của Trường văn bản vẫn hiển thị.


7

Trong Swift:

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

3

Tôi đã sử dụng giải pháp do MrMage cung cấp. Điều duy nhất tôi muốn thêm là bạn nên từ chức UITextView làm người phản hồi đầu tiên, nếu không, bạn bị mắc kẹt với văn bản đã chọn.

Đây là mã nhanh của tôi:

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

Để có giải pháp thay thế xử lý UIPickerView và Trang tính hành động, hãy xem ActionSheetPicker

https://github.com/TimCinel/ActionSheetPicker

Nó đã được kích hoạt cocoapods. Nó xử lý tất cả các nút hủy và hoàn tất trên Bảng hành động. Các ví dụ trong dự án mẫu là rất tốt. Tôi chọn ActionSheetStringPicker, dễ dàng xử lý các tùy chọn chỉ dựa trên Chuỗi, nhưng API có thể xử lý hầu hết mọi thứ mà tôi có thể nghĩ đến.

Ban đầu tôi bắt đầu một giải pháp giống như câu trả lời được đánh dấu kiểm, nhưng tình cờ gặp dự án này và tôi mất khoảng 20 phút để tích hợp mọi thứ vào ứng dụng của mình để sử dụng, bao gồm cả việc sử dụng cocopods: ActionSheetPicker (~> 0.0)

Hi vọng điêu nay co ich.

Tải xuống dự án git và xem các lớp sau:

  • ActionSheetPickerViewController.m
  • ActionSheetPickerCustomPickerDelegate.h

Đây gần như là hầu hết các mã mà tôi đã thêm, cộng với các lần nhập * .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.
}

Phiên bản cập nhật của pod có ở đây. github.com/skywinder/ActionSheetPicker-3.0
Nick N

1

Để ngăn chỉnh sửa UITextField trong khi sử dụng UIPickerView để chọn giá trị (trong 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
}

0

Cách giải quyết này hoạt động. Đặt UIView trong suốt phía trên trường văn bản và triển khai mã sau:

- (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
Tôi bối rối không hiểu tại sao bạn không sử dụng UIButton + touchUpInside trong suốt đơn giản và chọn cử chỉ UIView + để thay thế.
Chen Li Yong

0

Làm cho inputView của bạn được trình bày bằng một trường văn bản ẩn, trường này cũng thay đổi văn bản của trường được trình bày và bị vô hiệu hóa.


-5

Tôi đã sử dụng:

[self.textField setEnabled:NO];

và nó hoạt động tốt


-7

Điều này làm việc cho tôi [textview setEditable:NO]; Các câu trả lời ở trên đang làm phức tạp tình hình.


1
OP đã viết "Tôi biết được rằng tôi có thể tắt chỉnh sửa bằng cách đặt setEnabled hoặc setUserInteractionEnabled: KHÔNG thành KHÔNG. Ok, nhưng TextField ngừng phản hồi khi chạm vào và bộ chọn không hiển thị." Câu trả lời của bạn sẽ dừng tất cả các sự kiện, kết quả không mong muốn.
maninvan

@Tolgab thậm chí không phải là giải pháp liên quan cho OP này!
Anurag Sharma
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.