Закройте клавиатуру, коснувшись фона UITableView

105

У меня кот UITableViewс UITextFieldтенью клетки. Я хотел бы убрать клавиатуру, когда заден фон UITableView. Я пытаюсь сделать это, создав UIButtonразмер UITableViewи поместив его за UITableView. Единственная проблема заключается в том, что UIButtonон улавливает все касания, даже если касание находится в UITableView. Что я делаю не так?

Спасибо!

Хуа-Инь
источник
Повторяющиеся вопросы и ответы: Q1 , Q2 , Q3 .
Янтао Се
Это лучший ответ stackoverflow.com/a/12851794/1418457
onmyway133 02

Ответы:

203

Это легко сделать, создав объект UITapGestureRecognizer (по умолчанию он будет обнаруживать «жест» при однократном касании, поэтому дальнейшая настройка не требуется), указав цель / действие при срабатывании жеста, а затем прикрепив объект распознавателя жестов к вашему виду таблицы.

Например, возможно, в вашем viewDidLoadметоде:

UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard)];
[self.tableView addGestureRecognizer:gestureRecognizer];

И hideKeyboardметод может выглядеть так:

- (void) hideKeyboard {
    [textField1 resignFirstResponder];
    [textField2 resignFirstResponder];
    ...
    ...
}

Обратите внимание, что жест не срабатывает при касании внутри UITextFieldобъекта. Он запускается, хотя на UITableViewфоне, в нижнем колонтитуле, в виде заголовка, UILabelsвнутри ячеек и т. Д.

Mixja
источник
4
Когда я попробовал это, я обнаружил, что это мешает таблице выбирать ячейки :(. Отличное решение в противном случае
Брайан
109
Как gestureRecognizer.cancelsTouchesInView = NO;
указано
3
И не забудьте отпустить gestureRecognizer после того, как он будет прикреплен к tableView.
Пол Линч
39
Для hideKeyboardметода, вместо того, чтобы общаться напрямую с текстовыми полями, вы можете это сделать [self.view endEditing:NO];. Из документов Apple: « Этот метод просматривает текущее представление и его иерархию вложенных представлений для текстового поля, которое в настоящее время является первым респондентом. Если он находит его, он просит это текстовое поле отказаться от роли первого респондента. Если для параметра force установлено значение ДА, текстовое поле даже не запрашивается; оно вынуждено уйти в отставку. "
Gobot
1
при использовании этого метода мой метод didSelectRowAtIndexPath не вызывается. любое решение для этого ??
uniruddh 07
127

Решение UITapGestureRecognizer работает с выбором ячейки таблицы, если вы установили:

gestureRecognizer.cancelsTouchesInView = NO;
Азбуки
источник
1
Это позволяет прикоснуться к ячейке, но жест также распознается, возможно, нам стоит реализовать эти методы делегатаshouldReceiveTouch
onmyway133 02
61

Вот лучший способ сделать это. Просто сделай это

[self.view endEditing:YES];

или

[[self.tableView superView] endEditing:YES];
Саад
источник
где мне поместить этот код? извините, я новичок. И, пожалуйста, предоставьте быстрый код.
Джон
54

Вы также можете сделать это из раскадровки: введите описание изображения здесь

Бен
источник
1
Что бы я ни выбрал: «Отклонить при перетаскивании», «Отклонить в интерактивном режиме», когда я касаюсь ячейки таблицы, она выбирается. Я использую Xcode 8, swift 3. пожалуйста, помогите
Джон
22

Как UITableViewи подкласс UIScrollView, реализация одного метода делегата ниже обеспечивает чрезвычайно простое и быстрое решение. Нет необходимости даже вовлекать, resignFirstResponderтак как иерархия просмотра самоанализирует и находит текущего респондента и просит его отказаться от статуса респондента.

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    [self.view endEditing:YES];
}

И не забудьте добавить UIScrollViewDelegateв файл заголовка.

