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?
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.
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
}
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!
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
}
}
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.
Dans Swift:
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
questionField.resignFirstResponder();
// Additional code here
return false
}
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.
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
}
}
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:
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.
}
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
}
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é.
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];
}