Как отменить первый ответчик из текстового поля при нажатии пользователем в другом месте?

Я заполнил свой вид с помощью ScrollView (такого же размера, как и представление), и я застрял в том, как уволить первого ответчика, когда пользователь нажимает в другом месте в представлении (или в прокрутке). Любая идея о том, как это сделать? Я использую следующий метод, но он работает не так, как ожидалось:

- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
    [textField resignFirstResponder];
    return YES;
}

спасибо для помощи,

Стефан

Ответ 1

Я нашел ответ здесь: ссылка

Если ваша конечная цель - просто отставить первого ответчика, это должен работать: [self.view endEditing: YES]

Этот метод разработан для этого! Ссылка: endEditing:

Заставляет просмотр (или одно из его встроенных текстовых полей) оставить статус первого ответчика.

Ответ 2

Для более надежного и чистого решения добавьте распознаватель жестов к вашему основному виду.

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

На ваш взгляд загрузился:

UITapGestureRecognizer* tapBackground = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard:)];
[tapBackground setNumberOfTapsRequired:1];
[self.view addGestureRecognizer:tapBackground];

.. и определите целевое действие, которое будет срабатывать при нажатии:

-(void) dismissKeyboard:(id)sender
{
    [self.view endEditing:YES];
}

Ответ 3

Лучший вариант - самый короткий путь;)

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

Ответ 4

Для Swift 3 и Swift 4 вы можете сделать это:

func viewDidLoad() {
    super.viewDidLoad()

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

    self.view.addGestureRecognizer(tap)
}

@objc func hideKeyboardByTappingOutside() {
    self.view.endEditing(true)
}

Ответ 5

UIViewController наследует от UIResponder, поэтому наивный способ (я уверен, что это не самый умный способ сделать это) - это переписать следующие методы (по крайней мере, 1 из них)

– touchesBegan:withEvent:
– touchesMoved:withEvent:
– touchesEnded:withEvent:
- touchesCancelled:withEvent:

Затем вы можете получить затронутый вид, выполнив

UITouch *touch = [touches anyObject];
UIView *touchedView = [touch view];

наконец, отменит первого ответчика, если это представление не является вашим текстовым полем

if(touchedView != textField){
    [textField resignFirstResponder];
}

_

Недостатки этого подхода:

Вам придется обращаться с "краном" самостоятельно. (Такая же проблема, как старый iOS 3.1 или ранее). Вам придется придумать свою собственную реализацию, чтобы различать одиночные краны от перетаскивания, щелчков, двойных кранов, длинных кранов и т.д. Не сложно заставить его работать хорошо, но вряд ли вы получите его точно так же, как Apple обнаруживает краны (тайминги, расстояния, количество порогов!) Однако это зависит от ваших потребностей.

Если ваша структура представления достаточно проста, вы можете добавить распознаватель жестов в представление контейнера и оставить каждого ответчика каждый раз, когда вызывается обработчик:)

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

Ответ 6

Никто еще не представил лучший ответ здесь:

[[UIApplication sharedApplication] sendAction:@selector(resignFirstResponder) to:nil from:nil forEvent:nil];

Из документации по этому методу:

Обычно этот метод вызывается объектом UIControl, который пользователь коснулся. Реализация по умолчанию отправляет метод действия к данному целевому объекту или, если цель не указана, к первому Ответчик. Подклассы могут переопределять этот метод для выполнения специальных отправка сообщений о действиях.

Я выделил соответствующую часть этого параграфа. Указав nil для параметра to:, мы автоматически вызываем данный селектор на первом ответчике, где бы он ни находился, и нам не нужно знать, где находится иерархия представлений. Это также можно использовать для вызова других методов и для первого ответчика, а не просто для отказа от статуса первого ответчика.

Ответ 7

Дайте уникальный тег вашему UITextfield (т.е. 333), затем, чтобы уйти в отставку, первый ответчик сделает следующее:

UITextField *textField = (UITextField *)[self.view viewWithTag:333];
[textField resignFirstResponder];

Ответ 8

    -(BOOL)textFieldShouldReturn:(UITextField *)textField
{
    [self.TextField resignFirstResponder];

    return YES;
}

