Jak wyłączyć edycję UITextField, ale nadal akceptować touch?

Robię UITextField, który ma UIPickerView jako inputView. Wszystko jest dobre, z wyjątkiem tego, że mogę edytować przez kopiowanie, wklejanie, wycinanie i zaznaczanie tekstu, a ja tego nie chcę. Tylko Selektor powinien modyfikować pole tekstowe.

Dowiedziałem się, że mogę wyłączyć edycję ustawiając setEnabled lub setUserInteractionEnabled na NO. Ok, ale pole tekstowe przestaje odpowiadać na dotyk, a picker się nie pojawia.

Co mogę zrobić, aby to osiągnąć?

Author: Luiz de Prá, 2012-02-02

14 answers

Używając delegata textfield, istnieje metoda

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

Zwróć nie z tego, a każda próba edycji tekstu przez użytkownika zostanie odrzucona.

W ten sposób możesz pozostawić pole włączone, ale nadal zapobiegać wklejaniu do niego tekstu.

 109
Author: Nick Lockwood,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-02 17:50:20

To byłoby najprostsze ze wszystkich:

In viewDidLoad: (Ustaw delegata tylko dla pól tekstowych, które nie powinny być edytowalne.

self.textfield.delegate=self;

I wstaw tę funkcję delegata:

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
return NO;
}
To wszystko!
 15
Author: Ankish Jain,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-08 12:51:38

Przetłumacz odpowiedź Nick na swift:

P / S: Return false => pola tekstowe nie mogą być wprowadzane, edytowane przy pomocy klawiatury. Może po prostu ustawić tekst za pomocą kodu.EX: textField.tekst = "mój ciąg tutaj"

override func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    return false
}
 12
Author: lee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-24 08:14:26

W Języku Swift:

func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
    questionField.resignFirstResponder();
    // Additional code here
    return false
}
 6
Author: Saranya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-20 17:06:29

Byłoby bardziej eleganckie utworzenie niestandardowej podklasy UITextField, która zwraca NO dla wszystkich wywołań do canPerformAction:withSender: (lub przynajmniej gdzie action jest @selector(cut) lub @selector(paste)), jak opisano tutaj.

Dodatkowo zaimplementowałbym - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange: (NSRange)range replacementString: (NSString *)string zgodnie z sugestią Nicka w celu wyłączenia wprowadzania tekstu z klawiatur Bluetooth.

 5
Author: MrMage,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:38

W języku 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
   }
}
 5
Author: Nadeesha Lakmal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-10 10:59:47

Po prostu umieść UIButton dokładnie na całym polu UITextField bez tekstu etykiety, co czyni go "niewidzialnym". Ten przycisk może odbierać i delegować dotknięcia zamiast pola tekstowego, a zawartość pola tekstowego jest nadal widoczna.

 4
Author: Timm Kent,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-25 22:58:03

Dla alternatywy, która obsługuje UIPickerView i arkusze akcji, checkout ActionSheetPicker

Https://github.com/TimCinel/ActionSheetPicker

To cocoapods włączone. Obsługuje wszystkie przyciski anuluj i gotowe na arkuszu akcji. Przykłady w ramach przykładowego projektu są świetne. Wybieram ActionSheetStringPicker, który z łatwością obsługuje tylko opcje oparte na ciągach, ale API może obsłużyć większość wszystkiego, co przychodzi mi do głowy.

I oryginalnie zacząłem rozwiązanie podobne do checkmarked answer, ale natknąłem się na ten projekt i zajęło mi około 20 minut, aby zintegrować rzeczy z moją aplikacją do użytku, w tym za pomocą cocopods: ActionSheetPicker (~>0.0)

Mam nadzieję, że to pomoże.

Pobierz projekt git i spójrz na następujące klasy:

  • ActionSheetPickerViewController.m
  • ActionSheetPickerCustomPickerDelegate.h

Oto mniej więcej większość kodu, który dodałem, plus *.h import.

- (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.
}
 1
Author: Nick N,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-02 04:51:26

Użyłem rozwiązania dostarczonego przez MrMage. Jedyne, co bym dodał, to powinieneś zrezygnować z UITextView jako first responder, w przeciwnym razie utkniesz z zaznaczonym tekstem.

Oto Mój kod swift:

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
Author: Leedrick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-03 02:51:28

Aby zapobiec edycji UITextField podczas korzystania z UIPickerView do wyboru wartości (w języku 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
}
 1
Author: Thiru,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-18 06:14:38

To obejście działa. Umieść przezroczysty interfejs użytkownika nad polem tekstowym i zaimplementuj następujący kod:

- (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];
}
 0
Author: cocoakomali,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-02 17:53:52

Spraw, aby Widok inputView był prezentowany przez ukryte pole tekstowe, które również zmienia tekst prezentowanego i wyłączonego.

 0
Author: Sandro Vezzali,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-25 13:17:33

Użyłem:

[self.textField setEnabled:NO];

I jego praca w porządku

 -3
Author: Chris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-26 07:22:05

To zadziałało na mnie [textview setEditable:NO]; Powyższe odpowiedzi nadmiernie komplikują sytuację.

 -6
Author: Tolgab,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-05 21:47:03