Dans la bibliothèque d’IB, l’introduction nous dit que lorsque le return la touche est enfoncée, le clavier pour UITextView
disparaîtra. Mais en réalité le return la clé ne peut agir que comme '\ n'.
Je peux ajouter un bouton et utiliser [txtView resignFirstResponder]
pour masquer le clavier.
Mais y a-t-il moyen d'ajouter l'action pour le return touche dans le clavier afin que je n'ai pas besoin d'ajouter UIButton
?
UITextView
n'a aucune méthode qui sera appelée lorsque l'utilisateur appuiera sur la touche de retour. 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 instructions de l'interface.
Même dans ce cas, si vous voulez faire cela, implémentez la méthode textView:shouldChangeTextInRange:replacementText:
de UITextViewDelegate
et dans cette vérification, si le texte de remplacement est \n
, masquez le clavier.
Il y a peut-être d'autres moyens mais je n'en connais aucun.
Je me suis dit que je publierais l'extrait ici:
Assurez-vous de déclarer la prise en charge du protocole UITextViewDelegate
.
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if([text isEqualToString:@"\n"]) {
[textView resignFirstResponder];
return NO;
}
return YES;
}
Mise à jour de Swift 4.0:
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 trop utiliser le littéral chaîne 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;
}
Mise à jour de 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
}
Je sais que l’on a souvent répondu à cette question, mais voici mes deux points de vue.
J'ai trouvé les réponses par samvermette et ribeto vraiment utiles, ainsi que par le commentaire par maxpower dans les ribeto répondre. Mais il y a un problème avec ces approches. Le problème que matt mentionne dans la réponse de samvermette est que si l'utilisateur veut coller quelque chose avec un saut de ligne à l'intérieur, le clavier se cacherait sans rien coller.
Donc, mon approche est un mélange des trois solutions mentionnées ci-dessus et vérifie seulement si la chaîne entrée est une nouvelle ligne lorsque la longueur de la chaîne est égale à 1, afin de nous assurer 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 méthode plus élégante consiste à fermer le clavier lorsque l'utilisateur appuie quelque part en dehors du cadre du clavier.
Tout d'abord, définissez l'affichage 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 reliez-la sous forme d’action à l’événement Touch Up Inside, par exemple:
ViewController.h
-(IBAction)dismissKeyboardOnTap:(id)sender;
Dans le fichier ViewController principal, ViewController.m:
-(IBAction)dismissKeyboardOnTap:(id)sender
{
[[self view] endEditing:YES];
}
Vous pouvez exiger un double tap ou un toucher long en utilisant des techniques similaires. Vous devrez peut-être définir votre ViewController comme étant un UITextViewDelegate et connecter le TextView au ViewController. Cette méthode fonctionne à la fois pour UITextView et UITextField.
Source: Big Nerd Ranch
EDIT: J'aimerais également ajouter que si vous utilisez UIScrollView, la technique ci-dessus risque de ne pas fonctionner aussi facilement avec Interface Builder. Dans ce cas, vous pouvez utiliser un UIGestureRecognizer et appeler la méthode [[self view] endEditing: 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 appuie en dehors du clavier et ne touche pas un espace de saisie, le clavier est désactivé.
Ajoutez 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 aussi 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()
}
}
}
-(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 éditer
Il existe une autre solution lors de l’utilisation de uitextview: vous pouvez ajouter une barre d’outils en tant que InputAccessoryView dans "textViewShouldBeginEditing", et à partir du bouton Terminé de cette barre d’outils, vous pouvez ignorer le clavier. Le code correspondant est le suivant:
Dans 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 de Button Done qui se trouve dans la barre d’outils est la suivante:
-(IBAction)btnClickedDone:(id)sender
{
[self.view endEditing:YES];
}
J'ai trouvé la réponse par josebama comme étant la réponse la plus complète et la plus nette disponible dans ce fil.
Vous trouverez ci-dessous la syntaxe de 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
}
Utilisation du contrôleur de navigation pour héberger une barre permettant d’écarter 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;
}
Tout comme Matt comment to samvermette, je n’aime pas non plus l’idée de détecter "\ n". La touche "retour" existe pour une raison dans UITextView, à savoir aller à la ligne suivante.
La meilleure solution à mon avis consiste à imiter l'application de messagerie pour iPhone, qui consiste à ajouter une barre d'outils (et un bouton) sur le clavier.
J'ai eu le code de l'article suivant sur le blog:
http://www.iosdevnotes.com/2011/02/iphone-keyboard-toolbar/
Pas:
-Ajouter la barre d’outils à votre fichier XIB - définir la hauteur à 460
-Ajouter un élément de bouton de barre d’outils (s’il n’a pas déjà été ajouté). Si vous devez l'aligner à droite, ajoutez également un élément de bouton de barre flexible à XIB et déplacez l'élément de bouton de la barre d'outils.
-Créer une action qui lie votre élément de bouton à resignFirstResponder comme suit:
- (IBAction)hideKeyboard:(id)sender {
[yourUITextView resignFirstResponder];
}
-Ensuite:
- (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];
}
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.
UPDATE
Voir la réponse de ribto ci-dessous qui utilise [NSCharacterSet newlineCharacterSet]
à la place de \n
Juste résolu ce problème d'une manière différente.
Faites glisser le bouton dans le fichier viewController.h
et créez une action (Evénement envoyé: retouche à l'intérieur) comme:
(IBAction)ExitKeyboard:(id)sender;
Dans ViewController.m
devrait ressembler à:
(IBAction)ExitKeyboard:(id)sender {
[self.view endEditing:TRUE];
}
Essaye ça :
- (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 à vous assurer de déclarer le support du 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 reprenant l'exemple ci-dessus, voici comment j'ai initialisé la 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;
}
Etape 3. Et maintenant, la dernière pièce du puzzle consiste à 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;
}
Code rapide
Implémentez UITextViewDelegate dans votre classe/vue comme suit:
class MyClass: UITextViewDelegate { ...
définir le délégué textView sur auto
myTextView.delegate = self
Et puis implémentez 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 car ce n'est jamais une bonne idée de modifier la saisie de l'utilisateur dans un champ de texte par une solution de contournement et de ne pas réinitialiser l'état une fois le code de hack terminé.
D'accord. Tout le monde a donné 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 sur la TextField
et faites glisser tout en maintenant la touche 's'est terminée à la sortie.' vers la méthode suivante.
-(IBAction)hideTheKeyboard:(id)sender
{
[self.view endEditing:TRUE];
}
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)
}
Vous pouvez également masquer le clavier lorsque vous touchez dans l'écran de visualisation:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch * touch = [touches anyObject];
if(touch.phase == UITouchPhaseBegan) {
[txtDetail resignFirstResponder];
}
}
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;
}
La question demande comment 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 lors de l'utilisation de 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()
}
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
- (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;
}
}
Vous devez ajouter UIToolbar
en haut de la page UITextView pour simplifier la tâche plutôt que d'utiliser shouldChangeTextIn
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()
}
Je sais que ce n'est pas la réponse exacte à cette question, mais j'ai trouvé ce fil après avoir recherché une réponse sur Internet. Je suppose que les autres partagent ce sentiment.
C’est là ma variante du UITapGestureRecognizer que je trouve fiable et facile à utiliser - il suffit de définir le délégué de TextView sur ViewController.
Au lieu de ViewDidLoad, j'ajoute UITapGestureRecognizer lorsque TextView devient actif pour modification:
-(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 termine le mode d'édition et le UITapGestureRecognizer se supprime de lui-même afin 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 tellement évident, mais je n'ai jamais vu cette solution sur le Web. Est-ce que je fais quelque chose de mal?
N'oubliez pas de définir le délégué pour textView - sinon, resignfirstresponder ne fonctionnera pas.
Essaye ça .
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()
}
}