Come eliminare la tastiera per UITextView con il tasto Invio?


382

Nella libreria di IB, l'introduzione ci dice che quando returnsi preme il tasto, la tastiera per UITextViewscompare. Ma in realtà la returnchiave può agire solo come '\ n'.

Posso aggiungere un pulsante e usare [txtView resignFirstResponder]per nascondere la tastiera.

Ma c'è un modo per aggiungere l'azione per il returntasto della tastiera in modo che non sia necessario aggiungere UIButton?


Segui le istruzioni su questo post del blog: iphonedevelopertips.com/cocoa/…
ManojN,

Risposte:


354

UITextViewnon ha alcun metodo che verrà chiamato quando l'utente preme il tasto invio. Se si desidera che l'utente sia in grado di aggiungere solo una riga di testo, utilizzare a UITextField. Colpire il ritorno e nascondere la tastiera per a UITextViewnon segue le linee guida dell'interfaccia.

Anche in questo caso, se si desidera eseguire questa operazione, implementare il textView:shouldChangeTextInRange:replacementText:metodo UITextViewDelegatee verificare che sia il testo di sostituzione\n nascosto, nascondere la tastiera.

Potrebbero esserci altri modi, ma non ne sono a conoscenza.


1
Grazie e il metodo funziona bene. Il motivo per utilizzare UITextView è che può contenere testo su più righe. E ora lo sto usando come una finestra di messaggio.
Chilly Zhong

28
È abbastanza facile cambiare la chiave di ritorno in "fatto" usando uno [textField setReturnKeyType: UIReturnKeyDone];o usando il generatore di interfaccia
Casebash,

9
Bene, ora capisco che il modo in cui Apple finisce con un campo di testo multilinea è aggiungere fatto alla barra dei menu
Casebash,

8
Questo non è un buon modo per risolverlo perché stai limitando l'utente a utilizzare Invio per uscire dalla tastiera. Probabilmente il modo migliore è l'aggiunta di un pulsante che esegue il metodo resignFirstResponder.
Ele

5
@Casebash. Sembra che l'impostazione della chiave di ritorno su "done" non risolva il problema in Xcode 6.4, Swift 2.0. Ho impostato la chiave utilizzando IB.
MB_iOSDeveloper

505

Ho pensato di pubblicare lo snippet qui:

Assicurati di dichiarare il supporto per il UITextViewDelegateprotocollo.

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {

    if([text isEqualToString:@"\n"]) {
        [textView resignFirstResponder];
        return NO;
    }

    return YES;
}

Aggiornamento di Swift 4.0:

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    if text == "\n" {
        textView.resignFirstResponder()
        return false
    }
    return true
}

75
Il problema è che questo non è davvero un modo per rilevare che l'utente ha toccato il tasto Invio . L'utente potrebbe incollare un carattere di ritorno nel campo di testo e otterrai lo stesso messaggio delegato. Fondamentalmente stai abusando della visualizzazione del testo. Il modo di chiudere la tastiera è (1) di non farlo affatto (come quando si compone un messaggio nell'app Mail) o (2) di avere un pulsante Fatto altrove nell'interfaccia (come nell'app Note). Ad esempio, è possibile collegare alla tastiera un pulsante come una vista accessoria.
matt

@ Sam V quel frammento era un uomo forte. per me funziona. grazie un sacco uomo. C'è qualche frammento per la dissoluzione della tastiera numerica. saluti shishir
Shishir.bobby

Magnifico. Solo un promemoria che in alcune situazioni, per sbarazzarsi della tastiera, provare seguendo le linee ... [self.view endEditing: YES];
Fattie l'

@Vojto, funziona bene su iPad. Probabilmente non hai impostato il delegato.
Vincent,

4
Il problema è che la tastiera potrebbe nascondere parte dell'interfaccia utilizzata per chiudere. È davvero assurdo che IOS non abbia un pulsante su ogni tastiera dedicato a chiudere la tastiera, quindi l'utente può farlo se lo desidera.
Sani Elfishawy,

80

So che è già stata data una risposta, ma non mi piace usare letteralmente la stringa per la newline, quindi ecco cosa ho fatto.

- (BOOL)textView:(UITextView *)txtView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
    if( [text rangeOfCharacterFromSet:[NSCharacterSet newlineCharacterSet]].location == NSNotFound ) {
        return YES;
    }

    [txtView resignFirstResponder];
    return NO;
}

Aggiornamento di Swift 4.0:

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if (text as NSString).rangeOfCharacter(from: CharacterSet.newlines).location == NSNotFound {
    return true
}
txtView.resignFirstResponder()
return false
}

