Comment fermer le clavier pour UITextView avec la touche retour?

382

Dans la bibliothèque d'IB, l'introduction nous indique que lorsque la returntouche est enfoncée, le clavier de UITextViewdisparaîtra. Mais en réalité, la returnclé ne peut agir que comme «\ n».

Je peux ajouter un bouton et utiliser [txtView resignFirstResponder]pour masquer le clavier.

Mais existe-t-il un moyen d'ajouter l'action pour la returntouche du clavier afin que je n'aie pas besoin d'ajouter UIButton?

Chilly Zhong
la source
Suivez les instructions sur cet article de blog: iphonedevelopertips.com/cocoa/…
ManojN

Réponses:

354

UITextViewn'a aucune méthode qui sera appelée lorsque l'utilisateur appuiera sur la touche retour. Si vous souhaitez que l'utilisateur ne puisse ajouter qu'une seule ligne de texte, utilisez a UITextField. Frapper le retour et masquer le clavier pour un UITextViewne suit pas les directives d'interface.

Même alors, si vous voulez le faire, implémentez la textView:shouldChangeTextInRange:replacementText:méthode de UITextViewDelegateet dans cette vérification si le texte de remplacement est \n, cachez le clavier.

Il pourrait y avoir d'autres moyens mais je n'en connais aucun.

lostInTransit
la source
1
Merci et la méthode fonctionne bien. La raison d'utiliser UITextView est qu'il peut contenir du texte sur plusieurs lignes. Et maintenant, je l'utilise comme boîte de message.
Chilly Zhong
28
Il est assez facile de changer la clé de retour en "terminé" en utilisant soit [textField setReturnKeyType: UIReturnKeyDone];ou en utilisant le générateur d'interface
Casebash
9
D'accord, je comprends maintenant que la façon dont Apple termine avec un champ de texte multiligne est d'ajouter terminé à la barre de menus
Casebash
8
Ce n'est pas un bon moyen de résoudre ce problème car vous limitez l'utilisateur à utiliser Entrée pour sortir du clavier. La meilleure façon est probablement d'ajouter un bouton qui exécute la méthode resignFirstResponder.
Ele
5
@Casebash. Il semble que définir la clé de retour sur "terminé" ne résout pas le problème dans Xcode 6.4, Swift 2.0. J'ai défini la clé en utilisant IB.
MB_iOSDeveloper
505

Je pensais que je publierais l'extrait ici à la place:

Assurez-vous de déclarer la prise en charge du UITextViewDelegateprotocole.

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

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

    return YES;
}

Mise à jour Swift 4.0:

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    if text == "\n" {
        textView.resignFirstResponder()
        return false
    }
    return true
}
samvermette
la source
75
Le problème est que ce n'est pas vraiment un moyen de détecter que l'utilisateur a appuyé sur la touche de retour . L'utilisateur peut coller un caractère de retour dans le champ de texte et vous obtiendrez le même message de délégué. Fondamentalement, vous abusez de la vue texte. La façon de fermer le clavier est (1) de ne pas le faire du tout (comme lors de la composition d'un message dans l'application Mail) ou (2) d'avoir un bouton Terminé ailleurs dans l'interface (comme dans l'application Notes). Vous pouvez par exemple attacher un tel bouton comme vue accessoire au clavier.
mat
@ Sam V cet extrait était un homme cool. ça marche pour moi. merci un homme de tonne. Existe-t-il un extrait de code pour la dissémination du clavier numérique. ce qui concerne shishir
Shishir.bobby
Magnifique. Juste un rappel que dans certaines situations, pour se débarrasser du clavier, essayez le long des lignes ... [self.view endEditing: YES];
Fattie
@Vojto, fonctionne très bien sur iPad. Vous n'avez probablement pas défini le délégué.
Vincent
4
Le problème est que le clavier peut masquer une partie de l'interface utilisée pour ignorer. Il est vraiment absurde que IOS ne dispose pas d'un bouton sur chaque clavier dédié pour ignorer le clavier afin que l'utilisateur puisse le faire s'il le souhaite.
Sani Elfishawy
80

Je sais que cela a déjà été répondu, mais je n'aime pas vraiment utiliser le littéral de chaîne pour la nouvelle ligne, alors voici ce que j'ai fait.

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

    [txtView resignFirstResponder];
    return NO;
}

Mise à jour 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
}
ribeto
la source
6
Je pourrais le modifier comme ceci: NSRange resultRange = [text rangeOfCharacterFromSet: [NSCharacterSet newlineCharacterSet] options: NSBackwardsSearch]; Parce que c'est un hack de toute façon, il semble que vérifier la fin de la chaîne pour un retour soit un itinéraire plus sûr.
maxpower
@maxpower Très bon commentaire. En outre, il est préférable de vérifier le texte remplacé, par exemple NSString *replacedText = [textView.text stringByReplacingCharactersInRange:range withString:text].
Rudolf Adamkovič
Imaginez un utilisateur collant du texte copié ailleurs contenant une nouvelle ligne. Ils seraient probablement confus lorsque, au lieu d'ajouter le texte, l'application rejette simplement le clavier.
Nikolai Ruhe du
44

