web-dev-qa-db-fra.com

Masquer le clavier en cas de perte du focus sur une UITextView

J'ai donc une UITextView que j'utilise pour permettre à l'utilisateur de soumettre du texte.

Mon problème est, je n'arrive pas à comprendre comment permettre à l'utilisateur d'annuler en appuyant sur UITextView.

45
tuzzolotron

Simplifier la réponse de tuzzolotron : Lorsque la prise suivante est correctement connectée dans votre xib

    IBOutlet UITextView *myTextView;

Utilisez ceci dans le contrôleur de vue:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    UITouch *touch = [[event allTouches] anyObject];
    if ([myTextView isFirstResponder] && [touch view] != myTextView) {
        [myTextView resignFirstResponder];
    }
    [super touchesBegan:touches withEvent:event];
}

Un tap sur la vue du contrôleur de vue, en dehors de la vue texte, va démissionner du premier intervenant et fermer le clavier.

107
ohhorob

Une autre approche que j'ai beaucoup utilisée lorsque je travaille avec UITableViews, la barre de recherche et le clavier est la suivante, je pense que vous pouvez l'appliquer à un champ de texte.

UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard)];
[self.tableView addGestureRecognizer:gestureRecognizer];
gestureRecognizer.cancelsTouchesInView = NO;  // this prevents the gesture recognizers to 'block' touches
[gestureRecognizer release];

Et puis, voici la simple fonction de rappel

- (void)hideKeyboard {
    [myTextField resignFirstResponder];
}

J'espère que ça aide

30
Sr.Richie

À mon avis:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];

    // pass touches up to viewController
    [self.nextResponder touchesBegan:touches withEvent:event];
}

Dans mon viewcontroller:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    UITouch *touch = [[event allTouches] anyObject];
    if (keyboardShown && [touch view] != self.TextView) 
    {
         [self.TextView resignFirstResponder];
    }
    [super touchesBegan:touches withEvent:event];
}

- (void)keyboardWasShown:(NSNotification*)aNotification
{    
        keyboardShown = YES;
}
7
tuzzolotron

Voici le code Swift 3

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    if let touch = touches.first {
        if textField.isFirstResponder && touch.view != textField {
            textField.resignFirstResponder()
        }
    }
    super.touchesBegan(touches, with: event)
}
2
mythicalcoder

Ceci est un ancien post, mais je mettais cette solution en œuvre lorsque j’ai trouvé quelque chose de beaucoup plus simple (peut-être qu’elle n’était pas disponible à cette époque).

[self.myTextView endEditing: YES];

J'utilise un UITableView, alors j'ai mis cette ligne sur la méthode didSelectRowAtIndexPath: . Jusqu'ici, tout va bien ...

2
Carlos B
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
    var touch = event.allTouches()?.anyObject() as UITouch

    if( textfield.isFirstResponder() && touch.view != textfield) {
        textfield.resignFirstResponder()
        NSLog("Resigning first responder since touches began outside")
    }

    super.touchesBegan(touches, withEvent: event)
}

la réponse d'Ohhorob a fonctionné pour moi aussi. Voici l'équivalent Swift simple. 

1
atomic_ice

Voici une meilleure solution qui ne dépend pas d'un point de vente et qui va fonctionner avec un nombre quelconque d'objets UITextField dans votre contrôleur. 

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    UITouch *touch = [[event allTouches] anyObject];

    if (![[touch view] isKindOfClass:[UITextField class]]) {
        [self.view endEditing:YES];
    }
    [super touchesBegan:touches withEvent:event];
}
1
Yas T.

Très facile

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self.view endEditing:YES];
}
1
Salim

Je voulais une version de ce logiciel qui résiste à toutes les vues sans nécessiter de points de vente spécifiques. Voici ma solution que je mets dans l'une de mes vues de conteneur standard.

Il utilise MonoTouch C #, mais il devrait être évident de le convertir en Objective-C.

    private void findAndResignFirstResponder(UIView node=null) {
        if (node == null) { return; }
        if (node.IsFirstResponder) {
            node.ResignFirstResponder();
            return;
        }

        foreach (UIView view in node.Subviews) {
            findAndResignFirstResponder(node:view);
        }
    }

    private bool haveDrag = false;
    public override void TouchesEnded(NSSet touches, UIEvent evt) {
        if (!haveDrag) {
            UITouch touch = (UITouch)evt.AllTouches.AnyObject;
            if (!touch.View.CanBecomeFirstResponder) {
                this.findAndResignFirstResponder(this);
                Console.WriteLine("resign");
            }
        }
        base.TouchesEnded (touches, evt);
    }
    public override void TouchesMoved(NSSet touches, UIEvent evt) {
        haveDrag = true;
        base.TouchesMoved (touches, evt);
    }

    public override void TouchesBegan(NSSet touches, UIEvent evt) {
        haveDrag = false;
        base.TouchesBegan (touches, evt);
    }
0
David Jeske

Ma façon de le faire ...

  • Ajoutez une référence à TextView dans la @interface de votre ViewController:

    @property (weak, nonatomic) IBOutlet UITextView *yourTextView;
    
  • Remplacez cette méthode dans la @implementation de votre ViewController:

    - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
    {
        if ([self.yourTextView isFirstResponder]) {
          [self.yourTextView resignFirstResponder];
        }
    }
    
0
Stefano Vettorazzi