6
Potrei modificarlo in questo modo: NSRange resultRange = [text rangeOfCharacterFromSet: [NSCharacterSet newlineCharacterSet] opzioni: NSBackwardsSearch]; Poiché si tratta comunque di un hack, sembra che controllare la fine della stringa per un ritorno potrebbe essere un percorso più sicuro.
maxpower

@maxpower Ottimo commento. Inoltre, è meglio verificare il testo sostituito, ad es NSString *replacedText = [textView.text stringByReplacingCharactersInRange:range withString:text].
Rudolf Adamkovič,

Immagina un utente che incolla del testo copiato da altrove che contiene una nuova riga. Probabilmente sarebbero confusi quando invece di aggiungere il testo l'app semplicemente respinge la tastiera.
Nikolai Ruhe,

44

So che è stato risposto molte volte, ma ecco i miei due centesimi per il problema.

Ho trovato davvero utili le risposte di samvermette e ribeto e anche il commento di maxpower nella risposta di ribeto . Ma c'è un problema con questi approcci. Il problema che Matt menziona nel samvermette 's risposta ed è che, se l'utente vuole incollare qualcosa con un'interruzione di linea al suo interno, la tastiera si nascondeva senza incollare nulla.

Quindi il mio approccio è una combinazione delle tre soluzioni sopra menzionate e controlla solo se la stringa inserita è una nuova riga quando la lunghezza della stringa è 1, quindi ci assicuriamo che l'utente stia digitando invece di incollare.

Ecco cosa ho fatto:

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
    NSRange resultRange = [text rangeOfCharacterFromSet:[NSCharacterSet newlineCharacterSet] options:NSBackwardsSearch];
    if ([text length] == 1 && resultRange.location != NSNotFound) {
        [textView resignFirstResponder];
        return NO;
    }

    return YES;
}

Questa è la soluzione migliore per questo problema. la risposta samvermette non tiene conto della situazione in cui l'utente vuole incollare un testo.
marcopaivaf,

36

Un modo più elegante è quello di chiudere la tastiera quando l'utente tocca da qualche parte al di fuori del riquadro della tastiera.

Innanzitutto, imposta la vista di ViewController sulla classe "UIControl" nella finestra di ispezione delle identità in UIBuilder. Tieni premuto il tasto Control per trascinare la vista nel file di intestazione di ViewController e collegarla come azione con l'evento come Ritocco interno, ad esempio:

ViewController.h

-(IBAction)dismissKeyboardOnTap:(id)sender;

Nel file ViewController principale, ViewController.m:

-(IBAction)dismissKeyboardOnTap:(id)sender
    {
         [[self view] endEditing:YES];
    }

Puoi richiedere un doppio tocco o un tocco lungo usando tecniche simili. Potrebbe essere necessario impostare ViewController come UITextViewDelegate e connettere TextView a ViewController. Questo metodo funziona sia per UITextView che per UITextField.

Fonte: Big Nerd Ranch

EDIT: Vorrei anche aggiungere che se si utilizza un UIScrollView, la tecnica di cui sopra potrebbe non funzionare altrettanto facilmente tramite Interface Builder. In tal caso, è possibile utilizzare un UIGestureRecognizer e chiamare invece il metodo [[self view] endEditing: YES] al suo interno. Un esempio potrebbe essere:

