Jak zamknąć klawiaturę dla UITextView za pomocą klawisza Return?

381

W bibliotece IB wstęp mówi nam, że po returnnaciśnięciu klawisza klawiatura do UITextViewzniknie. Ale tak naprawdę returnklucz może działać tylko jako „\ n”.

Mogę dodać przycisk i użyć [txtView resignFirstResponder]do ukrycia klawiatury.

Ale czy istnieje sposób, aby dodać akcję dla returnklawisza na klawiaturze, aby nie trzeba było dodawać UIButton?

Chilly Zhong
źródło
Postępuj zgodnie z instrukcjami w tym poście na blogu: iphonedevelopertips.com/cocoa/…
ManojN

Odpowiedzi:

354

UITextViewnie ma żadnych metod, które zostaną wywołane, gdy użytkownik naciśnie klawisz powrotu. Jeśli chcesz, aby użytkownik mógł dodać tylko jeden wiersz tekstu, użyj UITextField. Naciśnięcie klawisza Return i ukrycie klawiatury dla UITextViewnie jest zgodne z wytycznymi interfejsu.

Nawet jeśli chcesz to zrobić, zaimplementuj textView:shouldChangeTextInRange:replacementText:metodę UITextViewDelegatei sprawdź, czy tekst zastępczy jest \n, ukryj klawiaturę.

Mogą być inne sposoby, ale nie znam ich.

lostInTransit
źródło
1
Dzięki, a metoda działa dobrze. Powodem korzystania z UITextView jest to, że może przechowywać tekst w wielu wierszach. A teraz używam go jako okna wiadomości.
Chilly Zhong,
28
Łatwo jest zmienić klucz powrotu na „zrobione” za pomocą jednego z narzędzi [textField setReturnKeyType: UIReturnKeyDone];lub konstruktora interfejsów
Casebash
9
Dobra, teraz rozumiem, że Apple kończąc z wielowierszowym polem tekstowym to dodać gotowe do paska menu
Casebash
7
Nie jest to dobry sposób na rozwiązanie tego problemu, ponieważ ograniczasz możliwość używania klawisza Enter do wychodzenia z klawiatury. Prawdopodobnie najlepszym sposobem jest dodanie przycisku uruchamiającego metodę resignFirstResponder.
Ele
5
@Casebash. Wygląda na to, że ustawienie klawisza Return na „done” nie rozwiązuje problemu w Xcode 6.4, Swift 2.0. Ustawiam klucz za pomocą IB.
MB_iOSDeveloper
504

Pomyślałem, że zamiast tego opublikuję fragment kodu tutaj:

Upewnij się, że deklarujesz wsparcie dla UITextViewDelegateprotokołu.

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

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

    return YES;
}

Aktualizacja Swift 4.0:

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    if text == "\n" {
        textView.resignFirstResponder()
        return false
    }
    return true
}
samvermette
źródło
75
Problem polega na tym, że tak naprawdę nie jest to sposób na wykrycie, że użytkownik nacisnął klawisz powrotu . Użytkownik może wkleić znak zwrotny w polu tekstowym, a otrzymasz tę samą wiadomość delegowaną. Zasadniczo niewłaściwie używasz widoku tekstu. Sposobem na zwolnienie klawiatury jest (1) całkowite zaniechanie tego (np. Podczas tworzenia wiadomości w aplikacji Mail) lub (2), aby mieć przycisk Gotowe w innym miejscu interfejsu (jak w aplikacji Notatki). Możesz na przykład dołączyć taki przycisk jako widok akcesoriów do klawiatury.
mat.
@ Sam V, ten fragment był fajnym człowiekiem. mi to pasuje. dzięki tonie człowieku. Czy istnieje jakiś fragment kodu służący do rozproszenia klawiatury numerycznej? pozdrowienia shishir
Shishir.bobby
Wspaniały. Przypomnienie, że w niektórych sytuacjach, aby pozbyć się klawiatury, spróbuj postępować zgodnie z instrukcjami ... [self.view endEditing: YES];
Fattie,
@Vojto, działa dobrze na iPadzie. Prawdopodobnie nie ustawiłeś delegata.
Vincent
4
Problem polega na tym, że klawiatura może ukrywać część interfejsu używanego do zamykania. To absurdalne, że IOS nie ma przycisku na każdej klawiaturze przeznaczonego do zwolnienia klawiatury, więc użytkownik może to zrobić, jeśli chce.
Sani Elfishawy
80

