Comment rejeter le clavier pour UITextView avec la touche de retour?
dans la bibliothèque de L'IB, l'introduction nous dit que lorsque la touche de retour est pressée, le clavier de UITextView
disparaîtra. Mais en fait la clé de retour ne peut agir que comme 'n'.
je peux ajouter un bouton et utiliser [txtView resignFirstResponder]
pour cacher le clavier.
mais y a-t-il un moyen d'ajouter l'action pour la touche de retour dans le clavier pour que je n'ai pas besoin d'ajouter UIButton
?
30 réponses
UITextView
n'a aucune méthode qui sera appelée lorsque l'utilisateur frappera la touche return. Si vous voulez que l'utilisateur puisse ajouter une seule ligne de texte, utilisez un UITextField
. Frapper le retour et cacher le clavier pour un UITextView
ne suit pas les directives de l'interface.
même si vous voulez faire cela, mettre en œuvre la textView:shouldChangeTextInRange:replacementText:
méthode de UITextViewDelegate
et dans ce vérifier si le texte de remplacement est \n
, masquer le clavier.
il y a peut-être d'autres moyens, mais je n'en connais aucun.
a pensé que je mettrais le snippet ici à la place:
assurez-vous de déclarer votre soutien au protocole UITextViewDelegate
.
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if([text isEqualToString:@"\n"]) {
[textView resignFirstResponder];
return NO;
}
return YES;
}
Swift 4.0 mise à jour:
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if text == "\n" {
textView.resignFirstResponder()
return false
}
return true
}
je sais que cela a déjà été répondu mais je n'aime pas vraiment utiliser la chaîne literal pour la nouvelle ligne donc 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;
}
Swift 4.0 mise à jour:
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
}
je sais que cela a été répondu beaucoup de fois, Mais voici mes deux cents à la question.
j'ai trouvé les réponses par samvermette et ribeto vraiment utile, et aussi le Commentaire par maxpower dans le ribeto 'S réponse. Mais il y a un problème avec ces approches. Le problème que matt mentionne, dans le samvermette réponse et c'est que si l'utilisateur veut coller quelque chose avec une rupture de ligne à l'intérieur, le clavier se cacherait sans coller quoi que ce soit.
ainsi mon approche est un mélange des trois solutions mentionnées ci-dessus et vérifiant seulement si la chaîne entrée est une nouvelle ligne quand la longueur de la chaîne est 1 donc nous nous assurons 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;
}
une façon plus élégante est de rejeter le clavier lorsque l'utilisateur tape quelque part en dehors du cadre du clavier.
tout d'abord, définissez la vue de votre ViewController à la classe "UIControl" dans l'inspecteur d'identité dans UIBuilder. Contrôle-Faites glisser la vue dans le fichier D'en-tête du ViewController et liez-la comme une action avec L'événement en tant que retouche à l'intérieur, tel que:
ViewController.h
-(IBAction)dismissKeyboardOnTap:(id)sender;
dans le ViewController principal fichier, ViewController.m:
-(IBAction)dismissKeyboardOnTap:(id)sender
{
[[self view] endEditing:YES];
}
vous pouvez avoir besoin d'un double robinet ou d'un long contact en utilisant des techniques similaires. Vous devrez peut-être configurer votre ViewController pour Qu'il soit un UITextViewDelegate et connecter le TextView au ViewController. Cette méthode fonctionne à la fois pour UITextView et UITextField.
Source: Big Nerd Ranch
EDIT: je voudrais aussi ajouter que si vous utilisez UIScrollView, la technique ci-dessus peut ne pas fonctionner aussi facilement par L'intermédiaire de L'Interface Builder. Dans ce cas, vous pouvez utiliser un UIGestureRecognizer et appeler la méthode endedediting:YES à la place. 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 tape à l'extérieur du clavier et ne touche pas d'espace d'entrée, le clavier sera rejeté.
ajouter cette méthode dans votre contrôleur de vue.
Swift :
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 être utile pour vous:
/**
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()
}
}
}
-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if([text isEqualToString:@"\n"])
[textView resignFirstResponder];
return YES;
}
yourtextView.delegate=self;
ajouter aussi UITextViewDelegate
N'oubliez pas de confirmer le protocole
si vous n'avez pas ajouté if([text isEqualToString:@"\n"])
vous ne pouvez pas modifier
il y a une autre solution en utilisant uitextview, Vous pouvez ajouter toolbar comme InputAccessoryView dans "textViewShouldBeginEditing", et à partir du bouton Fait de cette barre d'outils, vous pouvez rejeter clavier, le code pour cela est le suivant:
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 textviewdelegate méthode
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView
{
[textView setInputAccessoryView:toolBar];
return YES;
}
en action de bouton fait ce qui est dans la barre d'outils est le suivant:
-(IBAction)btnClickedDone:(id)sender
{
[self.view endEditing:YES];
}
j'ai trouvé la réponse par josebama pour être la réponse la plus complète et propre disponible dans ce fil.
ci-dessous est la syntaxe Swift 3 pour elle:
func textView(_ textView: UITextView, shouldChangeTextIn _: NSRange, replacementText text: String) -> Bool {
let resultRange = text.rangeOfCharacter(from: CharacterSet.newlines, options: .backwards)
if text.characters.count == 1 && resultRange != nil {
textView.resignFirstResponder()
// Do any additional stuff here
return false
}
return true
}
tout comme matt comment à samvermette, Je n'aime pas l'idée de détecter" \n " non plus. La touche "retour" est là pour une raison UITextView, c'est d'aller à la prochaine ligne de cours.
la meilleure solution à mon avis est d'imiter l'application de message iPhone - qui est d'ajouter barre d'outils (et bouton) sur le clavier.
j'ai obtenu le code de blog suivant:
http://www.iosdevnotes.com/2011/02/iphone-keyboard-toolbar/
Suit:
- ajouter barre d'outils à votre fichier XIB - régler la hauteur à 460
- ajouter l'article de la barre d'outils (si pas déjà ajouté). Si vous avez besoin de droite-alignez-le, Ajouter également élément de barre flexible à XIB, et déplacer l'élément de barre d'outils
- créer une action qui lie votre élément de bouton à resignfirtresponder comme suit:
- (IBAction)hideKeyboard:(id)sender {
[yourUITextView resignFirstResponder];
}
- puis:
- (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];
}
vient de résoudre ce problème d'une manière différente.
- créer un bouton qui sera placé en arrière-plan
- de L'Inspecteur D'attributs, changer le type de bouton à personnalisé, et le rend le bouton transparent.
- étendez le bouton pour couvrir toute la vue, et assurez-vous que le bouton est derrière tout l'autre objet. La manière simple de faire cela est de faire glisser le bouton en haut de la vue de liste dans la vue
-
contrôle Faites glisser le bouton vers le fichier
viewController.h
et créez une action (envoi de L'événement: retouche à l'intérieur) comme:(IBAction)ExitKeyboard:(id)sender;
-
Dans
ViewController.m
devrait ressembler à :(IBAction)ExitKeyboard:(id)sender { [self.view endEditing:TRUE]; }
- lancer app, et quand vous cliquez loin de la TextView, le clavier disparaît
Ajouter un observateur en viewDidLoad
[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(textViewKeyPressed:) name: UITextViewTextDidChangeNotification object: nil];
et ensuite utiliser 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 pour une touche de retour, mais je pense que c'est OK.
mise à JOUR
voir la réponse de ribto ci-dessous qui utilise [NSCharacterSet newlineCharacterSet]
au lieu de \n
utilisant le contrôleur de navigation pour héberger une barre pour rejeter le clavier:
dans le .h fichier:
UIBarButtonItem* dismissKeyboardButton;
dans le .m fichier:
- (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;
}
essayez ceci:
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{
if ([text isEqualToString:@"\n"]) {
[self.view endEditing:YES];
}
return YES;
}
/ / vous pouvez utiliser ceci ...
Étape 1. La première étape consiste à s'assurer que vous déclarez votre soutien au protocole UITextViewDelegate
. Ceci est 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 UITextView. En suivant l'exemple ci-dessus, voici comment j'ai initialisé le UITextView
avec EditorController
en tant 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 est de prendre des mesures en réponse au message shouldCahngeTextInRange
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;
}
swift
func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
if text == "\n" {
textView.resignFirstResponder()
}
return true
}
Code Swift
implémenter UITextViewDelegate dans votre classe / vue comme suit:
class MyClass: UITextViewDelegate { ...
placer le délégué de textView à l'auto
myTextView.delegate = self
et ensuite mettre en œuvre ce qui suit:
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 parce que ce n'est jamais une bonne idée de changer l'entrée de l'utilisateur dans un champ de texte pour un workarround et de ne pas réinitialiser l'état après le code de hack compléter.
vous pouvez également cacher le clavier lorsque vous touchez l'écran de vue:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch * touch = [touches anyObject];
if(touch.phase == UITouchPhaseBegan) {
[txtDetail resignFirstResponder];
}
}
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)
}
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;
}
Ok. 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 à la " N'Fin À la Sortie " événement Interface Builder
.
(cliquez-droit sur le TextField
et cntrl-faites glisser à partir d' ' N'fin à la sortie ' à la méthode suivante.
-(IBAction)hideTheKeyboard:(id)sender
{
[self.view endEditing:TRUE];
}
- (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;
}
+ (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;
}
}
la question demande comment le faire avec la touche de retour, mais je pense que cela pourrait aider quelqu'un avec l'intention de simplement faire disparaître le clavier en utilisant UITextView:
@IBOutlet weak var textView: UITextView!
private func addToolBarForTextView() {
let textViewToolbar: UIToolbar = UIToolbar()
textViewToolbar = UIBarStyle.Default
textViewToolbar = [
UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.Done, target: self, action: #selector(self.cancelInput)),
UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: self, action: nil),
UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Done, target: self, action: #selector(self.doneInput))
]
textViewToolbar()
self.textView.inputAccessoryView = textViewToolbar //do it for every relevant textView if there are more than one
}
func doneInput() {
self.textView.resignFirstResponder()
}
func cancelInput() {
self.textView.text = ""
self.textView.resignFirstResponder()
}
Appel addToolBarForTextView() dans le viewDidLoad ou à un autre du cycle de vie de la méthode.
il semble que c'était la solution parfaite pour moi.
Cheers,
Murat
-(BOOL)textFieldShouldReturn:(UITextField *)textField; // called from textfield (keyboard)
-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text; // good tester function - thanks
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 pour obtenir une réponse. Je suppose que d'autres partagent ce sentiment.
c'est ma variance du 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 le UITapGestureRecognizer lorsque le 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");
}
quand je tape en dehors de TextView, la vue se termine en mode édition et le UITapGestureRecognizer se supprime lui-même pour que je puisse continuer à interagir avec d'autres contrôles dans la vue.
-(void)tap:(UITapGestureRecognizer *)tapRec{
[[self view] endEditing: YES];
[self.view removeGestureRecognizer:tapRec];
NSLog(@"Tap recognized, tapRec getting removed");
}
j'espère que cela aidera. 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?
n'oubliez pas de définir le délégué pour le textView - sinon resignfirstresponder ne fonctionnera pas.
essayez ceci .
NSInteger lengthOfText = [[textView.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length];
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()
}
}
Mon hack pour cela :
1-Créer un bouton couvrant toute la vue; 2 - l'envoyer à l'arrière-plan de votre point de vue, 3-changer son Type de "Round Rect" en "Custom" dans L'attribut Inspector, 4 - créer une action 5-mettre en œuvre la méthode d'action:
- (IBAction)bgTouched:(id)sender
{
//to dismiss keyboard on bg btn pressed
[_userInput resignFirstResponder];
}
où _userInput est votre sortie TextField