-(void)ViewDidLoad{
    ....
    UITapGestureRecognizer *tapRec = [[UITapGestureRecognizer alloc] 
        initWithTarget:self action:@selector(tap:)];
    [self.view addGestureRecognizer: tapRec];
    ....
}

-(void)tap:(UITapGestureRecognizer *)tapRec{
    [[self view] endEditing: YES];
}

Quando l'utente tocca all'esterno della tastiera e non tocca uno spazio di immissione, la tastiera verrà chiusa.


1
Mi piace l'idea GestureRecognizerma il problema enorme è che tutti i pulsanti o i controlli sulla vista non sono più selezionabili.
esperto

35

Aggiungi questo metodo nel controller della vista.

Veloce :

func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
    if text == "\n" {
        textView.resignFirstResponder()
        return false
    }
    return true
}

Questo metodo può anche essere utile per te:

/**
Dismiss keyboard when tapped outside the keyboard or textView

:param: touches the touches
:param: event   the related event
*/
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
    if let touch = touches.anyObject() as? UITouch {
        if touch.phase == UITouchPhase.Began {
            textField?.resignFirstResponder()
        }
    }
}

2
Non dimenticare di confermare il protocollo UITextViewDelegate :)
swiftBoy,

Non penso che sia una buona idea ignorare i tocchiBegan e non chiamare super.touchesBegan(touches:withEvent:).
TGO,

Per esprimere la natura simmetrica di questo codice, dovresti scrivere else { return true }.
significato-importa

@ significato-non importa affatto
Alexander Volkov

@AlexanderVolkov Non sei d'accordo che sia una situazione simmetrica, non sai cosa intendo, non credi nel valore del codice semanticamente corretto, o ...?
significato-importa

26
-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
    if([text isEqualToString:@"\n"])
        [textView resignFirstResponder];
    return YES;
}

yourtextView.delegate=self;

Aggiungi anche UITextViewDelegate

Non dimenticare di confermare il protocollo

SE non hai aggiunto if([text isEqualToString:@"\n"])non puoi modificare


2
-1 Questa è solo una versione più povera della risposta di samvermette. Ti sei perso di ritorno NOse il testo è uguale a @"\n".
devios1

17

Esiste un'altra soluzione durante l'utilizzo con uitextview, è possibile aggiungere la barra degli strumenti come InputAccessoryView in "textViewShouldBeginEditing" e dal pulsante Fine di questa barra degli strumenti è possibile chiudere la tastiera, il codice è il seguente:

In viewDidLoad

toolBar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, 320, 44)]; //toolbar is uitoolbar object
toolBar.barStyle = UIBarStyleBlackOpaque;
UIBarButtonItem *btnDone = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(btnClickedDone:)];
[toolBar setItems:[NSArray arrayWithObject:btnDone]];

Nel metodo textviewdelegate

- (BOOL)textViewShouldBeginEditing:(UITextView *)textView
{
     [textView setInputAccessoryView:toolBar];
     return YES;
}

In azione del pulsante Fine che si trova nella barra degli strumenti è il seguente:

-(IBAction)btnClickedDone:(id)sender
{
    [self.view endEditing:YES];
}

17

Ho trovato la risposta di josebama come la risposta più completa e pulita disponibile in questo thread.

Di seguito è riportata la sintassi di Swift 4 :

func textView(_ textView: UITextView, shouldChangeTextIn _: NSRange, replacementText text: String) -> Bool {
    let resultRange = text.rangeOfCharacter(from: CharacterSet.newlines, options: .backwards)
    if text.count == 1 && resultRange != nil {
        textView.resignFirstResponder()
        // Do any additional stuff here
        return false
    }
    return true
}

L' resultRangeobiettivo è verificare se il testo contiene solo nuove righe che evitano il codice "\ n".
Qinghua,

6

veloce