Раджив Джайн
источник
2
Это можно сделать с помощью одного лайнера, как указал @Joe Masilotti, если вы нацеливаетесь на iOS7 и выше: self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;
atulkhatri
Что произойдет, если вы нажмете на текстовое поле в нижней части экрана, которое должно прокручиваться вверх, чтобы показать клавиатуру? - Ваша клавиатура будет скрыта.
Islam Q.
Swift 4 - self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissMode.onDrag
RobLabs
13

Во-первых, прислушайтесь к scrollViewWillBeginDraggingсвоему UIViewController, добавив UIScrollViewDelegate:

В файле .h:

@interface MyViewController : UIViewController <UIScrollViewDelegate> 

В файле .m:

- (void)scrollViewWillBeginDragging:(UIScrollView *)activeScrollView {

    [self dismissKeyboard];

}

Затем прислушайтесь к другим взаимодействиям:

- (void)setupKeyboardDismissTaps {

    UISwipeGestureRecognizer *swipeUpGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
    swipeUpGestureRecognizer.cancelsTouchesInView = NO;
    swipeUpGestureRecognizer.direction = UISwipeGestureRecognizerDirectionUp;
    [self.tableView addGestureRecognizer:swipeUpGestureRecognizer];

    UISwipeGestureRecognizer *swipeDownGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
    swipeDownGestureRecognizer.cancelsTouchesInView = NO;
    swipeDownGestureRecognizer.direction = UISwipeGestureRecognizerDirectionDown;
    [self.tableView addGestureRecognizer:swipeDownGestureRecognizer];

    UISwipeGestureRecognizer *swipeLeftGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
    swipeLeftGestureRecognizer.cancelsTouchesInView = NO;
    swipeLeftGestureRecognizer.direction = UISwipeGestureRecognizerDirectionLeft;
    [self.tableView addGestureRecognizer:swipeLeftGestureRecognizer];

    UISwipeGestureRecognizer *swipeRightGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
    swipeRightGestureRecognizer.cancelsTouchesInView = NO;
    swipeRightGestureRecognizer.direction = UISwipeGestureRecognizerDirectionRight;
    [self.tableView addGestureRecognizer:swipeRightGestureRecognizer];


    UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
    tapGestureRecognizer.cancelsTouchesInView = NO;
    [self.tableView addGestureRecognizer:tapGestureRecognizer];

}

Затем реализуйте dismissKeyboard:

- (void)dismissKeyboard {

    NSLog(@"dismissKeyboard");

    [yourTextFieldPointer resignFirstResponder];

}

И если, как и я, вы хотели отклонить клавиатуру для UITextField внутри настраиваемой ячейки таблицы:

- (void)dismissKeyboard {

    NSLog(@"dismissKeyboard");

    CustomCellClass *customCell = [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
    [customCell.textFieldInCell resignFirstResponder]; 

}

Надеюсь, что это поможет любому ищущему !!

Bbeckford
источник
12
tableView.keyboardDismissMode = .onDrag
Дом Брайан
источник
искал: D
Тобиас
8

Вот быстрая версия для вашего удовольствия от программирования:

Он добавляет распознаватель жестов касания, а затем закрывает клавиатуру. Никакого выхода для TextField не требуется!

override func viewDidLoad() {
    super.viewDidLoad()
    view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: "handleTap:"))
}

func handleTap(sender: UITapGestureRecognizer) {
    if sender.state == .Ended {
        view.endEditing(true)
    }
    sender.cancelsTouchesInView = false
}
Biodave
источник
1
Это работает даже с настраиваемым tableViewCell! Я потратил так много времени, пытаясь понять это. Спасибо вам большое! Ты мой герой. youtu.be/EqWRaAF6_WY
peacetype
8

Есть версия Swift 3 без блокировки кранов по ячейкам.

В viewDidLoad()методе:

let dismissKeyboardGesture = UITapGestureRecognizer(target: self, action: #selector(hideKeyboard))
dismissKeyboardGesture.cancelsTouchesInView = false
tableView.addGestureRecognizer(dismissKeyboardGesture)

И hideKeyboardвыглядит так:

func hideKeyboard() {
    view.endEditing(true)
}
Иван Сметанин
источник
7

У меня так получилось:

Создайте метод в своем TableViewController для деактивации первого респондента (который в этот момент будет вашим TextBox)

- (BOOL)findAndResignFirstResonder:(UIView *)stView {
    if (stView.isFirstResponder) {
        [stView resignFirstResponder];
        return YES;     
    }

    for (UIView *subView in stView.subviews) {
        if ([self findAndResignFirstResonder:subView]) {
            return YES;
        }
    }
    return NO;
}

В tableView:didSelectRowAtIndexPath:вызове предыдущего метода:

- (void)tableView:(UITableView *)tableView
                             didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    ...
    [self findAndResignFirstResonder: self.view];
    ...
}
ша
источник
вы делаете это неправильно, как просите. вы не помещаете кнопку в представление, вы говорите представлению, чтобы удалить клавиатуру, как говорится в этом ответе
2
Это прекрасно работает, если вы касаетесь ячейки табличного представления (и вне любого UITextField в этой ячейке табличного представления). Однако, если я коснусь фона представления таблицы (который часто оказывается более легкой целью - ура Фиттса!), Такой удачи не будет. Верно, этого и следовало ожидать, поскольку мы выполняем эту операцию в tableView: didSelectRowAtIndexPath :. Если это можно как-то отрегулировать для работы с касанием в любом другом месте в представлении таблицы (в противном случае фокус клавиатуры не нужен), я думаю, у нас есть победитель!
Джо Д'Андреа
У меня та же проблема, что и у jdandrea. Это didSelectRowAtIndexPathне сработает, если вы коснетесь самого TableView.
zekel
если didSelectRowAtIndexPath недостаточно, сделайте то же самое и в touchesBegan!
Амог Талпалликар
5

У меня была UITableViewControllerи реализацияtouchesBegan:withEvent: не сработала.

Вот что сработало:

Swift:

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    view.endEditing(true)
}

Цель-C:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [self.view endEditing:YES];
}
MontiRabbit
источник
Хорошая идея, мне это нравится.
HotFudge, воскресенье,
4
@interface DismissableUITableView : UITableView {
}
@end

@implementation DismissableUITableView

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

@end

Затем убедитесь, что в вашем файле Nib вы установили тип своего UITableView на DismissableUITableView ..... возможно, я мог бы придумать лучшее имя для этого класса, но вы поняли.

Bandejapaisa
источник
4

Если вы ориентируетесь на iOS7, вы можете использовать одно из следующего:

tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;

tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;

Первый будет анимировать клавиатуру за пределами экрана при прокрутке таблицы, а второй скроет клавиатуру, как стандартное приложение Messages.

Обратите внимание, что это from UIScrollView, который UITableViewнаследуется от.

Джо Масилотти
источник
отлично. Мне удалось как бы сломать его, проведя пальцем вниз от верхнего края экрана, пока клавиатура не начала двигаться вниз, затем проведя пальцем вверх, пока клавиатура не сдвинется немного вверх, а затем отпустив. scrollview не возвращается к началу, как должно.
Sam
3

Попробуй это:

viewDidLoad(){

    let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))

    tableView.addGestureRecognizer(tap)

}
//Calls this function when the tap is recognized.
@objc func dismissKeyboard() {

    //Causes the view (or one of its embedded text fields) to resign the first responder status.
    view.endEditing(true)

}
Майкл Колонна
источник
2

UITableView - это подкласс UIScrollView.

Я сделал это так, чтобы прослушать событие прокрутки пользователя, а затем resignFirstResponder. Вот метод UIScrollViewDelegate для реализации в вашем коде;

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView

При решении подобных задач я нашел лучший способ - исследовать протоколы делегатов для каждого объекта и родительских классов (в данном случае UITableViewDelegate, UIScrollViewDelegate. Количество событий, возникающих у NS-объектов, довольно велико и всесторонне. также проще реализовать протокол, чем создавать подклассы.

pschang
источник
2

У меня была такая же проблема, и вот мое решение, оно отлично работает для меня:

В представлении или контроллере представления, который вы реализовали <UITextFieldDelegate>

(В моем случае у меня есть обычай UITableViewCell TextFieldCell),

Объявить UITapGestureRecognizerкак свойство:

@interface TextFieldCell : UITableViewCell <UITextFieldDelegate>
{
    UITextField *theTextField;
    UITapGestureRecognizer *gestureRecognizer;
}
@property (nonatomic,retain) UITextField *theTextField;
@property (nonatomic,retain) UITapGestureRecognizer *gestureRecognizer; 

И инициализируйте его в своем представлении / контроллере:

self.gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(closeKeyboard:)];

В этом - (void)textFieldDidBeginEditing:(UITextField *)textFieldметоде используйте superViewдля перехода к вашему tableView и вызовите addGestureRecognizer:

[self.superview.superview addGestureRecognizer:gestureRecognizer];

И в - (void)textFieldDidEndEditing:(UITextField *)textField, просто удалите распознаватель жестов:

[self.superview.superview removeGestureRecognizer:gestureRecognizer];

Надеюсь, поможет.

hac.jack
источник
Это сделало это для меня. Спасибо hac.jack
gilsaints88
2

Я хотел, чтобы моя ячейка открывала клавиатуру, когда была выделена какая-либо часть ячейки, и закрывала ее, если вы щелкали в любом месте ячейки. Чтобы открыть клавиатуру:

- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
    [super setSelected:selected animated:animated];
    if (selected)
    {
        [self.textField becomeFirstResponder];
    }
}

(ПРИМЕЧАНИЕ: я создал подклассы ячейки, но вы можете легко добиться этого с помощью tableView:didSelectRowAtIndexPath:метода делегатаUITableView )

Это означало, что с лучшими решениями, если вы дважды щелкнете по ячейке, клавиатура будет дрожать, поскольку сначала распознаватель жестов попытался закрыть клавиатуру, а во-вторых, ячейка была повторно выбрана и попыталась открыть клавиатуру.

Решение - проверить, произошел ли щелчок внутри текущей выбранной ячейки:

- (void)viewDidLoad
{
    [super viewDidLoad];
    //gesture recognizer to close the keyboard when user taps away
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self
                                                                          action:@selector(dismissKeyboard:)];
    tap.cancelsTouchesInView = NO;
    [self.tableView addGestureRecognizer:tap];
}

-(void)dismissKeyboard:(UIGestureRecognizer*)tapGestureRecognizer
{
    if (!CGRectContainsPoint([self.tableView cellForRowAtIndexPath:[self.tableView indexPathForSelectedRow]].frame, [tapGestureRecognizer locationInView:self.tableView]))
    {
        [self.view endEditing:YES];
    }
}
Сэм
источник
2

Я нашел решение, которое отлично работает.

Необходимо использовать UIGestureRecognizerDelegate и метод - gestureRecognizer: shouldReceiveTouch: .

Добавьте распознаватель жестов в TableView следующим образом:

UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard)];
tapGestureRecognizer.cancelsTouchesInView = NO;
tapGestureRecognizer.delegate = self;
[self.suggestedTableView addGestureRecognizer:tapGestureRecognizer];
[tapGestureRecognizer release];

Затем реализуйте метод делегата shouldReceiveTouch для отклонения касаний, выполняемых в классе UITableViewCell. Метод hideKeyboard будет вызываться только тогда, когда прикосновение было выполнено вне класса UITableViewCell.

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    if([touch.view isKindOfClass:[UITableViewCell class]]) {
        return NO;
    }
    // UITableViewCellContentView => UITableViewCell
    if([touch.view.superview isKindOfClass:[UITableViewCell class]]) {
        return NO;
    }
    // UITableViewCellContentView => UITableViewCellScrollView => UITableViewCell
    if([touch.view.superview.superview isKindOfClass:[UITableViewCell class]]) {
        return NO;
    }
    return YES; // handle the touch
}

- (void) hideKeyboard{
    [textField resignFirstResponder];
}
млабрака
источник
2

