轻松解除键盘的方法?

时间:2009-04-12 02:19:30

标签: objective-c cocoa-touch sdk

我的表格中有很多控件分散在我的表格中,我想知道是否有一种更简单的方法来解除键盘,而不必遍历所有控件并将它们全部作为第一响应者重新签名。我想问题是......我如何才能让当前的第一响应者进入键盘?

31 个答案:

答案 0 :(得分:785)

尝试:

[self.view endEditing:YES];

答案 1 :(得分:126)

您可以强制当前编辑的视图使用[view endEditing:YES]重新设置其第一响应者状态。这隐藏了键盘。

-[UIResponder resignFirstResponder]不同,-[UIView endEditing:]会搜索子视图以查找当前的第一响应者。因此,您可以将其发送到顶级视图(例如self.view中的UIViewController),它会做正确的事情。

(这个答案以前包含了其他一些解决方案,这些解决方案也有效,但比必要的更复杂。我已将其删除以避免混淆。)

答案 2 :(得分:89)

您可以向应用程序发送零目标操作,它会随时退出第一响应者,而不必担心哪个视图当前具有第一响应者状态。

目标-C:

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

Swift 3.0:

UIApplication.shared.sendAction(#selector(resignFirstResponder), to: nil, from: nil, for: nil)

NOS目标操作在Mac OS X上常用于菜单命令,这里是在iOS上使用它们。

答案 3 :(得分:56)

老实说,我并不为这里提出的任何解决方案而疯狂。我确实找到了一种使用TapGestureRecognizer的好方法,我认为它可以解决问题的核心:当你点击键盘以外的任何东西时,关掉键盘。

  1. 在viewDidLoad中,注册接收键盘通知并创建UITapGestureRecognizer:

    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
    
    [nc addObserver:self selector:@selector(keyboardWillShow:) name:
    UIKeyboardWillShowNotification object:nil];
    
    [nc addObserver:self selector:@selector(keyboardWillHide:) name:
    UIKeyboardWillHideNotification object:nil];
    
    tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
    action:@selector(didTapAnywhere:)];
    
  2. 添加键盘显示/隐藏响应者。在那里你添加和删除TapGestureRecognizer到UIView,它应该在点击时解除键盘。注意:您不必将其添加到所有子视图或控件。

    -(void) keyboardWillShow:(NSNotification *) note {
        [self.view addGestureRecognizer:tapRecognizer];
    }
    
    -(void) keyboardWillHide:(NSNotification *) note
    {
        [self.view removeGestureRecognizer:tapRecognizer];
    }
    
  3. TapGestureRecognizer会在点击时调用您的功能,您可以像这样关闭键盘:

    -(void)didTapAnywhere: (UITapGestureRecognizer*) recognizer {    
        [textField resignFirstResponder];
    }
    
  4. 这个解决方案的好处是它只过滤Taps,而不是滑动。因此,如果您在键盘上方滚动内容,则滑动仍会滚动并显示键盘。通过在键盘消失后移除手势识别器,可以正常处理视图上的未来点击。

答案 4 :(得分:22)

这是一个解决方案,通过在一个地方添加代码,在任何文本字段中点击return时键盘就会消失(因此不必为每个文本字段添加处理程序) ):


考虑这种情况:

我有一个viewcontroller,其中包含两个文本字段(用户名和密码)。 和viewcontroller实现UITextFieldDelegate协议

我在viewDidLoad中执行此操作

- (void)viewDidLoad 
{
    [super viewDidLoad];

    username.delegate = self;
    password.delegate = self;
}

并且viewcontroller将可选方法实现为

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

并且无论您在哪个文本字段,只要我点击键盘上的return,它就会被解雇!

在您的情况下,只要您将所有textfield的委托设置为self并实现textFieldShouldReturn

,就会有效

答案 5 :(得分:14)

更好的方法是让某些东西“窃取”第一响应者状态。

由于UIApplication是UIResponder的子类,您可以尝试:

[[UIApplication sharedApplication] becomeFirstResponder]
[[UIApplication sharedApplication] resignFirstResponder]