func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
    if text == "\n" {
        textView.resignFirstResponder()
    }
    return true
}

e configurare


Da dove viene quella schermata?
Sam,

6

Utilizzo del controller di navigazione per ospitare una barra per chiudere la tastiera:

nel file .h:

UIBarButtonItem* dismissKeyboardButton;

nel file .m:

- (void)viewDidLoad {
    dismissKeyboardButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(dismissKeyboard)];
}

-(void)textViewDidBeginEditing:(UITextView *)textView {
    self.navigationItem.rightBarButtonItem = dismissKeyboardButton;
}

-(void)textFieldDidBeginEditing:(UITextField *)textField {
    self.navigationItem.rightBarButtonItem = dismissKeyboardButton;
}

-(void)dismissKeyboard {
    [self.textField resignFirstResponder];
    [self.textView resignFirstResponder];
    //or replace this with your regular right button
    self.navigationItem.rightBarButtonItem = nil;
}

5

Proprio come un commento opaco a Samvermette, non mi piace neanche l'idea di rilevare "\ n". La chiave "return" è lì per un motivo in UITextView, che è quello di andare ovviamente alla riga successiva.

La migliore soluzione secondo me è imitare l'app per i messaggi di iPhone, che consiste nell'aggiungere la barra degli strumenti (e il pulsante) sulla tastiera.

Ho ricevuto il codice dal seguente post sul blog:

http://www.iosdevnotes.com/2011/02/iphone-keyboard-toolbar/

passi:

-Aggiunta barra degli strumenti al file XIB: imposta l'altezza su 460

-Aggiungi elemento pulsante barra degli strumenti (se non già aggiunto). Se è necessario allinearlo a destra, aggiungere anche l'elemento pulsante barra flessibile a XIB e spostare l'elemento pulsante barra degli strumenti

-Crea azioni che collegano l'elemento del tuo pulsante a dimettersiFirstResponder come segue:

- (IBAction)hideKeyboard:(id)sender {
    [yourUITextView resignFirstResponder];
}

-Poi:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];

    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}

- (void)keyboardWillShow:(NSNotification *)notification {
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.3];

    CGRect frame = self.keyboardToolbar.frame;
    frame.origin.y = self.view.frame.size.height - 260.0;
    self.keyboardToolbar.frame = frame;

    [UIView commitAnimations];
}

- (void)keyboardWillHide:(NSNotification *)notification {
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.3];

    CGRect frame = self.keyboardToolbar.frame;
    frame.origin.y = self.view.frame.size.height;
    self.keyboardToolbar.frame = frame;

    [UIView commitAnimations];
}

Fuori tema. Sebbene la tua soluzione sia elegante, non risponde alla domanda originale: "Come eliminare la tastiera per UITextView con il tasto Invio?". Ci sono situazioni in cui UITextView viene utilizzato per simulare una parola che avvolge UITextField, non per inserire più righe.
SwiftArchitect,

2
Anche se è fuori tema, è molto utile. Voglio anche inserire un UITextView con più righe e chiudere la tastiera quando voglio.
Yeung

5

Ho appena risolto questo problema in un modo diverso.

  • Crea un pulsante che verrà posizionato in background
  • Da Impostazioni attributi, cambia il tipo di pulsante in personalizzato e rende il pulsante trasparente.
  • Espandi il pulsante per coprire l'intera vista e assicurati che il pulsante si trovi dietro tutto l'altro oggetto. Un modo semplice per farlo è trascinare il pulsante nella parte superiore della vista elenco nella vista
  • Controllo trascinare il pulsante sul viewController.hfile e creare un'azione (Evento inviato: ritocco interno) come:

    (IBAction)ExitKeyboard:(id)sender;
  • Nel ViewController.mdovrebbe essere simile:

    (IBAction)ExitKeyboard:(id)sender {
        [self.view endEditing:TRUE];
    }
  • Esegui l'app e quando fai clic lontano da TextView, la tastiera scompare