UITableViewимеет удобное backgroundViewсвойство, с помощью которого я добился такого поведения, не вмешиваясь в выбор ячеек, как показано ниже в Swift:

let tableBackTapRecognizer = UITapGestureRecognizer(target: self, action: #selector(hideKeyboard))
tableView.backgroundView = UIView()
tableView.backgroundView?.addGestureRecognizer(tableBackTapRecognizer)
Шафак Гезер
источник
1

Простое использование UITapGestureRecognizer cancelsTouchesInView = NOозначает, что касания ячеек и UITextViews также запускают скрытие. Это плохо, если у вас есть несколько UITextView, и вы нажимаете на следующий. Клавиатура начнет скрываться, а затем следующий textView станет firstResponder, и клавиатура снова станет видимой. Чтобы этого избежать, проверьте место касания и скрывайте клавиатуру только в том случае, если касание не находится в ячейке:

// init
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapTableView:)];
tapRecognizer.cancelsTouchesInView = NO;
[self.tableView addGestureRecognizer:tapRecognizer];


// Hide on tap
- (void)didTapTableView:(UITapGestureRecognizer *)tap
{
    CGPoint point = [tap locationInView:tap.view];
    [self.view endEditing:!CGRectContainsPoint([self.tableView rectForRowAtIndexPath:[self.tableView indexPathForRowAtPoint:point]], point)];
}

Чтобы scrollViewWillBeginDragging:сработало, scrollEnabledсвойство tableView должно бытьYES

// Hide on scroll
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    [self.view endEditing:YES];
}
Шон Труп
источник
Отлично для меня. Добавлен текстовый блок в ячейку tableview; если прикоснусь за пределами клавиатуры увольняю
Никола
0

Почему вы хотите создать таблицу, полную текстовых полей? Вы должны использовать подробное представление для каждой строки, содержащей текстовые поля. При отправке подробного просмотра убедитесь, что вы вызываете «[myTextField статьFirstResponder]», чтобы пользователь мог начать редактирование одним щелчком мыши от списка таблиц.

Mugunth
источник
Приложение «Контакты» от Apple делает именно это. Я бы не сказал, что он полон текстовых полей как таковых, но он использует их для хорошего эффекта.
Джо Д'Андреа
2
Редактирование встроенного текста в табличном представлении намного быстрее и интуитивно понятнее, чем нажатие подробных представлений для каждого текстового поля, которое пользователь хочет редактировать ... просто спросите ближайшую HTML-форму, или текстовые поля на панелях настроек iPhone, или в приложении «Контакты», или и т. д. и т. д. и т.д ... очень жаль, что Apple не сделала этот тип ячейки стандартным, но в Интернете есть много информации о достижении этого.
glenc
0

Если вы хотите создать подкласс (тьфу!) Для представления таблицы, то может сработать что-то вроде этого :

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

   BOOL backgroundTouched = YES;

   for (UITouch *touch in touches) {
      CGPoint location = [touch locationInView:self];
      for (UITableViewCell *cell in self.visibleCells) {
         if (CGRectContainsPoint(cell.frame, location)) {
            backgroundTouched = NO;
            break;
         }
      }
   }

   if (backgroundTouched) {
      for (UITableViewCell *cell in self.visibleCells) {
         // This presumes the first subview is the text field you want to resign.
         [[cell.contentView.subviews objectAtIndex:0] resignFirstResponder];
      }
   }

   [super touchesBegan:touches withEvent:event];
}
Джо Д'Андреа
источник
0

Если вы хотите закрыть клавиатуру, пока нажата клавиша возврата, вы можете просто добавить следующий код в textField, который должен возвращать метод, т.е.

- (BOOL)textFieldShouldReturn:(UITextField *)atextField
{
   [textField resignFirstresponder];
}

Некоторые текстовые поля могут иметь представление средства выбора или какое-либо другое в качестве подпредставления, поэтому в этом случае вышеуказанный метод не работает, поэтому в этом случае нам нужно использовать класс UITapGestureRecognizer, т.е. добавить следующий фрагмент кода в метод viewDidLoad, т.е.

UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self
                                                                          action:@selector(dismissKeyboard)];

    [self.view addGestureRecognizer:tap];

Теперь просто добавьте ответчика об отставке к методу выбора, то есть:

-(void)dismissKeyboard 
{
    [textField resignFirstResponder];
}

Надеюсь, это поможет, спасибо :)

Эшвар Чайтанья
источник
0

Много интересных ответов. Я хотел бы скомпилировать различные подходы в решение, которое, по моему мнению, лучше всего подходит для сценария UITableView (это тот, который я обычно использую): обычно мы хотим скрыть клавиатуру в двух сценариях: при нажатии за пределами текстовых элементов пользовательского интерфейса, или при прокрутке вниз / вверх UITableView. Первый сценарий мы можем легко добавить с помощью TapGestureRecognizer, а второй - с помощью метода scrollViewWillBeginDragging: UIScrollViewDelegate. Первый порядок работы, способ скрыть клавиатуру:

   /**
     *  Shortcut for resigning all responders and pull-back the keyboard
     */
    -(void)hideKeyboard
    {
        //this convenience method on UITableView sends a nested message to all subviews, and they resign responders if they have hold of the keyboard
        [self.tableView endEditing:YES];

    }

Этот метод отменяет любой пользовательский интерфейс textField вложенных представлений в иерархии представлений UITableView, поэтому он более практичен, чем отказ от каждого отдельного элемента по отдельности.

Затем мы позаботимся об отклонении с помощью внешнего жеста Tap, с помощью:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    [self setupKeyboardDismissGestures];

}

- (void)setupKeyboardDismissGestures
{

//    Example for a swipe gesture recognizer. it was not set-up since we use scrollViewDelegate for dissmin-on-swiping, but it could be useful to keep in mind for views that do not inherit from UIScrollView
//    UISwipeGestureRecognizer *swipeUpGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard)];
//    swipeUpGestureRecognizer.cancelsTouchesInView = NO;
//    swipeUpGestureRecognizer.direction = UISwipeGestureRecognizerDirectionUp;
//    [self.tableView addGestureRecognizer:swipeUpGestureRecognizer];

    UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard)];
    //this prevents the gestureRecognizer to override other Taps, such as Cell Selection
    tapGestureRecognizer.cancelsTouchesInView = NO;
    [self.tableView addGestureRecognizer:tapGestureRecognizer];

}

Установка для параметра tapGestureRecognizer.cancelsTouchesInView значения NO означает, что gestureRecognizer не переопределяет обычную внутреннюю работу UITableView (например, не мешает выделению ячейки).

Наконец, чтобы скрыть клавиатуру при прокрутке вверх / вниз UITableView, мы должны реализовать метод scrollViewWillBeginDragging: протокола UIScrollViewDelegate, как:

.h файл

@interface MyViewController : UIViewController <UIScrollViewDelegate>

.m файл

#pragma mark - UIScrollViewDelegate

-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    [self hideKeyboard];
}

Я надеюсь, что это помогает! знак равно

Робертибирис
источник
0

Вот как я наконец добился работы. Я объединил предложения и коды из разных ответов. Возможности: отключение клавиатуры, перемещение текстовых полей над клавиатурой при редактировании и установка типа возврата клавиатуры «Далее» и «Готово». ЗАМЕНИТЕ «...» с другими полями

static const CGFloat ANIMATION_DURATION = 0.4;
static const CGFloat LITTLE_SPACE = 5;
CGFloat animatedDistance;
CGSize keyboardSize;

@interface ViewController () <UITextFieldDelegate>
 @property (weak, nonatomic) IBOutlet UITextField *firstNameTXT;
  .....// some other text fields
 @property (weak, nonatomic) IBOutlet UITextField *emailTXT;
@end