Wiem, że już na nie odpowiedziano, ale tak naprawdę nie lubię używać literału łańcuchowego dla nowej linii, więc oto co zrobiłem.

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

    [txtView resignFirstResponder];
    return NO;
}

Aktualizacja 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
źródło
6
Mógłbym to zmodyfikować w następujący sposób: NSRange resultRange = [zakres tekstuOfCharacterFromSet: [NSCharacterSet newlineCharacterSet] opcje: NSBackwardsSearch]; Ponieważ i tak jest to hack, wydaje się, że sprawdzanie końca łańcucha pod kątem powrotu może być bezpieczniejszą trasą.
maxpower
@maxpower Bardzo dobry komentarz. Lepiej też sprawdzić z zastąpionym tekstem, np NSString *replacedText = [textView.text stringByReplacingCharactersInRange:range withString:text].
Rudolf Adamkovič
Wyobraź sobie, że użytkownik wkleja tekst skopiowany z innego miejsca, który zawiera nowy wiersz. Prawdopodobnie byliby zdezorientowani, gdy zamiast dodawać tekst, aplikacja po prostu zwalnia klawiaturę.
Nikolai Ruhe,
44

Wiem, że udzielono na nie odpowiedzi wiele razy, ale oto moje dwa centy na ten temat.

Bardzo przydatne okazały się odpowiedzi samvermette i ribeto , a także komentarz maxpower w ribeto . Ale z tymi podejściami jest problem. Problem, o którym Matt wspomina w samvermette , i to, że jeśli użytkownik chce wkleić coś z linią w środku, klawiatura ukryłaby się bez wklejania czegokolwiek.

Więc moje podejście jest mieszanką trzech wyżej wymienionych rozwiązań i sprawdzanie tylko, czy wprowadzony ciąg znaków jest nową linią, gdy długość łańcucha wynosi 1, więc upewniamy się, że użytkownik pisze zamiast wklejać.

Oto co zrobiłem:

- (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
źródło
To najlepsze rozwiązanie tego problemu. Odpowiedź samvermette nie uwzględnia sytuacji, w której użytkownik chce wkleić tekst.
marcopaivaf,
36

Bardziej eleganckim sposobem jest zwolnienie klawiatury, gdy użytkownik stuknie gdzieś poza ramkę klawiatury.

Najpierw ustaw widok ViewController na klasę „UIControl” w inspektorze tożsamości w UIBuilder. Przeciągnij z wciśniętym klawiszem Control do pliku nagłówka ViewController i połącz go jako akcję ze zdarzeniem jako Touch Up Inside, na przykład:

ViewController.h

-(IBAction)dismissKeyboardOnTap:(id)sender;

W głównym pliku ViewController ViewController.m:

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

Możesz wymagać podwójnego stuknięcia lub długiego dotyku przy użyciu podobnych technik. Może być konieczne ustawienie ViewController jako UITextViewDelegate i połączenie TextView z ViewController. Ta metoda działa zarówno dla UITextView, jak i UITextField.

Źródło: Big Nerd Ranch

EDYCJA: Chciałbym również dodać, że jeśli używasz UIScrollView, powyższa technika może nie działać tak łatwo przez Konstruktora interfejsów. W takim przypadku możesz użyć UIGestureRecognizer i zamiast tego wywołać metodę [[self view] endEditing: YES]. Przykładem może być:

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

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

Gdy użytkownik stuknie poza klawiaturę i nie dotknie miejsca na wejście, klawiatura się odrzuci.

TMilligan
źródło
1
Podoba mi się pomysł, GestureRecognizerale dużym problemem jest to, że nie można już klikać wszystkich przycisków ani kontroli w widoku.
ekspert
34

Dodaj tę metodę do kontrolera widoku.

Szybki :

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

Ta metoda może być również pomocna dla Ciebie:

/**
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
źródło
2
Nie zapomnij potwierdzić protokołu UITextViewDelegate :)
swiftBoy
Nie sądzę, że dobrym pomysłem jest przesłonięcie dotyku Rozpocznij i nie rozmawiaj super.touchesBegan(touches:withEvent:).
TGO
Aby wyrazić symetryczny charakter tego kodu, powinieneś napisać else { return true }.
znaczenie-ma znaczenie
@ znaczenie nie ma znaczenia
Alexander Volkov
@AlexanderVolkov Nie zgadzasz się, że to symetryczna sytuacja, nie wiesz, co mam na myśli, nie wierzysz w wartość semantycznie poprawnego kodu lub ...?
znaczenie-ważne
26
-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
    if([text isEqualToString:@"\n"])
        [textView resignFirstResponder];
    return YES;
}

yourtextView.delegate=self;

Dodaj także UITextViewDelegate

Nie zapomnij potwierdzić protokołu

JEŚLI nie dodałeś if([text isEqualToString:@"\n"]), nie możesz edytować

Vineesh TP
źródło
2
-1 To tylko gorsza wersja odpowiedzi na samvermette. Przegapiłeś powrót, NOjeśli tekst jest równy @"\n".
devios1
17

Istnieje inne rozwiązanie podczas korzystania z uitextview. Możesz dodać pasek narzędzi jako InputAccessoryView w „textViewShouldBeginEditing”, a po zakończeniu przycisku tego paska narzędzi możesz zamknąć klawiaturę, kod tego jest następujący:

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

W metodzie textviewdelegate

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

W działaniu przycisku Gotowe znajdującego się na pasku narzędzi jest:

-(IBAction)btnClickedDone:(id)sender
{
    [self.view endEditing:YES];
}
g212gs
źródło
17

Znalazłem odpowiedź josebama na najbardziej kompletną i czystą odpowiedź dostępną w tym wątku.

Poniżej znajduje się dla niego składnia 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
}
Puneet Kohli
źródło
Te resultRangemają na celu sprawdzenie, czy tekst zawiera tylko znaki nowej linii, który unika ciężkiej kodu „\ n”.
Qinghua,
6

szybki

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

i skonfiguruj

Eduardo Oliveros Acosta
źródło
Skąd ten zrzut ekranu?
Sam
6

Użycie kontrolera nawigacyjnego do obsługi paska do zwolnienia klawiatury:

w pliku .h:

UIBarButtonItem* dismissKeyboardButton;

w pliku .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
źródło
5

Podobnie jak matowy komentarz do samvermette, nie podoba mi się pomysł wykrycia „\ n”. Klawisz „return” istnieje z jakiegoś powodu w UITextView, to znaczy, aby przejść oczywiście do następnego wiersza.

Moim zdaniem najlepszym rozwiązaniem jest naśladowanie aplikacji do przesyłania wiadomości iPhone'a - dodawanie paska narzędzi (i przycisku) na klawiaturze.

Mam kod z następującego postu na blogu:

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

Kroki:

-Dodaj pasek narzędzi do pliku XIB - ustaw wysokość na 460

-Dodaj przycisk na pasku narzędzi (jeśli jeszcze nie został dodany). Jeśli chcesz wyrównać do prawej, dodaj również element przycisku paska elastycznego do XIB i przesuń element przycisku paska narzędzi

-Utwórz akcję łączącą element przycisku, aby zrezygnować z usługi FirstResponder w następujący sposób:

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

-Następnie:

- (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];
}
przyjacielu
źródło
Poza tematem. Chociaż Twoje rozwiązanie jest eleganckie, nie odpowiada na pierwotne pytanie: „Jak zamknąć klawiaturę dla UITextView za pomocą klawisza Return?”. Zdarzają się sytuacje, w których UITextView wykorzystuje się do symulacji zawijania słów UITextField, a nie do wprowadzania wielu wierszy.
SwiftArchitect
2
Chociaż jest to nie na temat, jest bardzo przydatne. Chcę również, aby UITextView był wprowadzany z wieloma wierszami i wyłączał klawiaturę, kiedy chcę.
Yeung
5

Właśnie rozwiązałem ten problem w inny sposób.

  • Utwórz przycisk, który zostanie umieszczony w tle
  • W Inspektorze atrybutów zmień typ przycisku na niestandardowy, a przycisk będzie przezroczysty.
  • Rozwiń przycisk, aby objąć cały widok, i upewnij się, że przycisk znajduje się za wszystkimi innymi obiektami. Prostym sposobem na to jest przeciągnięcie przycisku na górę listy w widoku
  • Sterowanie przeciągnij przycisk do viewController.hpliku i utwórz akcję (Wysłane zdarzenie: retusz wewnątrz), na przykład:

    (IBAction)ExitKeyboard:(id)sender;
  • W ViewController.mpowinna wyglądać następująco:

    (IBAction)ExitKeyboard:(id)sender {
        [self.view endEditing:TRUE];
    }
  • Uruchom aplikację, a gdy klikniesz poza TextView, klawiatura znika
Uvichy
źródło
Musisz także dodać: - (void) textViewDidEndEditing: (UITextView *) textView {[self.TextView resignFirstResponder]; }
samouray,
5

Dodaj obserwatora w viewDidLoad

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

a następnie użyj selektora, aby sprawdzić „\ n”

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

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

Używa „\ n” i nie sprawdza specjalnie klucza powrotnego, ale myślę, że to jest OK.

AKTUALIZACJA

Zobacz odpowiedź ribto poniżej, która używa [NSCharacterSet newlineCharacterSet]zamiast\n

Todd B.
źródło
BŁĄD używa, \na klucz powrotu jest wykrywany na podstawie, \nwięc sprawdza klucz powrotu. Jedyną różnicą jest to, że używasz powiadomień, a nie textViewDelegates.
GoodSp33d
Teraz myślę, że sprawdzanie [NSCharacterSet newlineCharacterSet]zamiast \ n może być lepszym sposobem.
ToddB
5

Kod SWIFT

Zaimplementuj UITextViewDelegate w swojej klasie / widoku w następujący sposób:

class MyClass: UITextViewDelegate  { ...

ustaw delegata textView na siebie

myTextView.delegate = self

A następnie zaimplementuj następujące:

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

EDYCJA Zaktualizowałem kod, ponieważ nigdy nie jest dobrym pomysłem zmiana danych wprowadzanych przez użytkownika w polu tekstowym na obejście problemu i nie resetowanie stanu po zakończeniu hakowania.

Frithjof Schaefer
źródło
4

Spróbuj tego :

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

    return YES;

}
Nabil El
źródło
4

// Możesz użyć tego ...

Krok 1. Pierwszym krokiem jest upewnienie się, że deklarujesz obsługę UITextViewDelegateprotokołu. Odbywa się to w pliku nagłówka, na przykład tutaj jest nagłówek o nazwie

EditorController.h:

@interface EditorController : UIViewController  {
  UITextView *messageTextView;
}

@property (nonatomic, retain) UITextView *messageTextView;

@end

Krok 2. Następnie musisz zarejestrować kontroler jako delegat UITextView. Kontynuując powyższy przykład, oto jak zainicjowałem za UITextViewpomocą EditorControllerjako delegata…

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

Krok 3. A teraz ostatnim elementem układanki jest podjęcie działań w odpowiedzi na shouldCahngeTextInRangewiadomość w następujący sposób:

- (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
źródło
3

Możesz także ukryć klawiaturę, dotykając ekranu widoku:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
     UITouch * touch = [touches anyObject];
     if(touch.phase == UITouchPhaseBegan) {
        [txtDetail resignFirstResponder];
      }
 }
Hitesh Vaghela
źródło
IMHO, jest to bardzo dobre podejście, znacznie lepsze niż w przypadku przycisku, który zasłania cały widok.
WebOrCode
3

Szybka odpowiedź:

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

func tap(sender: UITapGestureRecognizer) {
    view.endEditing(true)
}
Glauco Neves
źródło
3

Użyłem tego kodu do zmiany respondera.

 - (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
źródło
dlaczego nie użyć [self.view endEditing: YES]; pewnego razu??
ajay_nasa,
3

Pytanie brzmi, jak to zrobić za pomocą klawisza Return, ale myślę, że może to pomóc komuś, kto chce po prostu zniknąć z klawiatury podczas korzystania z 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()
}

Zadzwoń addToolBarForTextView () w viewDidLoad lub innej metody cyklu życia.

Wydaje się, że było to dla mnie idealne rozwiązanie.

Twoje zdrowie,

Murat

Murat Yasar
źródło
1
W 2019 r. Teraz kopiuj i wklej, bez błędów składniowych i bieżącego nazewnictwa
Fattie,
1
zdecydowanie najlepsza odpowiedź tutaj. Właśnie naprawiłem prosty błąd składniowy, oczywiście edytuj, jak chcesz. Dzięki!
Fattie
2

Ok. Wszyscy udzielają odpowiedzi za pomocą sztuczek, ale myślę, że właściwym sposobem jest osiągnięcie tego celu

Łączenie następującej akcji ze zdarzeniem „ Did End On Exit ” w Interface Builder. (kliknij prawym przyciskiem myszy TextFieldi przeciągnij cntrl z „ Did end on exit ” na następującą metodę.

-(IBAction)hideTheKeyboard:(id)sender
{
    [self.view endEditing:TRUE];
}
carbonr
źródło
6
-1 Pytanie dotyczy UITextView, a nie UITextField, mój przyjacielu
Yogi
2
większość tych odpowiedzi jest tutaj z głosami, ponieważ pasuje do różnych scenariuszy różnych programistów.
carbonr
Jeśli używasz UITextField, jest to sposób na zrobienie tego. BTW, powinieneś użyć TAK / NIE dla BOOL-ów Objective-C, a nie PRAWDA / FAŁSZ.
Jon Shier
1
@jshier: PRAWDA / FAŁSZ jest również OK
Jogowie
2

Podobne do innych odpowiedzi przy użyciu, UITextViewDelegateale nowszego szybkiego interfejsu, isNewlinebyłoby:

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
źródło
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
źródło
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
źródło
0

Wiem, że to nie jest dokładna odpowiedź na to pytanie, ale znalazłem ten wątek po przeszukaniu Internetu w poszukiwaniu odpowiedzi. Zakładam, że inni podzielają to uczucie.

Jest to moja odmiana UITapGestureRecognizer, który uważam za niezawodny i łatwy w użyciu - wystarczy ustawić delegata TextView na ViewController.

Zamiast ViewDidLoad dodaję UITapGestureRecognizer, gdy TextView staje się aktywny do edycji:

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

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

Kiedy stukam poza TextView, widok kończy tryb edycji, a UITapGestureRecognizer usuwa się, dzięki czemu mogę kontynuować interakcję z innymi kontrolkami w widoku.

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

Mam nadzieję, że to pomoże. Wydaje się to takie oczywiste, ale nigdy nie widziałem tego rozwiązania w Internecie - czy robię coś złego?

BGC
źródło
0

Nie zapomnij ustawić delegata dla textView - w przeciwnym razie rezygnacja z pierwszego korespondenta nie zadziała.

Ron Holmes
źródło
0

Spróbuj tego .

NSInteger lengthOfText = [[textView.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length];
Hiren Panchal
źródło
0

Dla 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
źródło
0

Powinieneś dodać UIToolbar do góry UITextView, aby było łatwiejsze niż używanieshouldChangeTextIn

W 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
źródło
Zdecydowanie najlepsze rozwiązanie. Zauważ, że zamiast ustawiać ramkę, po prostu użyjtoolbar.sizeToFit()
Fattie