Devi anche aggiungere: - (void) textViewDidEndEditing: (UITextView *) textView {[self.TextView resignFirstResponder]; }
sabato

5

Aggiungi un osservatore in viewDidLoad

[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(textViewKeyPressed:) name: UITextViewTextDidChangeNotification object: nil];

e quindi usa il selettore per verificare "\ n"

-(void) textViewKeyPressed: (NSNotification*) notification {

  if ([[[notification object] text] hasSuffix:@"\n"])
  {
    [[notification object] resignFirstResponder];
  }
}

Usa "\ n" e non controlla specificamente la chiave di ritorno, ma penso che sia OK.

AGGIORNARE

Vedi la risposta di ribto sotto che utilizza [NSCharacterSet newlineCharacterSet]al posto di\n


Err utilizza \ne la chiave di ritorno viene rilevata in base a \ncosì controlla la chiave di ritorno. L'unica differenza è che stai usando le notifiche piuttosto che usare i textViewDelegates.
GoodSp33d,

Ora penso che controllare [NSCharacterSet newlineCharacterSet]piuttosto che \ n potrebbe essere un modo migliore per andare.
ToddB,

5

codice SWIFT

Implementa UITextViewDelegate nella tua classe / Visualizza in questo modo:

class MyClass: UITextViewDelegate  { ...

imposta il delegato textView su sé stesso

myTextView.delegate = self

E quindi implementare quanto segue:

  func textViewDidChange(_ textView: UITextView) {
    if textView.text.characters.count >= 1 {

        if let lastChar = textView.text.characters.last {

            if(lastChar == "\n"){

              textView.text = textView.text.substring(to: textView.text.index(before: textView.text.endIndex))
              textView.resignFirstResponder()
            }
        }
    }
}

MODIFICA Ho aggiornato il codice perché non è mai una buona idea cambiare l'input dell'utente in un campo di testo per un'area di lavoro e non ripristinare lo stato dopo il completamento del codice di hacking.


4

Prova questo :

 - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{
    if ([text isEqualToString:@"\n"]) {
        [self.view endEditing:YES];
    }

    return YES;

}

4

// Puoi usare questo ...

Passaggio 1. Il primo passaggio consiste nell'assicurarsi di dichiarare il supporto per il UITextViewDelegateprotocollo. Questo viene fatto nel tuo file di intestazione, come esempio qui è l'intestazione chiamata

EditorController.h:

@interface EditorController : UIViewController  {
  UITextView *messageTextView;
}

@property (nonatomic, retain) UITextView *messageTextView;

@end

Passaggio 2. Successivamente sarà necessario registrare il controller come delegato di UITextView. Continuando dall'esempio sopra, ecco come ho inizializzato il UITextViewcon EditorControllercome delegato ...

- (id) init {
    if (self = [super init]) {
        // define the area and location for the UITextView
        CGRect tfFrame = CGRectMake(10, 10, 300, 100);
        messageTextView = [[UITextView alloc] initWithFrame:tfFrame];
        // make sure that it is editable
        messageTextView.editable = YES;

        // add the controller as the delegate
        messageTextView.delegate = self;
    }

Passaggio 3. E ora l'ultimo pezzo del puzzle è agire in risposta al shouldCahngeTextInRangemessaggio come segue:

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range 
  replacementText:(NSString *)text
{
    // Any new character added is passed in as the "text" parameter
    if ([text isEqualToString:@"\n"]) {
        // Be sure to test for equality using the "isEqualToString" message
        [textView resignFirstResponder];

        // Return FALSE so that the final '\n' character doesn't get added
        return FALSE;
    }
    // For any other character return TRUE so that the text gets added to the view
    return TRUE;
}

3

Puoi anche nascondere la tastiera quando tocchi nella schermata di visualizzazione:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
     UITouch * touch = [touches anyObject];
     if(touch.phase == UITouchPhaseBegan) {
        [txtDetail resignFirstResponder];
      }
 }

IMHO, questo è un ottimo approccio, molto meglio che con il pulsante che copre l'intera vista.
WebOrCode

3

Risposta rapida:

override func viewDidLoad() {
    super.viewDidLoad()
    let tapGestureReconizer = UITapGestureRecognizer(target: self, action: "tap:")
    view.addGestureRecognizer(tapGestureReconizer)
}

func tap(sender: UITapGestureRecognizer) {
    view.endEditing(true)
}

3

Ho usato questo codice per cambiare risponditore.

