Wie deaktiviere ich die UITextField-Bearbeitung, akzeptiere aber trotzdem Berührungen?

106

Ich mache ein UITextField, das ein UIPickerViewas hat inputView. Es ist alles gut, außer dass ich Text kopieren, einfügen, ausschneiden und auswählen kann und es nicht will. Nur die Auswahl sollte das Textfeld ändern.

Ich habe gelernt, dass ich die Bearbeitung durch Einstellen setEnabledoder setUserInteractionEnabledauf deaktivieren kann NO. Ok, aber das TextField reagiert nicht mehr auf Berührungen und der Picker wird nicht angezeigt.

Was kann ich tun, um dies zu erreichen?

Luiz de Prá
quelle

Antworten:

131

Bei Verwendung des Textfelddelegaten gibt es eine Methode

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

Geben Sie NO zurück, und jeder Versuch des Benutzers, den Text zu bearbeiten, wird abgelehnt.

Auf diese Weise können Sie das Feld aktiviert lassen, aber dennoch verhindern, dass Personen Text in das Feld einfügen.

Nick Lockwood
quelle
4
Wenn Sie dennoch auf Berührungen reagieren möchten, antworten Sie auf "Aufsetzen" und nicht auf "Aufsetzen im Inneren". Andernfalls wird Ihre Veranstaltung nie aufgerufen.
Radven
@NickLockwood Gibt es Möglichkeiten, wie wir weiterhin zulassen können, dass textField der Ersthelfer wird, aber die Benutzerinteraktion deaktivieren und das Caret ausblenden?
onmyway133
1
@entropy Ich gehe davon aus, dass Sie den Inhalt auswählen möchten, damit der Benutzer ihn kopieren kann. Wenn Sie UITextField unterordnen, können Sie so ziemlich jedes Verhalten überschreiben - z. B. können Sie das Feld zwingen, immer alle auszuwählen, wenn der Benutzer es berührt, wodurch das Caret effektiv ausgeblendet wird.
Nick Lockwood
1
@LoryLory es ist das gleiche, verwenden Sie stattdessen einfach die Swift-Syntax für die Delegate-Methode.
Nick Lockwood
5
Genauer gesagt können wir bei Bedarf "textFieldShouldBeginEditing" verwenden
Naveen Shan
21

Übersetzen Sie die Antwort von Nick auf schnell:

P / S: Rückgabe false => Die Textfelder können nicht eingegeben und über die Tastatur bearbeitet werden. Es kann nur Text durch code.EX setzen: textField.text = "My String Here"

override func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    return false
}
Lee
quelle
3
Das funktioniert bei mir nicht. Klicken Sie einfach lange auf das Textfeld, bis der Zoom angezeigt wird und das iOS-Menü zum Ausschneiden / Kopieren / Einfügen angezeigt wird. Damit kann ich den Text ändern.
RowanPD
2
swift 4: `func textField (_ textField: UITextField, shouldChangeCharactersIn Bereich: NSRange, replaceString string: String) -> Bool {return false}`
Lionello
16

Dies wäre die einfachste von allen:

in viewDidLoad: (Legen Sie den Delegaten nur für Textfelder fest, die nicht bearbeitet werden dürfen.

self.textfield.delegate=self;

und fügen Sie diese Delegatenfunktion ein:

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

Das ist es!

Ankish Jain
quelle
27
Dies verhindert, dass der Picker präsentiert wird, und behebt somit nicht das beschriebene Problem
Martin Lockett
6
@MartinLockett Wenn Sie das UIPickerViewVerhalten dieser Delegatmethode auslösen , funktioniert es gut.
Albert Bori
9

In schnellem 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
   }
}
Nadeesha Lakmal
quelle
7

Es wäre eleganter, eine benutzerdefinierte Unterklasse zu erstellen UITextField, die NOfür alle Aufrufe von canPerformAction:withSender:(oder zumindest wo actionist @selector(cut)oder @selector(paste)) zurückgegeben wird, wie hier beschrieben .