Je sais que cela a été répondu à de nombreuses reprises, mais voici mes deux cents à la question.

J'ai trouvé les réponses de samvermette et ribeto très utiles, ainsi que le commentaire de maxpower dans la réponse de ribeto . Mais il y a un problème avec ces approches. Le problème que Matt mentionne dans la réponse de la samvermette et c'est que si l'utilisateur veut coller quelque chose avec un saut de ligne à l'intérieur, le clavier se cacherait sans rien coller.

Mon approche consiste donc à mélanger les trois solutions mentionnées ci-dessus et à ne vérifier que si la chaîne entrée est une nouvelle ligne lorsque la longueur de la chaîne est 1, nous nous assurons donc que l'utilisateur tape au lieu de coller.

Voici ce que j'ai fait:

- (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;
}
josebama
la source
Il s'agit d'une meilleure solution à ce problème. La réponse de samvermette ne tient pas compte de la situation où l'utilisateur souhaite coller un texte.
marcopaivaf
36

Une manière plus élégante consiste à fermer le clavier lorsque l'utilisateur appuie quelque part en dehors du cadre du clavier.

Tout d'abord, définissez la vue de votre ViewController sur la classe "UIControl" dans l'inspecteur d'identité dans UIBuilder. Faites glisser la vue dans le fichier d'en-tête de ViewController et liez-la en tant qu'action avec l'événement comme Touch Up Inside, par exemple:

ViewController.h

-(IBAction)dismissKeyboardOnTap:(id)sender;

Dans le fichier principal de ViewController, ViewController.m:

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

Vous pouvez exiger un double tapotement ou une longue pression en utilisant des techniques similaires. Vous devrez peut-être définir votre ViewController pour qu'il soit un UITextViewDelegate et connecter le TextView au ViewController. Cette méthode fonctionne pour UITextView et UITextField.

Source: Ranch Big Nerd

EDIT: Je voudrais également ajouter que si vous utilisez un UIScrollView, la technique ci-dessus peut ne pas fonctionner aussi facilement via Interface Builder. Dans ce cas, vous pouvez utiliser un UIGestureRecognizer et appeler à la place la méthode [[self view] endEditing: YES]. Un exemple serait:

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

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

Lorsque l'utilisateur touche en dehors du clavier et ne touche pas d'espace d'entrée, le clavier se ferme.

TMilligan
la source
1
J'aime l'idée avec GestureRecognizermais l'énorme problème est que tous les boutons ou contrôles de la vue ne sont plus cliquables.
expert
35

Ajoutez cette méthode dans votre contrôleur de vue.

Rapide :

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

Cette méthode peut également vous être utile:

/**
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()
        }
    }
}
Alexander Volkov
la source
2
N'oubliez pas de confirmer le protocole UITextViewDelegate :)
swiftBoy
Je ne pense pas que ce soit une bonne idée de remplacer les touchesBegan et de ne pas appeler super.touchesBegan(touches:withEvent:).
TGO
Pour exprimer la nature symétrique de ce code, vous devez écrire else { return true }.
signification compte
@ signification-importe pas du tout
Alexander Volkov
@AlexanderVolkov Vous n'êtes pas d'accord pour dire que c'est une situation symétrique, vous ne savez pas ce que je veux dire, vous ne croyez pas à la valeur d'un code sémantiquement correct, ou, ...?
signification est importante
26
-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
    if([text isEqualToString:@"\n"])
        [textView resignFirstResponder];
    return YES;
}

yourtextView.delegate=self;

Ajoutez également UITextViewDelegate

N'oubliez pas de confirmer le protocole

SI vous n'avez pas ajouté, if([text isEqualToString:@"\n"])vous ne pouvez pas modifier

Vineesh TP
la source
2
-1 Ceci est juste une version plus pauvre de la réponse de samvermette. Vous avez manqué de revenir NOsi le texte est égal à @"\n".
devios1
17

Il existe une autre solution lors de l'utilisation avec uitextview, vous pouvez ajouter la barre d'outils en tant que InputAccessoryView dans "textViewShouldBeginEditing", et à partir du bouton terminé de cette barre d'outils, vous pouvez fermer le clavier, le code pour cela est le suivant:

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]];

Dans la méthode textviewdelegate

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

En action du bouton Terminé qui se trouve dans la barre d'outils est le suivant:

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

J'ai trouvé que la réponse de josebama était la réponse la plus complète et la plus claire disponible dans ce fil.

Voici la syntaxe Swift 4 pour cela:

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
}
Puneet Kohli
la source
L' resultRangeobjectif est de tester si le texte ne contient que des sauts de ligne qui évitent le code dur "\ n".
Qinghua
6

rapide

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

et configurer

Eduardo Oliveros Acosta
la source
D'où vient cette capture d'écran?
Sam
6

Utilisation du contrôleur de navigation pour héberger une barre pour fermer le clavier:

dans le fichier .h:

UIBarButtonItem* dismissKeyboardButton;

dans le fichier .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;
}
Alex Stone
la source
5

Tout comme un commentaire mat à samvermette, je n'aime pas non plus l'idée de détecter "\ n". La touche "retour" est là pour une raison dans UITextView, c'est d'aller à la ligne suivante bien sûr.

La meilleure solution à mon avis est d'imiter l'application de message iPhone - qui consiste à ajouter une barre d'outils (et un bouton) sur le clavier.

J'ai reçu le code du blog suivant:

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

Pas:

-Ajouter la barre d'outils à votre fichier XIB - définissez la hauteur sur 460

-Ajouter un élément du bouton de la barre d'outils (s'il n'est pas déjà ajouté). Si vous devez l'aligner à droite, ajoutez également l'élément de bouton de barre flexible à XIB et déplacez l'élément de bouton de barre d'outils

-Créer une action qui relie votre élément de bouton à resignFirstResponder comme suit:

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

-Alors:

- (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];
}
ami
la source
Hors sujet. Bien que votre solution soit élégante, elle ne répond pas à la question d'origine: "Comment supprimer le clavier pour UITextView avec la touche retour?". Il existe des situations où UITextView est utilisé pour simuler un habillage de mot UITextField, et non pour entrer plusieurs lignes.
SwiftArchitect
2
Bien qu'il soit hors sujet, il est très utile. Je veux également qu'un UITextView soit entré avec plusieurs lignes et que je rejette le clavier quand je le veux.
Yeung
5

Je viens de résoudre ce problème d'une manière différente.

  • Créez un bouton qui sera placé en arrière-plan
  • Dans l'inspecteur d'attributs, changez le type de bouton en personnalisé et rend le bouton transparent.
  • Développez le bouton pour couvrir toute la vue et assurez-vous qu'il se trouve derrière tous les autres objets. Pour ce faire, il vous suffit de faire glisser le bouton en haut de la liste dans la vue
  • Faites glisser le bouton vers le viewController.hfichier et créez une action (Événement envoyé: Retouche à l'intérieur) comme:

    (IBAction)ExitKeyboard:(id)sender;
  • Dans ViewController.m devrait ressembler à:

    (IBAction)ExitKeyboard:(id)sender {
        [self.view endEditing:TRUE];
    }
  • Exécutez l'application et lorsque vous cliquez en dehors de TextView, le clavier disparaît
Uvichy
la source
Vous devez également ajouter: - (void) textViewDidEndEditing: (UITextView *) textView {[self.TextView resignFirstResponder]; }
samouray
5

Ajouter un observateur dans viewDidLoad

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

puis utilisez le sélecteur pour vérifier "\ n"

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

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

Il utilise "\ n" et ne vérifie pas spécifiquement une clé de retour, mais je pense que c'est OK.

MISE À JOUR

Voir la réponse de ribto ci-dessous qui utilise [NSCharacterSet newlineCharacterSet]à la place de\n

ToddB
la source
Err, il utilise \net la clé de retour est détectée en fonction de \nsorte qu'il vérifie la clé de retour. La seule différence est que vous utilisez des notifications plutôt que d'utiliser les textViewDelegates.
GoodSp33d
Maintenant, je pense que vérifier [NSCharacterSet newlineCharacterSet]plutôt que \ n pourrait être une meilleure façon de procéder.
ToddB
5

Code rapide

Implémentez UITextViewDelegate dans votre classe / View comme ceci:

class MyClass: UITextViewDelegate  { ...

définissez le délégué textView sur self

myTextView.delegate = self

Et puis implémentez les éléments suivants:

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

EDIT J'ai mis à jour le code car ce n'est jamais une bonne idée de changer l'entrée utilisateur dans un champ de texte pour une solution de contournement et de ne pas réinitialiser l'état une fois le code de piratage terminé.

Frithjof Schaefer
la source
4

Essaye ça :

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

    return YES;

}
Nabil El
la source
4

// Vous pouvez utiliser ceci ...

Étape 1. La première étape consiste à vous assurer que vous déclarez la prise en charge du UITextViewDelegateprotocole. Cela se fait dans votre fichier d'en-tête, comme exemple voici l'en-tête appelé

EditorController.h:

@interface EditorController : UIViewController  {
  UITextView *messageTextView;
}

@property (nonatomic, retain) UITextView *messageTextView;

@end

Étape 2. Ensuite, vous devrez enregistrer le contrôleur en tant que délégué de l'UITextView. En UITextViewreprenant l'exemple ci-dessus, voici comment j'ai initialisé le avec en EditorControllertant que délégué…

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

Étape 3. Et maintenant, la dernière pièce du puzzle consiste à agir en réponse au shouldCahngeTextInRangemessage comme suit:

- (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;
}
Abhishek Pathak
la source
3

Vous pouvez également masquer le clavier lorsque vous touchez dans l'écran d'affichage:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
     UITouch * touch = [touches anyObject];
     if(touch.phase == UITouchPhaseBegan) {
        [txtDetail resignFirstResponder];
      }
 }
Hitesh Vaghela
la source
À mon humble avis, c'est une très bonne approche, bien meilleure qu'avec un bouton qui couvre toute la vue.
WebOrCode
3

Réponse rapide:

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

func tap(sender: UITapGestureRecognizer) {
    view.endEditing(true)
}
Glauco Neves
la source
3

J'ai utilisé ce code pour changer de répondeur.

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

    }
Avijit Nagare
la source
pourquoi ne pas utiliser [self.view endEditing: YES]; une fois que??
ajay_nasa
3

La question demande comment le faire avec la touche retour mais je pense que cela pourrait aider quelqu'un avec l'intention de simplement faire disparaître le clavier lors de l'utilisation de 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()
}

Appelez addToolBarForTextView () dans viewDidLoad ou une autre méthode de cycle de vie.

Il semble que c'était la solution parfaite pour moi.

À votre santé,

Murat

Murat Yasar
la source
1
Pour 2019, copiez et collez maintenant, aucune erreur de syntaxe et dénomination actuelle
Fattie
1
de loin la meilleure réponse ici. Je viens de corriger l'erreur de syntaxe simple, bien sûr, éditez comme vous le souhaitez. Merci!
Fattie
2

D'accord. Tout le monde a donné des réponses avec des astuces mais je pense que la bonne façon d'y parvenir est de

Connexion de l'action suivante à l' événement " Did End On Exit " dans Interface Builder. (cliquez avec le bouton droit de la souris TextFieldet faites glisser le curseur de la souris sur " Fin de la sortie " jusqu'à la méthode suivante.

-(IBAction)hideTheKeyboard:(id)sender
{
    [self.view endEditing:TRUE];
}
carbonr
la source
6
-1 La question concerne UITextView et non UITextField mon ami
Yogi
2
la plupart de ces réponses sont ici avec des votes car elles conviennent à différents scénarios de différents développeurs.
carbonr
Si vous utilisez un UITextField, c'est la façon de le faire. BTW, vous devez utiliser OUI / NON pour les booléens Objective-C, pas VRAI / FAUX.
Jon Shier
1
@jshier: TRUE / FALSE est OK aussi
Yogi
2

Similaire à d'autres réponses utilisant la UITextViewDelegatemais une interface rapide plus récente isNewlineserait:

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    if let character = text.first, character.isNewline {
        textView.resignFirstResponder()
        return false
    }
    return true
}
BROK3N S0UL
la source
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;
}
Rinju Jain
la source
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;
    }
}
Venu Gopal Tewari
la source
0

Je sais que ce n'est pas la réponse exacte à cette question, mais j'ai trouvé ce fil après avoir cherché sur Internet une réponse. Je suppose que les autres partagent ce sentiment.

C'est mon écart de l'UITapGestureRecognizer que je trouve fiable et facile à utiliser - il suffit de définir le délégué du TextView au ViewController.

Au lieu de ViewDidLoad, j'ajoute UITapGestureRecognizer lorsque TextView devient actif pour l'édition:

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

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

Lorsque je tape en dehors de TextView, la vue met fin au mode d'édition et UITapGestureRecognizer se supprime pour que je puisse continuer à interagir avec les autres contrôles de la vue.

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

J'espère que ça aide. Cela semble si évident, mais je n'ai jamais vu cette solution nulle part sur le Web - est-ce que je fais quelque chose de mal?

BGC
la source
0

N'oubliez pas de définir le délégué pour le textView - sinon resignfirst responder ne fonctionnera pas.

Ron Holmes
la source
0

Essaye ça .

NSInteger lengthOfText = [[textView.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length];
Hiren Panchal
la source
0

Pour 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()
        }
    }
MB_iOSDeveloper
la source
0

Vous devez ajouter UIToolbaren haut UITextView pour faciliter plutôt que d'utilisershouldChangeTextIn

Dans 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()
}
Giang
la source
De loin la meilleure solution. Notez qu'au lieu de définir le cadre, utilisez simplementtoolbar.sizeToFit()
Fattie