2012-02-02 9 views
74

Sto effettuando un UITextField che ha un UIPickerView come inputView. Va tutto bene, tranne il fatto che posso modificare, copiare, incollare, tagliare e selezionare il testo, e io non lo voglio. Solo il Raccoglitore dovrebbe modificare il campo di testo.Come disabilitare la modifica di UITextField ma si accetta ancora il tocco?

Ho appreso che è possibile disabilitare la modifica impostando setEnabled o setUserInteractionEnabled:NO a NO. Ok, ma il campo di testo smette di rispondere al tocco e il selettore non viene visualizzato.

Cosa posso fare per ottenerlo?

+0

Hey mi chiedevo come è stato implementato un UIPickerView come inputView? hai un campione di codice? Attualmente faccio apparire UIPickerView dal basso come un popup. Preferirei che venisse come la tastiera. Come si imposta la cornice ecc? –

risposta

103

Utilizzando il delegato campo di testo, c'è un metodo

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

Ritorno NO da questo, e ogni tentativo da parte dell'utente di modificare il testo saranno respinte.

In questo modo è possibile lasciare il campo abilitato ma impedire comunque alle persone di incollare il testo.

+4

Se vuoi ancora rispondere al tocco, rispondi a "tocca giù" e non "ritocca dentro". Altrimenti il ​​tuo evento non viene mai chiamato. – radven

+0

@NickLockwood ci sono modi in cui possiamo ancora permettere a textField di diventare il primo risponditore, ma disabilitare l'interazione dell'utente e nascondere il cursore? – onmyway133

+1

@entropy Suppongo che desideri essere in grado di selezionare il contenuto in modo che l'utente possa copiarlo? Se si sottoclasse UITextField, è possibile ignorare praticamente qualsiasi comportamento, ad es. è possibile forzare il campo a selezionare sempre tutte le volte che l'utente tocca, il che nasconderebbe effettivamente il cursore. –

0

Questa soluzione alternativa funziona. Mettere un UIView trasparente sopra il campo di testo e implementare il seguente codice:

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

Sono confuso dal motivo per cui non usi un semplice UIButton + touchUpInside trasparente e preferisco invece UIView + gesture. –

5

sarebbe più elegante per creare una sottoclasse personalizzata di UITextField che restituisce NO per tutte le chiamate a canPerformAction:withSender: (o almeno dove action è @selector(cut) o @selector(paste)), come descritto here.

Inoltre, mi piacerebbe anche implementare - (BOOL) textField: (UITextField *) textField shouldChangeCharactersInRange: (NSRange) Campo ReplacementString: (NSString *) string come da suggerimento di Nick al fine di disabilitare il testo inserendo da Bluetooth tastiere.

+0

Non posso per la vita di me capire come farlo. I metodi 'canPerformAction' e' shouldChangeCharactersInRange' della sottoclasse non vengono mai chiamati. – Nestor

17

Questa sarebbe la più semplice di tutte:

in viewDidLoad: (impostare il delegato solo per i campi di testo che non dovrebbe essere modificabile

self.textfield.delegate=self; 

e inserire questa funzione delegato:.

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

Thats it!

+17

Ciò impedisce al selettore di essere presentato e quindi non risolve il problema descritto –

+3

@MartinLockett Se si attiva il comportamento 'UIPickerView' da quel metodo delegato, funziona correttamente. –

-3

Io ho usato:

[self.textField setEnabled:NO]; 

e il suo lavoro bene

0

Fai la tua inputView essere presentate da un campo di testo nascosto che cambia anche il testo di quello presentato e disabili.

1

Per un'alternativa che gestisce l'UIPickerView e Fogli di azione, cassa ActionSheetPicker

https://github.com/TimCinel/ActionSheetPicker

E 'cocoapods abilitati. Gestisce tutti i pulsanti Annulla e Fine sul foglio di azione. Gli esempi all'interno del progetto di esempio sono fantastici. Scelgo ActionSheetStringPicker, che gestisce facilmente solo le opzioni basate su String, ma l'API è in grado di gestire la maggior parte di tutto ciò che mi viene in mente.

Originariamente ho iniziato una soluzione molto simile alla risposta segno di spunta, ma imbattuti in questo progetto e mi ha portato circa 20 minuti per ottenere le cose integrati nel mio app per l'utilizzo anche utilizzando cocopods: ActionSheetPicker (~> 0.0)

Speranza questo aiuta.

Scarica il progetto Git e guardare le seguenti classi:

  • ActionSheetPickerViewController.m
  • ActionSheetPickerCustomPickerDelegate.h

Qui è grosso modo la maggior parte del codice che ho aggiunto, più il * .h importazioni.

- (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. 
} 
+0

Al giorno d'oggi sarebbe meglio utilizzare le funzionalità integrate di questo wrapper del foglio di azioni. per esempio. UIPickerView come inputView e una barra dei pulsanti come inputAccessoryView – malhal

4

È sufficiente posizionare un UIButton esattamente su tutta UITextField senza Label-testo che rende "invisibile". Questo pulsante può ricevere e delegare tocchi al posto del campo di testo e il contenuto del campo di testo è ancora visibile.

+0

Questa soluzione ha funzionato bene per la mia situazione – WBuck

1

Ho utilizzato la soluzione fornita da MrMage. L'unica cosa che aggiungo è che dovresti abbandonare UITextView come primo risponditore, altrimenti rimani bloccato con il testo selezionato.

Ecco il mio codice 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 
    } 

} 
0

per impedire la modifica di UITextField durante l'utilizzo UIPickerView per la selezione di valori (a 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 
} 
6

Tradurre la risposta di Nick a rapida:

P/S: restituisce falso => ​​i campi di testo non possono essere immessi, modificati dalla tastiera. E 'solo possibile impostare il testo da code.EX: TextField.text = "Il mio String Qui"

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

Questo non funziona per me. Basta fare un lungo clic sul campo di testo fino a quando appare lo zoom e appare il menu di taglio/copia/incolla di iOS e posso usarlo per modificare il testo. – RowanPD

+0

rapida 4: ' func textField (_ textField: UITextField, gamma shouldChangeCharactersIn: NSRange, ReplacementString string: String) -> Bool { return false } ' – lionello

-6

Questo ha funzionato per me [textview setEditable:NO]; Le risposte di cui sopra sono overcomplicating la situazione.

+1

Il PO ha scritto "ho imparato che è possibile disattivare la modifica impostando setEnabled o setUserInteractionEnabled: NO a NO. Ok, ma il campo di testo smette di rispondere al tocco e il selettore non viene visualizzato. " La tua risposta interromperà tutti gli eventi, il che non è stato il risultato desiderato. – maninvan

+0

@Tolgab non è la soluzione correlata per questo OP! –

5

In Swift:

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

a 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 
    } 
} 
Problemi correlati