 - (BOOL)textView:(UITextView*) textView shouldChangeTextInRange: (NSRange) range replacementText: (NSString*) text
    {
        if ([text isEqualToString:@"\n"]) {
            //[textView resignFirstResponder];
            //return YES;
            NSInteger nextTag = textView.tag + 1;
            // Try to find next responder
            UIResponder* nextResponder = [self.view viewWithTag:nextTag];
            if (nextResponder) {
                // Found next responder, so set it.
                [nextResponder becomeFirstResponder];
            } else {
                // Not found, so remove keyboard.
                [textView resignFirstResponder];
            }
            return NO; 


            return NO;
        }
        return YES;

    }

perché non usare [self.view endEditing: YES]; una volta??
ajay_nasa,

3

La domanda chiede come farlo con il tasto Invio, ma penso che ciò potrebbe aiutare qualcuno con l'intenzione di far scomparire la tastiera quando si usa UITextView:

private func addToolBarForTextView() {
    let textViewToolbar: UIToolbar = UIToolbar()
    textViewToolbar.barStyle = .default
    textViewToolbar.items = [
        UIBarButtonItem(title: "Cancel", style: .done,
                  target: self, action: #selector(cancelInput)),
        UIBarButtonItem(barButtonSystemItem: .flexibleSpace,
                  target: self, action: nil),
        UIBarButtonItem(title: "Post Reply", style: .done,
                  target: self, action: #selector(doneInput))
    ]
    textViewToolbar.sizeToFit()
    yourTextView.inputAccessoryView = textViewToolbar
}

@objc func cancelInput() { print("cancel") }
@objc func doneInput() { print("done") }

override func viewDidLoad() {
    super.viewDidLoad()
    addToolBarForTextView()
}

Chiamare addToolBarForTextView () nel viewDidLoad o in qualche altro metodo del ciclo di vita.

Sembra che sia stata la soluzione perfetta per me.

Saluti,

Murat


1
Per il 2019 ora copia e incolla, nessun errore di sintassi e denominazione corrente
Fattie,

1
di gran lunga la migliore risposta qui. Ho appena corretto il semplice errore di sintassi, ovviamente modificalo come desideri. Grazie!
Fattie,

2

Ok. Tutti hanno dato delle risposte con dei trucchi, ma penso che il modo giusto per raggiungere questo obiettivo sia

Collegamento della seguente azione all'evento " Did End On Exit " in Interface Builder. (fare clic con il tasto destro del mouse TextFielde trascinare e trascinare da " Fine all'uscita " al seguente metodo.

-(IBAction)hideTheKeyboard:(id)sender
{
    [self.view endEditing:TRUE];
}

6
-1 La domanda riguarda UITextView e non UITextField amico mio
Yogi

2
la maggior parte di queste risposte sono qui con voti perché si adatta a vari scenari di sviluppatori diversi.
carbonr,

Se stai usando un UITextField, questo è il modo di farlo. A proposito, dovresti usare SÌ / NO per BOOL Objective-C, non VERO / FALSO.
Jon Shier,

1
@jshier: Anche VERO / FALSO va bene
Yogi,

2

Simulare ad altre risposte utilizzando l' UITextViewDelegateinterfaccia rapida ma più recente isNewlinesarebbe:

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    if let character = text.first, character.isNewline {
        textView.resignFirstResponder()
        return false
    }
    return true
}

1
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range  replacementText:(NSString *)text
{
    if (range.length==0) {
        if ([text isEqualToString:@"\n"]) {
            [txtView resignFirstResponder];
            if(textView.returnKeyType== UIReturnKeyGo){

                [self PreviewLatter];
                return NO;
            }
            return NO;
        }
    }   return YES;
}

1
+ (void)addDoneButtonToControl:(id)txtFieldOrTextView
{
    if([txtFieldOrTextView isKindOfClass:[UITextField class]])
    {
        txtFieldOrTextView = (UITextField *)txtFieldOrTextView;
    }
    else if([txtFieldOrTextView isKindOfClass:[UITextView class]])
    {
        txtFieldOrTextView = (UITextView *)txtFieldOrTextView;
    }

    UIToolbar* numberToolbar = [[UIToolbar alloc]initWithFrame:CGRectMake(0,
                                                                          0,
                                                                          [Global returnDeviceWidth],
                                                                          50)];
    numberToolbar.barStyle = UIBarStyleDefault;


    UIBarButtonItem *btnDone = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"btn_return"]
                                                                style:UIBarButtonItemStyleBordered
                                                               target:txtFieldOrTextView
                                                               action:@selector(resignFirstResponder)];