@implementation ViewController
- (void)viewDidLoad{
.....
// add tap gesture to help in dismissing keyboard
UITapGestureRecognizer * tapGesture = [[UITapGestureRecognizer alloc]
                                       initWithTarget:self
                                       action:@selector(tapScreen:)];// outside textfields

[self.view addGestureRecognizer:tapGesture];

// set text fields return key type to Next, last text field to Done
[self.firstNameTXT setReturnKeyType:UIReturnKeyNext];
.....
[self.emailTXT setReturnKeyType:UIReturnKeyDone];

// set text fields tags
[self.firstNameTXT setTag:0];
....// more text fields
[self.emailTXT setTag:5];

// add keyboard notification
[[NSNotificationCenter defaultCenter] addObserver:self     selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];
}
[[NSNotificationCenter defaultCenter] addObserver:self      selector:@selector(keyboardDidHide:) name:UIKeyboardDidHideNotification object:nil];
}

// dismiss keyboard when tap outside text fields
- (IBAction)tapScreen:(UITapGestureRecognizer *)sender {
  if([self.firstNameTXT isFirstResponder])[self.firstNameTXT resignFirstResponder];
  ...
  if([self.emailTXT isFirstResponder])[self.emailTXT  resignFirstResponder];

  }
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
   if(textField.returnKeyType==UIReturnKeyNext) {
     // find the text field with next tag
     UIView *next = [[textField superview] viewWithTag:textField.tag+1];
     [next becomeFirstResponder];
   } else if (textField.returnKeyType==UIReturnKeyDone || textField.returnKeyType==UIReturnKeyDefault) {
    [textField resignFirstResponder];
 }
return YES;
}

// Moving current text field above keyboard
-(BOOL) textFieldShouldBeginEditing:(UITextField*)textField{
   CGRect viewFrame = self.view.frame;
   CGRect textFieldRect = [self.view.window convertRect:textField.bounds fromView:textField];
   CGRect viewRect = [self.view.window convertRect:self.view.bounds fromView:self.view];
   CGFloat textFieldBottomLine = textFieldRect.origin.y + textFieldRect.size.height + LITTLE_SPACE;//

   CGFloat keyboardHeight = keyboardSize.height;

   BOOL isTextFieldHidden = textFieldBottomLine > (viewRect.size.height - keyboardHeight)? TRUE :FALSE;
  if (isTextFieldHidden) {
    animatedDistance = textFieldBottomLine - (viewRect.size.height - keyboardHeight) ;
    viewFrame.origin.y -= animatedDistance;
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:ANIMATION_DURATION];
    [self.view setFrame:viewFrame];
    [UIView commitAnimations];
  }
  return YES;
}

-(void) restoreViewFrameOrigionYToZero{
  CGRect viewFrame = self.view.frame;
  if (viewFrame.origin.y != 0) {
    viewFrame.origin.y = 0;
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:ANIMATION_DURATION];
    [self.view setFrame:viewFrame];
    [UIView commitAnimations];
  }
}

-(void)keyboardDidShow:(NSNotification*)aNotification{
   NSDictionary* info = [aNotification userInfo];
   keyboardSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
 }

-(void)keyboardDidHide:(NSNotification*)aNotification{
   [self restoreViewFrameOrigionYToZero];// keyboard is dismissed, restore frame view to its  zero origin
}
@end
Камель
источник
0

Ответ @ mixca очень полезен, но что, если у меня что-то отличается от UITextField. Я думаю, что лучший способ справиться с этим, выполнив поиск всех подвидов основного представления с рекурсивной функцией, проверьте пример ниже

- (BOOL)findAndResignFirstResponder {
if (self.isFirstResponder) {
    [self resignFirstResponder];
    return YES;
}

    for (UIView *subView in self.subviews) {
        if ([subView findAndResignFirstResponder]) {
            return YES;
        }
    }
    return NO;
}

а также вы можете поместить этот метод в свой служебный класс и использовать жест касания, например ответ @ mixca ..

Мерт
источник
0

Свифт 4 / 4,2 / 5

Вы также можете закрыть клавиатуру при нажатии на ячейку - прежде чем делать что-либо еще.

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    view.endEditing(true)
    // Do something here
    }
Н. Дер
источник
0

tableView.keyboardDismissMode = .onDrag //. интерактивный

К. Митра
источник