如果不这样做,请创建一个具有零大小框架的新UITextField,将其添加到某个地方的视图中并执行类似的操作(后跟辞职)。

答案 6 :(得分:7)

把它放在一些实用类中。

+ (void)dismissKeyboard {
    [self globalResignFirstResponder];
}

+ (void) globalResignFirstResponder {
    UIWindow * window = [[UIApplication sharedApplication] keyWindow];
    for (UIView * view in [window subviews]){
        [self globalResignFirstResponderRec:view];
    }
}

+ (void) globalResignFirstResponderRec:(UIView*) view {
    if ([view respondsToSelector:@selector(resignFirstResponder)]){
        [view resignFirstResponder];
    }
    for (UIView * subview in [view subviews]){
        [self globalResignFirstResponderRec:subview];
    }
}

答案 7 :(得分:6)

@Nicholas Riley& @Kendall Helmstetter Geln& @cannyboy:

绝对精彩!

谢谢。

在这个帖子中考虑你的建议和其他人的建议,这就是我所做的:

使用后的样子:

[[self appDelegate] dismissKeyboard]; (注意:我添加了appDelegate作为NSObject的补充,因此我可以在任何地方使用)

引擎盖下的内容:

- (void)dismissKeyboard 
{
    UITextField *tempTextField = [[[UITextField alloc] initWithFrame:CGRectZero] autorelease];
    tempTextField.enabled = NO;
    [myRootViewController.view addSubview:tempTextField];
    [tempTextField becomeFirstResponder];
    [tempTextField resignFirstResponder];
    [tempTextField removeFromSuperview];
}

修改

我对tempTextField.enabled = NO;的回答的修正案。如果您在整个应用中依赖这些通知,则停用文本字段会阻止发送UIKeyboardWillShowNotificationUIKeyboardWillHideNotification个键盘通知。

答案 8 :(得分:5)

这里有很多过于复杂的答案,也许是因为这在iOS文档中并不容易找到。约瑟夫H就在上面:

[[view window] endEditing:YES];

答案 9 :(得分:4)

当用户触摸UITextField或键盘外部屏幕上的任何位置时,快速提示如何解除iOS中的键盘。考虑到iOS键盘可以占用多少空间,让用户轻松直观地关闭键盘是有意义的。

这是a link

答案 10 :(得分:3)

这是我在代码中使用的内容。它就像一个魅力!

在yourviewcontroller.h中添加:

@property (nonatomic) UITapGestureRecognizer *tapRecognizer;

现在在.m文件中,将其添加到ViewDidLoad函数:

- (void)viewDidLoad {
    //Keyboard stuff
    tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapAnywhere:)];
    tapRecognizer.cancelsTouchesInView = NO;
    [self.view addGestureRecognizer:tapRecognizer];
}

另外,在.m文件中添加此功能:

- (void)handleSingleTap:(UITapGestureRecognizer *) sender
{
    [self.view endEditing:YES];
}

答案 11 :(得分:3)

比Meagar的答案更简单

覆盖touchesBegan:withEvent:

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

当您触摸dismiss the keyboard中的任何位置时,background会{。}}。

答案 12 :(得分:2)

在swift 3中,您可以执行以下操作

UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)

答案 13 :(得分:2)

从UITableView和UIScrollView中解除键盘的最佳方法是:

// Assume we have an ExecutorService "pool" and N is the count of tasks
List<Future<SomeType>> batch = new ArrayList<>(N);

for( int i = 0; i < N; i++ ){ 
     batch.add(pool.submit(new Task(i)));
}

for( Future fut : batch ) fut.get();
/* get will block until the task is done. 
 * If it is already done it will return immediately.
 * So if all futures in the list return from get, all tasks are done.
 */

答案 14 :(得分:2)

您应该将endEditing:发送到工作窗口,作为UIView

的子类
[[UIApplication sharedApplication].windows.firstObject endEditing:NO];

答案 15 :(得分:2)

在视图控制器的头文件中,将<UITextFieldDelegate>添加到控制器接口的定义中,以使其符合UITextField委托协议......

