Как убрать клавиатуру для UITextView с ключом возврата?
В библиотеке IB введение говорит нам, что при нажатии клавиши return клавиатура для UITextView
исчезнет. Но на самом деле клавиша return может действовать только как \n.
Я могу добавить кнопку и использовать [txtView resignFirstResponder]
чтобы скрыть клавиатуру.
Но есть ли способ добавить действие для клавиши return на клавиатуре, чтобы мне не нужно было добавлять UIButton
?
Ответы
Ответ 1
UITextView
не имеет методов, которые будут вызываться, когда пользователь нажимает на возвращаемый ключ. Если вы хотите, чтобы пользователь мог добавлять только одну строку текста, используйте UITextField
. Нажатие на возврат и скрытие клавиатуры для UITextView
не соответствует рекомендациям интерфейса.
Даже если вы хотите это сделать, примените метод textView:shouldChangeTextInRange:replacementText:
UITextViewDelegate
и в этом случае проверьте, есть ли текст замены \n
, скройте клавиатуру.
Могут быть другие способы, но я не знаю о них.
Ответ 2
Я подумал, что вместо этого выложу фрагмент:
Убедитесь, что вы объявили о поддержке протокола UITextViewDelegate
.
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if([text isEqualToString:@"\n"]) {
[textView resignFirstResponder];
return NO;
}
return YES;
}
Обновление Swift 4.0:
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if text == "\n" {
textView.resignFirstResponder()
return false
}
return true
}
Ответ 3
Я знаю, что на это уже был дан ответ, но мне не очень нравится использовать строковый литерал для новой строки, вот что я сделал.
- (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:
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
}
Ответ 4
Я знаю, что на это ответили много раз, но вот мои два цента в этом вопросе.
Я нашел ответы samvermette и ribeto действительно полезными, а также комментарий maxpower в ответе ribeto. Но есть проблемы с этими подходами. Проблема в том, что matt упоминает в ответе samvermette, и это означает, что если пользователь хочет вставить что-то с линией перерыв внутри, клавиатура скроется, не вставляя ничего.
Итак, мой подход представляет собой смесь трех вышеупомянутых решений и проверяет, является ли введенная строка новой строкой, когда длина строки равна 1, поэтому мы проверяем, что пользователь вводит текст вместо вставки.
Вот что я сделал:
- (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;
}
Ответ 5
Более элегантный способ заключается в том, чтобы убрать клавиатуру, когда пользователь удаляет где-то вне рамки клавиатуры.
Сначала установите представление ViewController в класс "UIControl" в инспекторе идентификации в UIBuilder. Control-перетащите представление в заголовочный файл ViewController и свяжите его как действие с событием как Touch Up Inside, например:
ViewController.h
-(IBAction)dismissKeyboardOnTap:(id)sender;
В главном файле ViewController ViewController.m:
-(IBAction)dismissKeyboardOnTap:(id)sender
{
[[self view] endEditing:YES];
}
Вы можете потребовать двойной кран или длинное касание, используя аналогичные методы. Вам может потребоваться настроить ваш ViewController как UITextViewDelegate и подключить TextView к ViewController. Этот метод работает как для UITextView, так и для UITextField.
Источник: Big Nerd Ranch
EDIT: Я также хотел бы добавить, что если вы используете UIScrollView, описанная выше техника может работать не так легко через Interface Builder. В этом случае вы можете использовать UIGestureRecognizer и вызывать в нем метод [[self view] endEditing: YES]. Примером может служить:
-(void)ViewDidLoad{
....
UITapGestureRecognizer *tapRec = [[UITapGestureRecognizer alloc]
initWithTarget:self action:@selector(tap:)];
[self.view addGestureRecognizer: tapRec];
....
}
-(void)tap:(UITapGestureRecognizer *)tapRec{
[[self view] endEditing: YES];
}
Когда пользователь выходит за пределы клавиатуры и не нажимает пространство ввода, клавиатура будет упущена.
Ответ 6
Добавьте этот метод в свой контроллер.
Swift
func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
if text == "\n" {
textView.resignFirstResponder()
return false
}
return true
}
Этот метод также может быть полезен для вас:
/**
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()
}
}
}
Ответ 7
-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if([text isEqualToString:@"\n"])
[textView resignFirstResponder];
return YES;
}
yourtextView.delegate=self;
Также добавьте UITextViewDelegate
Не забудьте подтвердить протокол
Если вы не добавили, if([text isEqualToString:@"\n"])
вы не можете редактировать
Ответ 8
Существует еще одно решение при использовании с uitextview,
Вы можете добавить панель инструментов в качестве InputAccessoryView в "textViewShouldBeginEditing", и с помощью этой кнопки на панели инструментов вы можете отключить клавиатуру, код для этого следующий:
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]];
В методе textviewdelegate
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView
{
[textView setInputAccessoryView:toolBar];
return YES;
}
В действии кнопки "Готово", которая находится на панели инструментов, выполняется следующее:
-(IBAction)btnClickedDone:(id)sender
{
[self.view endEditing:YES];
}
Ответ 9
Я нашел ответ Джозебамы самым полным и чистым ответом, доступным в этой теме.
Ниже приведен синтаксис 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
}
Ответ 10
Использование контроллера навигации для размещения панели для отклонения клавиатуры:
в .h файле:
UIBarButtonItem* dismissKeyboardButton;
в .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;
}
Ответ 11
Как и матовый комментарий к samvermette, мне не нравится идея обнаружения "\n". Ключ "возврат" существует по какой-либо причине в UITextView, то есть идти к следующей строке, конечно.
Лучшим решением, на мой взгляд, является подражание приложению для iPhone-сообщений - это добавить панель инструментов (и кнопку) на клавиатуре.
Я получил код из следующего сообщения в блоге:
http://www.iosdevnotes.com/2011/02/iphone-keyboard-toolbar/
Шаги:
-Добавить панель инструментов к вашему XIB файлу - установить высоту до 460
-Добавить элемент панели инструментов (если он еще не добавлен). Если вам нужно выровнять по правому краю, добавьте в XIB элемент гибкой панели, и переместите элемент кнопки на панели инструментов
-Создайте действие, которое связывает ваш элемент кнопки с resignFirstResponder следующим образом:
- (IBAction)hideKeyboard:(id)sender {
[yourUITextView resignFirstResponder];
}
-Тогда:
- (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];
}
Ответ 12
Добавить наблюдателя в viewDidLoad
[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(textViewKeyPressed:) name: UITextViewTextDidChangeNotification object: nil];
а затем используйте селектор для проверки "\n"
-(void) textViewKeyPressed: (NSNotification*) notification {
if ([[[notification object] text] hasSuffix:@"\n"])
{
[[notification object] resignFirstResponder];
}
}
Он использует "\n" и специально не проверяет ключ возврата, но я думаю, что все в порядке.
UPDATE
См. ниже приведенный ниже ответ, который использует [NSCharacterSet newlineCharacterSet]
вместо \n
Ответ 13
Просто решить эту проблему по-другому.
- Создайте кнопку, которая будет помещена в фоновом режиме
- В инспекторе атрибутов измените тип кнопки на пользовательский, и кнопка станет прозрачной.
- Разверните кнопку, чтобы закрыть весь вид, и убедитесь, что кнопка находится за всем другим объектом. Легкий способ сделать это - перетащить кнопку в верхнюю часть списка в представлении
-
Управляйте перетаскиванием кнопки в файл viewController.h
и создайте действие (отправленное событие: коснитесь внутри), например:
(IBAction)ExitKeyboard:(id)sender;
-
В ViewController.m
должно выглядеть так:
(IBAction)ExitKeyboard:(id)sender {
[self.view endEditing:TRUE];
}
- Запустить приложение, и когда вы нажимаете кнопку "TextView", клавиатура исчезает.
Ответ 14
Попробуйте следующее:
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{
if ([text isEqualToString:@"\n"]) {
[self.view endEditing:YES];
}
return YES;
}
Ответ 15
Swift Code
Реализовать UITextViewDelegate в своем классе/Посмотреть так:
class MyClass: UITextViewDelegate { ...
установите делегат textView в self
myTextView.delegate = self
И затем выполните следующее:
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()
}
}
}
}
ИЗМЕНИТЬ
Я обновил код, потому что никогда не рекомендуется менять ввод пользователя в текстовое поле для рабочего стола и не восстанавливать состояние после завершения кода взлома.
Ответ 16
//Вы можете использовать это...
Шаг 1. Первым шагом будет убедиться, что вы объявляете поддержку протокола UITextViewDelegate
. Это делается в вашем файле заголовка, например, здесь заголовок
EditorController.h:
@interface EditorController : UIViewController {
UITextView *messageTextView;
}
@property (nonatomic, retain) UITextView *messageTextView;
@end
Шаг 2. Затем вам нужно будет зарегистрировать контроллер как делегат UITextViews. Продолжая из приведенного выше примера, вот как я инициализировал UITextView
с EditorController
в качестве делегата...
- (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;
}
Шаг 3. И теперь последний фрагмент головоломки должен принять действие в ответ на сообщение shouldCahngeTextInRange
следующим образом:
- (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;
}
Ответ 17
быстры
func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
if text == "\n" {
textView.resignFirstResponder()
}
return true
}
![и настроить]()
Ответ 18
Ok. Каждый дал ответы с трюками, но я думаю, что правильный способ достичь этого -
Подключение следующего действия к событию Завершить выход "в Interface Builder
.
(щелкните правой кнопкой мыши по элементу TextField
и cntrl-drag от << → до конца до следующего метода.
-(IBAction)hideTheKeyboard:(id)sender
{
[self.view endEditing:TRUE];
}
Ответ 19
Вы также можете скрыть клавиатуру при касании в окне просмотра:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch * touch = [touches anyObject];
if(touch.phase == UITouchPhaseBegan) {
[txtDetail resignFirstResponder];
}
}
Ответ 20
Быстрый ответ:
override func viewDidLoad() {
super.viewDidLoad()
let tapGestureReconizer = UITapGestureRecognizer(target: self, action: "tap:")
view.addGestureRecognizer(tapGestureReconizer)
}
func tap(sender: UITapGestureRecognizer) {
view.endEditing(true)
}
Ответ 21
Я использовал этот код для изменения ответчика.
- (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;
}
Ответ 22
- (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;
}
Ответ 23
+ (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;
}
}
Ответ 24
Вопрос задает вопрос, как это сделать с помощью ключа возврата, но я думаю, что это может помочь кому-то с намерением просто отключить клавиатуру при использовании 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()
}
Вызвать addToolBarForTextView() в viewDidLoad или какой-либо другой метод жизненного цикла.
Кажется, это было идеальным решением для меня.
Приветствия,
Мурат
Ответ 25
-(BOOL)textFieldShouldReturn:(UITextField *)textField; // called from textfield (keyboard)
-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text; // good tester function - thanks
Ответ 26
Я знаю, что это не точный ответ на этот вопрос, но я нашел эту нить после поиска в Интернете ответа. Я предполагаю, что другие разделяют это чувство.
Это моя дисперсия UITapGestureRecognizer, которую я считаю надежной и простой в использовании - просто установите делегат TextView в ViewController.
Вместо ViewDidLoad я добавляю UITapGestureRecognizer, когда TextView становится активным для редактирования:
-(void)textViewDidBeginEditing:(UITextView *)textView{
_tapRec = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap:)];
[self.view addGestureRecognizer: _tapRec];
NSLog(@"TextView Did begin");
}
Когда я выхожу за пределы TextView, вид прекращает режим редактирования, а UITapGestureRecognizer удаляет себя, поэтому я могу продолжить взаимодействие с другими элементами управления в представлении.
-(void)tap:(UITapGestureRecognizer *)tapRec{
[[self view] endEditing: YES];
[self.view removeGestureRecognizer:tapRec];
NSLog(@"Tap recognized, tapRec getting removed");
}
Надеюсь, это поможет. Это кажется настолько очевидным, но я никогда не видел этого решения нигде в Интернете - я что-то делаю неправильно?
Ответ 27
Не забудьте установить делегат для textView - иначе resignfirstresponder не будет работать.
Ответ 28
Попробуйте это.
NSInteger lengthOfText = [[textView.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length];
Ответ 29
Для 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()
}
}
Ответ 30
Мой взломать для этого:
1- создать кнопку, охватывающую весь вид;
2- отправьте его на задний план,
3- измените тип "Круглый Rect" на "Custom" в Инспекторе атрибутов,
4- создать действие
5- выполните метод действия:
- (IBAction)bgTouched:(id)sender
{
//to dismiss keyboard on bg btn pressed
[_userInput resignFirstResponder];
}
где _userInput - это ваша текстовая панель