Ответ 9

Просто создайте IBOutlet или указатель на текстовое поле и вызовите [textField resignFirstResponder]; откуда вы хотите.

Ответ 10

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

[self.view addGestureRecognizer:tap];

и селектор

-(void)TapTodissmiss{

    [self.txtffld resignFirstResponder];

}

Ответ 11

По возможности наилучшим вариантом является сделать ваш UIView для наследования с UIButton.

Вам просто нужно изменить его в Interface Builder, и сразу вы получите варианты создания Action "Touch Up Inside", как любая другая кнопка.

Ваше представление будет работать как обычно, потому что UIButton по-прежнему является просмотром, но вы будете уведомлены, когда кто-то наберет вид. Там вы можете позвонить

[self.view endEditing:YES];

Отменить любую клавиатуру.

Обратите внимание, что если ваше представление является UIScrollView, это решение не для вас.

Ответ 12

Создайте свой IBOutlet в файле ViewController.h, как показано ниже:

//YOUR ViewController.h FILE

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController
{
    //WIRE THIS WITH YOUR UITextField OBJECT AT YOUR .xib FILE
    IBOutlet UITextField *yourIBOutletUITextField;
}

@end

Добавьте это в файл ViewController.m:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
     [yourIBOutletUITextField resignFirstResponder];
}

как показано ниже:

//YOUR ViewController.m FILE

#import "ViewController.h"

@implementation ViewController


//ADD THIS METHOD BELOW
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
     [yourIBOutletUITextField resignFirstResponder];
}


- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Release any cached data, images, etc that aren't in use.
}

#pragma mark - View lifecycle

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    }

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
}

- (void)viewDidDisappear:(BOOL)animated
{
    [super viewDidDisappear:animated];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

@end

Ответ 13

Для моей реализации [self.view endEditing: YES] не работает.

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

-(void) hideKeyboardPlease{
   [uiTextTo becomeFirstResponder];
   [uiTextTo resignFirstResponder];
}

Ответ 14

Это то, что я делаю...

UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideAllKeyboards)];
tapGesture.cancelsTouchesInView = NO;
[self.view addGestureRecognizer:tapGesture];

-(void) hideAllKeyboards {
    [textField_1 resignFirstResponder];
    [textField_2 resignFirstResponder];
    [textField_3 resignFirstResponder];
    .
    .
    .
    [textField_N resignFirstResponder];
}

Ответ 15

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

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

[self.view endEditing:YES];

}

Ответ 16

Обновление

Я нашел еще один простой способ

просто объявить свойство: -

@property( strong , nonatomic) UITextfield *currentTextfield;

и Gecognizer Gothognizer: -

@property (strong , nonatomic) UITapGestureRecognizer *resignTextField;

В ViewDidLoad

_currentTextfield=[[UITextField alloc]init];
_resignTextField=[[UITapGestureRecognizer alloc]initWithTarget:@selector(tapMethod:)];

[self.view addGestureRecognizer:_resignTextField];

Реализовать метод делегата текстового поля doneBeginEditing

 -(void)textFieldDidBeginEditing:(UITextField *)textField{


      _currentTextfield=textField;

    }

Реализовать свой метод жестов (_resignTextField)

 -(void)tapMethod:(UITapGestureRecognizer *)Gesture{

     [_currentTextfield resignFirstResponder];

 }

Ответ 17

Создайте большую кнопку за всем этим, и обратный вызов кнопки вызывает resignFirstResponder на каждый введенный вами вход. Просто убедитесь, что все, что пользователь взаимодействует, находится поверх кнопки.

Конечно, кнопка будет настраиваемой и прозрачной.

Я бы рассмотрел реализацию IBOutletCollection, названного resignables, и установил каждый вход в эту коллекцию. И обратный вызов кнопки выполняет итерацию по этой коллекции, вызывающую resignFirstResponder для всех.

Изменить: если это расширенное представление прокрутки, не забудьте правильно установить маркеры размерного размера в опции просмотра кнопки, таким образом, кнопка всегда будет расширяться и сжиматься до высоты и ширины прокрутки