@interface someViewController : UIViewController <UITextFieldDelegate>

...在控制器的实现文件(.m)中添加以下方法,或者如果你已有viewDidLoad方法,则添加代码...

- (void)viewDidLoad
{
    // Do any additional setup after loading the view, typically from a nib.
    self.yourTextBox.delegate = self;
}

...然后,将yourTextBox链接到实际的文本字段

- (BOOL)textFieldShouldReturn:(UITextField *)theTextField 
{
    if (theTextField == yourTextBox) {
        [theTextField resignFirstResponder];
    }
    return YES;
}

答案 16 :(得分:1)

您可能还需要覆盖UIViewController disablesAutomaticKeyboardDismissal以在某些情况下使其工作。如果你有一个,可能必须在UINavigationController上完成。

答案 17 :(得分:1)

对文本字段进行子类化...以及文本视图

在子类中放置此代码..

-(void)conformsToKeyboardDismissNotification{

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(dismissKeyBoard) name:KEYBOARD_DISMISS object:nil];
}

-(void)deConformsToKeyboardDismissNotification{

    [[NSNotificationCenter defaultCenter] removeObserver:self name:KEYBOARD_DISMISS object:nil];
}

- (void)dealloc{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [self resignFirstResponder];
}

在textfield委托中(类似于textview委托)

-(void)textFieldDidBeginEditing:(JCPTextField *)textField{
     [textField conformsToKeyboardDismissNotification];
}


- (void)textFieldDidEndEditing:(JCPTextField *)textField{
    [textField deConformsToKeyboardDismissNotification];
}

全部设置..现在只需在代码中的任何位置发布通知。它将重新签名任何键盘。

答案 18 :(得分:1)

Jeremy的回答并不适合我,我想是因为我在标签视图中有一个导航堆栈,顶部有一个模态对话框。我现在正在使用以下内容,它对我有用,但你的里程可能会有所不同。

 // dismiss keyboard (mostly macro)
[[UIApplication sharedApplication].delegate dismissKeyboard]; // call this in your to app dismiss the keybaord

// --- dismiss keyboard (in indexAppDelegate.h) (mostly macro)
- (void)dismissKeyboard;

// --- dismiss keyboard (in indexAppDelegate.m) (mostly macro)
// do this from anywhere to dismiss the keybard
- (void)dismissKeyboard {    // from: http://stackoverflow.com/questions/741185/easy-way-to-dismiss-keyboard

    UITextField *tempTextField = [[UITextField alloc] initWithFrame:CGRectZero];

    UIViewController *myRootViewController = <#viewController#>; // for simple apps (INPUT: viewController is whatever your root controller is called.  Probably is a way to determine this progragrammatically)
    UIViewController *uivc;
    if (myRootViewController.navigationController != nil) { // for when there is a nav stack
        uivc = myRootViewController.navigationController;
    } else {
        uivc = myRootViewController;
    }

    if (uivc.modalViewController != nil) { // for when there is something modal
        uivc = uivc.modalViewController;
    } 

    [uivc.view  addSubview:tempTextField];

    [tempTextField becomeFirstResponder];
    [tempTextField resignFirstResponder];
    [tempTextField removeFromSuperview];
    [tempTextField release];

}

答案 19 :(得分:1)

我们可以迅速做到

UIApplication.sharedApplication().sendAction("resignFirstResponder", to: nil, from: nil, forEvent: nil)

答案 20 :(得分:1)

在键盘弹出后关闭键盘, 2例

  1. 当UITextField在UIScrollView中

  2. 当UITextField在UIScrollView外

  3. 2.当UITextField位于UIScrollView之外时 覆盖UIViewController子类中的方法

    您还必须为所有UITextView添加委托

    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
        [self.view endEditing:YES];
    }
    
    1. 滚动视图中,点击外部不会触发任何事件,因此在这种情况下使用点击手势识别器, 拖放滚动视图的 UITapGesture 为其创建IBAction
    2. 创建IBAction,按ctrl +单击UITapGesture并将其拖到viewcontroller的.h文件中。

      这里我将tappedEvent命名为我的动作名称

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

      上述信息来自以下链接,如果您不理解该数据,请参阅更多信息或与我联系。

      http://samwize.com/2014/03/27/dismiss-keyboard-when-tap-outside-a-uitextfield-slash-uitextview/

