web-dev-qa-db-fra.com

Comment désactiver l’édition UITextField tout en acceptant le toucher?

Je crée un UITextField qui a un UIPickerView comme inputView. C'est tout bon, sauf que je peux éditer par copier, coller, couper et sélectionner du texte et que je ne le veux pas. Seul le sélecteur doit modifier le champ de texte.

J'ai appris que je pouvais désactiver l'édition en définissant setEnabled ou setUserInteractionEnabled sur NO. Ok, mais TextField cesse de répondre au toucher et le sélecteur n'apparaît pas.

Que puis-je faire pour y parvenir?

101
Luiz de Prá

En utilisant le délégué textfield, il y a une méthode

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

Renvoyez NO à partir de cette page et toute tentative de modification du texte par l'utilisateur sera rejetée.

De cette façon, vous pouvez laisser le champ activé, tout en empêchant les gens d'y coller du texte.

124
Nick Lockwood

Traduire la réponse de Nick en Swift:

P/S: Return false => les champs de texte ne peuvent pas être entrés, édités par le clavier. Ils peuvent simplement définir du texte par code.EX: textField.text = "My String Here"

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

Ce serait le plus simple de tous:

in viewDidLoad: (définissez le délégué uniquement pour les champs de texte qui ne doivent pas être modifiables.

self.textfield.delegate=self;

et insérez cette fonction de délégué:

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

C'est ça!

16
Ankish Jain

Dans 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
   }
}
7
Nadeesha Lakmal

Il serait plus élégant de créer une sous-classe personnalisée de UITextField qui retourne NO pour tous les appels à canPerformAction:withSender: (Ou au moins où action est @selector(cut) ou @selector(paste)), comme décrit ici .

En outre, je mettrais également en œuvre - (BOOL) textField: (UITextField *) textField shouldChangeCharactersInRange: (NSRange) range replacementString: (NSString *) chaîne conforme à la suggestion de Nick afin de désactiver la saisie de texte à partir de claviers Bluetooth.

7
MrMage

Dans Swift:

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

Placez simplement un UIButton exactement sur l'ensemble de UITextField sans Label-texte, ce qui le rend "invisible". Ce bouton peut recevoir et déléguer des touches au lieu du champ de texte et le contenu du champ de texte est toujours visible.

6
Timm Kent

J'ai utilisé la solution fournie par MrMage. La seule chose que j’ajouterais, c’est que vous devriez renoncer à UITextView en tant que premier répondant, sinon vous êtes coincé avec le texte sélectionné.

Voici mon code 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
    }

}
3
Leedrick

Pour une alternative qui gère les fiches UIPickerView et Action, consultez ActionSheetPicker.

https://github.com/TimCinel/ActionSheetPicker

Les cocoapodes sont activés. Il gère tous les boutons annuler et terminé de la feuille d'action. Les exemples dans l'exemple de projet sont excellents. J'ai choisi ActionSheetStringPicker, qui gère facilement uniquement les options basées sur String, mais l'API peut gérer la plupart des choses auxquelles je peux penser.

À l'origine, j'avais commencé une solution qui ressemblait beaucoup à la réponse cochée, mais je suis tombé sur ce projet et il m'a fallu environ 20 minutes pour intégrer des éléments dans mon application, notamment à l'aide de cocopods: ActionSheetPicker (~> 0.0)

J'espère que cela t'aides.

Téléchargez le projet git et examinez les classes suivantes:

  • ActionSheetPickerViewController.m
  • ActionSheetPickerCustomPickerDelegate.h

Voici à peu près la plupart du code que j'ai ajouté, plus les importations * .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.
}
1
Nick N

Pour empêcher la modification de UITextField lors de l'utilisation de UIPickerView pour la sélection de valeurs (dans 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
Thiru

Faites en sorte que votre inputView soit présenté par un champ de texte masqué qui modifie également le texte du texte présenté et désactivé.

0
Sandro Vezzali

Cette solution de contournement fonctionne. Placez un UIView transparent au-dessus du champ de texte et implémentez le code suivant:

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