    numberToolbar.items = [NSArray arrayWithObjects:btnDone,nil];
    [numberToolbar sizeToFit];

    if([txtFieldOrTextView isKindOfClass:[UITextField class]])
    {
         ((UITextField *)txtFieldOrTextView).inputAccessoryView = numberToolbar;
    }
    else if([txtFieldOrTextView isKindOfClass:[UITextView class]])
    {
         ((UITextView *)txtFieldOrTextView).inputAccessoryView = numberToolbar;
    }
}

0

So che non è la risposta esatta a questa domanda, ma ho trovato questa discussione dopo aver cercato su Internet una risposta. Presumo che altri condividano quella sensazione.

Questa è la mia varianza di UITapGestureRecognizer che trovo affidabile e facile da usare: basta impostare il delegato di TextView su ViewController.

Invece di ViewDidLoad aggiungo UITapGestureRecognizer quando TextView diventa attivo per la modifica:

-(void)textViewDidBeginEditing:(UITextView *)textView{
    _tapRec = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap:)];

    [self.view addGestureRecognizer: _tapRec];
    NSLog(@"TextView Did begin");
}

Quando tocco all'esterno di TextView, la vista termina la modalità di modifica e UITapGestureRecognizer si rimuove per consentirmi di continuare a interagire con altri controlli nella vista.

-(void)tap:(UITapGestureRecognizer *)tapRec{
    [[self view] endEditing: YES];
    [self.view removeGestureRecognizer:tapRec];
    NSLog(@"Tap recognized, tapRec getting removed");
}

Spero che questo possa essere d'aiuto. Sembra così ovvio ma non ho mai visto questa soluzione da nessuna parte sul web - sto facendo qualcosa di sbagliato?


0

Non dimenticare di impostare il delegato per textView, altrimenti resignfirstresponder non funzionerà.


0

Prova questo .

NSInteger lengthOfText = [[textView.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length];

0

Per Xcode 6.4., Swift 1.2. :

   override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent)
    {
        super.touchesBegan(touches, withEvent: event)
        if let touch = touches.first as? UITouch
        {
            self.meaningTextview.resignFirstResponder()
        }
    }

0

Dovresti aggiungere UIToolbar all'inizio di UITextView per semplificare anziché utilizzareshouldChangeTextIn

In Swift 4

let toolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 50))
        toolbar.barStyle = .default
        toolbar.items = [
            UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil),
            UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(doneAction))
        ]
        textView.inputAccessoryView = toolbar
@objc func doneAction(){
 self.textView.resignFirstResponder()
}

Di gran lunga la soluzione migliore. Si noti che invece di impostare il frame, basta usaretoolbar.sizeToFit()
Fattie il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.