答案 21 :(得分:0)

最简单的方法是调用方法

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{
    if(![txtfld resignFirstResponder])
    {
        [txtfld resignFirstResponder];
    }
    else
    {

    }
    [super touchesBegan:touches withEvent:event];
}

答案 22 :(得分:0)

我最近需要使用的稍微强大的方法:

- (void) dismissKeyboard {
    NSArray *windows = [UIApplication sharedApplication].windows;

    for(UIWindow *window in windows) [window endEditing:true];

    //  Or if you're only working with one UIWindow:

    [[UIApplication sharedApplication].keyWindow endEditing:true];
}

我找到了其他一些&#34;全球&#34;方法不起作用(例如,UIWebView&amp; WKWebView拒绝辞职。

答案 23 :(得分:0)

在您的视图中添加一个Tap Gesture Recognizer。并定义它ibaction

您的.m文件就像

    - (IBAction)hideKeyboardGesture:(id)sender {
    NSArray *windows = [UIApplication sharedApplication].windows;
    for(UIWindow *window in windows) [window endEditing:true];
    [[UIApplication sharedApplication].keyWindow endEditing:true];
}

这对我有用

答案 24 :(得分:0)

您可以递归遍历子视图,存储所有UITextField的数组,然后遍历它们并将它们全部重新签名。

不是一个很好的解决方案,特别是如果您有很多子视图,但对于简单的应用程序,它应该可以解决问题。

我用更复杂但更高效的方式解决了这个问题,但是对我的应用程序的动画引擎使用单例/管​​理器,并且只要文本字段成为响应者,我就会将其分配给静态根据某些其他事件将被扫除(辞职)......我几乎不可能在段落中解释。

要有创意,在找到这个问题后,我花了10分钟时间为我的应用程序考虑这个问题。

答案 25 :(得分:0)

是的,endEditing是最好的选择。从iOW 7.0开始,UIScrollView有一个很酷的功能,可以在与滚动视图交互时关闭键盘。为实现此目的,您可以设置keyboardDismissMode的{​​{1}}属性。

将键盘关闭模式设置为:

UIScrollView

它几乎没有其他类型。看看这个apple document

答案 26 :(得分:0)

在swift:

self.view.endEditing(true)

答案 27 :(得分:0)

这不是很漂亮,但当我不知道响应者是什么时,我辞职第一个响应者的方式:

在IB中或以编程方式创建UITextField。把它隐藏起来。如果您在IB中创建它,请将其链接到您的代码。 然后,当您想要关闭键盘时,将响应者切换到不可见的文本字段,并立即将其重新签名:

  [self.invisibleField becomeFirstResponder];
  [self.invisibleField resignFirstResponder];

答案 28 :(得分:0)

您必须使用其中一种方法

[self.view endEditing:YES];

[self.textField resignFirstResponder];

答案 29 :(得分:0)

<强>更新

我找到了另一种简单的方法

只需声明一个属性: -

@property( strong , nonatomic) UITextfield *currentTextfield;

和Tap Gesture Gecognizer: -

@property (strong , nonatomic) UITapGestureRecognizer *resignTextField;

在ViewDidLoad

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

[self.view addGestureRecognizer:_resignTextField];

实施文本字段委托方法didBeginEditing

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


      _currentTextfield=textField;

    }

实施点击手势方法(_resignTextField)

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

     [_currentTextfield resignFirstResponder];

 }

答案 30 :(得分:0)

我讨厌没有使用私有API调用以编程方式关闭键盘的“全局”方式。通常,我需要以编程方式关闭键盘而不知道第一响应者是什么对象。我已经使用Objective-C运行时API检查self,枚举其所有属性,提取UITextField类型的那些,并向它们发送resignFirstResponder消息

这不应该这么难......