Darüber hinaus würde ich auch implementieren - (BOOL) textField: (UITextField *) textField shouldChangeCharactersInRange: (NSRange) Bereich ErsatzString: (NSString *) Zeichenfolge gemäß Nicks Vorschlag, um die Eingabe von Text über Bluetooth-Tastaturen zu deaktivieren.

MrMage
quelle
Ich kann nicht für mein Leben herausfinden, wie das geht. Die Unterklassen canPerformActionund shouldChangeCharactersInRangeMethoden werden niemals aufgerufen.
Nestor
7

Platzieren Sie einfach einen UIButton genau über dem gesamten UITextField ohne Label-Text, wodurch es "unsichtbar" wird. Diese Schaltfläche kann Berührungen anstelle des Textfelds empfangen und delegieren, und der Inhalt des Textfelds ist weiterhin sichtbar.

Timm Kent
quelle
7

In Swift:

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

Ich habe die von MrMage bereitgestellte Lösung verwendet. Das einzige, was ich hinzufügen möchte, ist, dass Sie UITextView als Ersthelfer zurücktreten sollten, da Sie sonst mit dem ausgewählten Text nicht weiterkommen.

Hier ist mein schneller 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
    }

}
Leedrick
quelle
1

Eine Alternative für UIPickerView und Action Sheets finden Sie unter ActionSheetPicker

https://github.com/TimCinel/ActionSheetPicker

Es sind Cocoapods aktiviert. Es behandelt alle Schaltflächen zum Abbrechen und Fertigstellen im Aktionsblatt. Die Beispiele innerhalb des Beispielprojekts sind großartig. Ich wähle den ActionSheetStringPicker, der einfach nur auf Zeichenfolgen basierende Optionen verarbeitet, aber die API kann fast alles verarbeiten, was mir einfällt.

Ich habe ursprünglich eine Lösung gestartet, die der mit einem Häkchen versehenen Antwort ähnelt, bin jedoch auf dieses Projekt gestoßen und habe ungefähr 20 Minuten gebraucht, um Dinge für die Verwendung in meine App zu integrieren, einschließlich der Verwendung von Cocopods: ActionSheetPicker (~> 0.0)

Hoffe das hilft.

Laden Sie das Git-Projekt herunter und sehen Sie sich die folgenden Klassen an:

  • ActionSheetPickerViewController.m
  • ActionSheetPickerCustomPickerDelegate.h

Hier ist ungefähr der größte Teil des Codes, den ich hinzugefügt habe, sowie die * .h-Importe.

- (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.
}
Nick N.
quelle
Eine aktualisierte Version des Pods finden Sie hier. github.com/skywinder/ActionSheetPicker-3.0
Nick N
1

So verhindern Sie die Bearbeitung von UITextField, während Sie UIPickerView zum Auswählen von Werten verwenden (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
}
Thiru
quelle
0

Diese Problemumgehung funktioniert. Platzieren Sie eine transparente UIView über dem Textfeld und implementieren Sie den folgenden 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];
}
Cocoakomali
quelle
1
Ich bin verwirrt darüber, warum Sie kein einfaches transparentes UIButton + touchUpInside verwenden, und habe mich stattdessen für UIView + Geste entschieden.
Chen Li Yong
0

Stellen Sie sicher, dass Ihre Eingabeansicht durch ein verstecktes Textfeld dargestellt wird, das auch den Text des dargestellten und deaktivierten Textfelds ändert.

Sandro Vezzali
quelle
-5

Ich benutzte :

[self.textField setEnabled:NO];

und seine Arbeit gut

Chris
quelle
-7

Das hat bei mir funktioniert [textview setEditable:NO]; Die obigen Antworten machen die Situation zu kompliziert.

Tolgab
quelle
1
Das OP schrieb: "Ich habe gelernt, dass ich die Bearbeitung deaktivieren kann, indem ich setEnabled oder setUserInteractionEnabled: NO auf NO setze. Ok, aber das TextField reagiert nicht mehr auf Berührungen und die Auswahl wird nicht angezeigt." Ihre Antwort stoppt alle Ereignisse, die nicht erwünscht waren.
Maninvan
@ Tolgab nicht die gerade verwandte Lösung für dieses OP!
Anurag Sharma