web-dev-qa-db-ja.com

iOS - UITextFieldの外側に触れるとキーボードを消す

ユーザーがUITextFieldの外側に触れるとキーボードが消えるようにする方法を考えています。

436
jonepatr

UITapGestureRecogniserを追加してそれをビューに割り当てる必要があります。そしてセレクタのUITextFieldにresign first responderを呼び出します。

コード:

in viewDidLoad

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

[self.view addGestureRecognizer:tap];

dismissKeyboardの場合:

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

aTextFieldはキーボードを担当するテキストフィールドです)

Swift 3 versionはそのように見える

let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.dismissKeyboard (_:)))
self.view.addGestureRecognizer(tapGesture)

dismissKeyboardの場合

func dismissKeyboard (_ sender: UITapGestureRecognizer) {
    aTextField.resignFirstResponder()
}
732
Jensen2k

いくつか答えをまとめました。

viewDidLoad:中に初期化されるivarを使う

UIGestureRecognizer *tapper;

- (void)viewDidLoad
{
    [super viewDidLoad];
    tapper = [[UITapGestureRecognizer alloc]
                initWithTarget:self action:@selector(handleSingleTap:)];
    tapper.cancelsTouchesInView = NO;
    [self.view addGestureRecognizer:tapper];
}

現在編集中のものを削除します。

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

これをチェックしてください、これがそれをする最も簡単な方法でしょう、

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
      [self.view endEditing:YES];// this will do the trick
}

または

このライブラリは、スクロールバーの自動スクロール、キーボードを隠すためのスペースのタップなどを処理します。

https://github.com/michaeltyson/TPKeyboardAvoiding

100
Prasad De Zoysa

UITapGestureRecognizerメソッドを使うことで問題を抱えている人たちがいるのを私は見ます。既存のボタンのタップ動作を変更せずにこの機能を実現した最も簡単な方法は、@ Jensen2kの回答に1行だけ追加することです。

[tap setCancelsTouchesInView:NO];

これにより、@ Dmitry Sitnikovのメソッドを使用せずに既存のボタンを機能させることができました。

ここでそのpropertyについて読んでください(CancelsTouchesInViewを検索してください): UIGestureRecognizerクラスリファレンス

スクロールバーがどのように機能するのかはよくわかりませんが、問題がある場合もありますが、他のユーザーが同じシナリオに遭遇する可能性があります。

84
Qiao Yi

あなたのUIViewを(インターフェースビルダーで)UIControlのインスタンスにしてから、それらのTouchUpInsideイベントをdismissKeyboardメソッドに接続するのが良いでしょう。このIBActionメソッドは以下のようになります。

- (IBAction)dismissKeyboard:(id)sender {
    [aTextBox resignFirstResponder];
}
55
Dmitry Sitnikov

Swiftバージョンでは、これは他の要素と組み合わせて動作します(UIButtonや他のUITextFieldなど)

override func viewDidLoad() {
    super.viewDidLoad()

    let tapper = UITapGestureRecognizer(target: self, action:#selector(endEditing))
    tapper.cancelsTouchesInView = false
    view.addGestureRecognizer(tapper)
}
28
Rob

これはどうですか:私はこれが古い記事であることを知っています。それは誰かを助けるかもしれません:)

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {  
    NSArray *subviews = [self.view subviews];
    for (id objects in subviews) {
        if ([objects isKindOfClass:[UITextField class]]) {
            UITextField *theTextField = objects;
            if ([objects isFirstResponder]) {
                [theTextField resignFirstResponder];
            }
        } 
    }
}
17
Mr H

スイフト4

この拡張メソッドを使用してUIViewControllerを一度設定します(例:viewDidLoad)。

override func viewDidLoad() {
    super.viewDidLoad()
    self.setupHideKeyboardOnTap()
}

キーボードはNavigationBarをタップしても削除されます。

import UIKit
extension UIViewController {
    /// Call this once to dismiss open keyboards by tapping anywhere in the view controller
    func setupHideKeyboardOnTap() {
        self.view.addGestureRecognizer(self.endEditingRecognizer())
        self.navigationController?.navigationBar.addGestureRecognizer(self.endEditingRecognizer())
    }

    /// Dismisses the keyboard from self.view
    private func endEditingRecognizer() -> UIGestureRecognizer {
        let tap = UITapGestureRecognizer(target: self.view, action: #selector(self.view.endEditing(_:)))
        tap.cancelsTouchesInView = false
        return tap
    }
}
16
FBente

これは良い一般的な解決策です。

目的C:

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

迅速:

override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
    self.view.endEditing(true)
}

@icodebusterソリューションに基づく: https://stackoverflow.com/a/18756253/417652

13
eduludi

これを行うための最も簡単な(そして最善の)方法は、グローバルビューをサブクラス化し、hitTest:withEventメソッドを使用して任意のタッチを聞くことです。キーボードのタッチは登録されていないので、hitTest:withEventは タッチ/スクロール/スワイプ/ピンチ... のいずれかの場所で呼び出され、[self endEditing:YES]を呼び出します。

ビュー上部のボタンをクリックしてもtouchesBeganは呼び出されないため、これはtouchesBeganを使用するよりも優れています。例えばスクロールジェスチャーを認識できないUITapGestureRecognizerよりはましです。また、複雑で動的なユーザーインターフェースでは、どこにでも暗い画面を配置できないため、暗い画面を使用するよりも優れています。さらに、それは他のアクションをブロックしません、あなたは外側のボタンを選択するために二度タップする必要はありません(UIPopoverの場合のように)。

また、[textField resignFirstResponder]を呼び出すよりも優れています。画面に多数のテキストフィールドがある可能性があるため、これはすべてのフィールドに有効です。

10
Enzo Tran

スイフト4 oneliner

view.addGestureRecognizer(UITapGestureRecognizer(target: view, action: #selector(UIView.endEditing(_:))))
7
newDeveloper

XCode 6以降のストーリーボードを使ってこれを行うことができます。


キーボードを隠すアクションを作成する

これをあなたのViewControllerが使用するクラスのヘッダファイルに追加してください。

@interface TimeDelayViewController : UIViewController <UITextFieldDelegate>

- (IBAction)dissmissKeyboardOnTap:(id)sender;

@end

次に、これを同じViewControllerの実装ファイルに追加します。

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

これはあなたのストーリーボードシーン(すなわちViewController)の 'Received Actions'の1つになります。

enter image description here


ユーザーイベントにアクションを接続する

さて、あなたはこのアクションをキーボードから触れるというユーザーのジェスチャーに結び付ける必要があります。

重要 - ストーリーボードに含まれている 'UIView'をUIControl に変換する必要があります。そうすればイベントを受け取ることができます。 View Controllerのシーン階層からビューを選択します。

enter image description here

...そしてそのクラスを変更します。

enter image description here

ここであなたのシーンの「受け取ったアクション」の隣にある小さな円からあなたのシーンの「空の」部分にドラッグしてください(実際にはあなたはUIControlに「受け取ったアクション」をドラッグしています)。あなたはあなたがあなたの行動を結びつけることができるイベントの選択が表示されるでしょう:

enter image description here

[中をタッチアップ]オプションを選択します。これで、作成したIBActionを、キーボードを触るというユーザーアクションに結びつけました。ユーザーがキーボードをタップすると、キーボードは非表示になります。

(注:アクションをイベントにフックするには、受信したアクションからView Controllers階層のUIControlに直接ドラッグすることもできます。階層では「Control」と表示されます。 _

6
Chris Halcrow

これは、外部に触れることによってキーボードを隠す最も簡単な方法であるはずです。

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

(from ユーザーがテキストフィールドの外側の他の領域をタップしたときにキーボードを閉じる方法?

6

ビューがUIScrollViewに埋め込まれている場合は、次のものを使用できます。

tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;
tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;

前者はTable Viewがスクロールされたときにキーボードを画面外でアニメーション化し、後者は標準のMessagesアプリのようにキーボードを非表示にします。

これらはiOS 7.0以降で利用可能です。

5
Joe Masilotti

私が正しいと思ったらあなたはtextfieldのoutSideをタップしてキーボードのワイルタップを辞任したいのですが、あなたはtextfieldを参照していません。

これを試して;

  • グローバルtextFieldを取り、それをreftextFieldと呼びましょう
  • textFieldDidBeginEditingで、参照テキストフィールドをに設定します。

    - (void) textFieldDidBeginEditing:(UITextField *)textField{
        reftextField = textField;
    }
    
  • 今、あなたはどんなボタン時計でも喜んで使うことができます(編集開始時に透明なボタンを追加することをお勧めします)。

    - (void)dismissKeyboard {
          [reftextField resignFirstResponder];
    }
    
  • またはやめるボタンのためにこれを試してください。

    //for resigning on done button    
    - (BOOL) textFieldShouldReturn:(UITextField *)textField{
        [textField resignFirstResponder];
        return YES;
    }
    
5
rptwsthi

@ Jensen2kの答えの迅速なバージョン:

let gestureRecognizer : UITapGestureRecognizer = UITapGestureRecognizer.init(target: self, action: "dismissKeyboard")
self.view.addGestureRecognizer(gestureRecognizer)

func dismissKeyboard() {
    aTextField.resignFirstResponder()
}

ワンライナー

self.view.addTapGesture(UITapGestureRecognizer.init(target: self, action: "endEditing:"))
3
Syed Asad Ali

ここにリストに追加するために、外付けタッチでキーボードを消す方法の私のバージョン。

viewDidLoad:

UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
[self.view addGestureRecognizer:singleTap];

どこでも:

-(void)handleSingleTap:(UITapGestureRecognizer *)sender{
    [textFieldName resignFirstResponder];
    puts("Dismissed the keyboard");
}
3
John Riselvato

UITapGestureRecognizername __--を使うことに関する沢山の素晴らしい答えがここにあります。それらすべてはUITextFieldname__のclear(X)ボタンを壊します。解決策は、そのデリゲートを介してジェスチャー認識機能を抑制することです。

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    BOOL touchViewIsButton = [touch.view isKindOfClass:[UIButton class]];
    BOOL touchSuperviewIsTextField = [[touch.view superview] isKindOfClass:[UITextField class]];
    return !(touchViewIsButton && touchSuperviewIsTextField);
}

これは最も堅牢なソリューションではありませんが、私にとってはうまくいきます。

3
skedastik

次のように、UiViewのカテゴリを作成してtouchesBeganの方法をオーバーライドできます。

それは私のためにうまく働いています。そしてそれはこの問題のための集中解決策です。

#import "UIView+Keyboard.h"
@implementation UIView(Keyboard)

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self.window endEditing:true];
    [super touchesBegan:touches withEvent:event];
}
@end
3
Hiren

最も簡単で短い方法の1つは、このコードをあなたのviewDidLoadに追加することです。

[self.view addGestureRecognizer:[[UITapGestureRecognizer alloc]
                                     initWithTarget:self.view
                                     action:@selector(endEditing:)]];
2
Sudhin Davis

私はここで多くの反応を試みたが運が悪かった。ジェスチャーレコグナイザーのUIButtonsプロパティをNOに設定しても、タップジェスチャーレコグナイザーが常にタップしてもcancelsTouchesInViewが応答しないようにしていました。

これは結局問題を解決したものです:

アイバーを持っている:

UITapGestureRecognizer *_keyboardDismissGestureRecognizer;

テキストフィールドの編集が開始されたら、ジェスチャ認識機能を設定します。

- (void) textFieldDidBeginEditing:(UITextField *)textField
{
    if(_keyboardDismissGestureRecognizer == nil)
    {
        _keyboardDismissGestureRecognizer = [[[UITapGestureRecognizer alloc]
                                       initWithTarget:self
                                       action:@selector(dismissKeyboard)] autorelease];
        _keyboardDismissGestureRecognizer.cancelsTouchesInView = NO;

        [self.view addGestureRecognizer:_keyboardDismissGestureRecognizer];
    }
}

それからトリックはdismissKeyboardメソッドをどのように設定するかです。

- (void) dismissKeyboard
{
    [self performSelector:@selector(dismissKeyboardSelector) withObject:nil afterDelay:0.01];
}

- (void) dismissKeyboardSelector
{
    [self.view endEditing:YES];

    [self.view removeGestureRecognizer:_keyboardDismissGestureRecognizer];
    _keyboardDismissGestureRecognizer = nil;
}

タッチ処理の実行スタックからdismissKeyboardSelectorの実行を取り出すことについて何かがあると思います...

2
user1021430

私は新しい開発にBarryの例を使いました。うまくいった!しかし、私はわずかな変更を加えなければなりませんでした、編集されているテキストフィールドのためだけにキーボードを消すのに必要です。

だから、私は次のBarryの例に追加しました:

- (void) textFieldDidBeginEditing:(UITextField *)textField
{
    _textBeingEdited = textField;
}
-(void) textFieldDidEndEditing:(UITextField *)textField
{
    _textBeingEdited = nil;
}

また、hideKeyboardメソッドを次のように変更しました。

- (IBAction)hideKeyboard:(id)sender
{
    // Just call resignFirstResponder on all UITextFields and UITextViews in this VC
    // Why? Because it works and checking which one was last active gets messy.
    //UITextField * tf = (UITextField *) sender;
    [_textBeingEdited resignFirstResponder];
}
2
mtorre

この作品

この例では、aTextFieldが唯一のUITextFieldです。

// YourViewController.h
// ...
@interface YourViewController : UIViewController /* some subclass of UIViewController */ <UITextFieldDelegate> // <-- add this protocol
// ...
@end

// YourViewController.m

@interface YourViewController ()
@property (nonatomic, strong, readonly) UITapGestureRecognizer *singleTapRecognizer;
@end
// ...

@implementation
@synthesize singleTapRecognizer = _singleTapRecognizer;
// ...

- (void)viewDidLoad
{
    [super viewDidLoad];
    // your other init code here
    [self.view addGestureRecognizer:self.singleTapRecognizer];

{

- (UITapGestureRecognizer *)singleTapRecognizer
{
    if (nil == _singleTapRecognizer) {
        _singleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapToDismissKeyboard:)];
        _singleTapRecognizer.cancelsTouchesInView = NO; // absolutely required, otherwise "tap" eats events.
    }
    return _singleTapRecognizer;
}

// Something inside this VC's view was tapped (except the navbar/toolbar)
- (void)singleTapToDismissKeyboard:(UITapGestureRecognizer *)sender
{
    NSLog(@"singleTap");
    [self hideKeyboard:sender];
}

// When the "Return" key is pressed on the on-screen keyboard, hide the keyboard.
// for protocol UITextFieldDelegate
- (BOOL)textFieldShouldReturn:(UITextField*)textField
{
    NSLog(@"Return pressed");
    [self hideKeyboard:textField];
    return YES;
}

- (IBAction)hideKeyboard:(id)sender
{
    // Just call resignFirstResponder on all UITextFields and UITextViews in this VC
    // Why? Because it works and checking which one was last active gets messy.
    [aTextField resignFirstResponder];
    NSLog(@"keyboard hidden");
}
1
user246672

この場合、 ScrollView を使用してScrollViewのTextFieldに追加することができます。ScrollViewをタップしてからViewをクリックしてからキーボードを終了します。念のためにサンプルコードを作成しようとしました。このような、

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var scrollView: UIScrollView!
    @IBOutlet weak var textField: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()

        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(ViewController.tap(_:)))
        view.addGestureRecognizer(tapGesture)
        // Do any additional setup after loading the view, typically from a nib.
    }
    func tap(gesture: UITapGestureRecognizer) {
        textField.resignFirstResponder()
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

あなたのストーリーボードそれを見てください。

enter image description here

1
Ravi Dhorajiya
  • ビューでデリゲートを設定したテキストフィールドをロードしました:

    override func viewDidLoad() 
    {
      super.viewDidLoad()
      self.userText.delegate = self
    }
    
  • この機能を追加:

    func textFieldShouldReturn(userText: UITextField!) -> Bool 
    {
     userText.resignFirstResponder()
     return true;
    }
    
1
seggy

このコードを ViewController.m /ファイルに追加します。

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

UITapGestureRecognizer *singleTapGestureRecognizer = [[UITapGestureRecognizer alloc]
                                                          initWithTarget:self
                                                          action:@selector(handleSingleTap:)];
    [singleTapGestureRecognizer setNumberOfTapsRequired:1];
    [singleTapGestureRecognizer requireGestureRecognizerToFail:singleTapGestureRecognizer];

    [self.view addGestureRecognizer:singleTapGestureRecognizer];
}

- (void)handleSingleTap:(UITapGestureRecognizer *)recognizer
{
    [self.view endEditing:YES];
    [textField resignFirstResponder];
    [scrollView setContentOffset:CGPointMake(0, -40) animated:YES];

}
1
Gaurav Gilani

UITextFieldの外側をクリックすると、キーボードを閉じるためのUITapGestureRecongnizerメソッドを使用できます。ユーザーがUITextFieldの外側をクリックするたびにこのメソッドを使用することで、キーボードは消えます。以下はそれを使うためのコードスニペットです。

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

    [self.view addGestureRecognizer:tap];


//Method
- (void) dismissk
{
    [abctextfield resignFirstResponder];
    [deftextfield resignFirstResponder];

}
1
Nirzar Gandhi
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {

    if let touch = touches.first{
     view.endEditing(true)

     }
}
1
Phani Sai

それを置くテキストフィールドにメッセージresignFirstResponderを送ります。 この記事を参照してください 詳細については/。

1
Ke Sun

Swiftでこれに苦しんでいる人のために。これはJensen2kによって承認された答えですが、Swiftにあります。

スイフト2.3

    override func viewDidLoad() {
        //.....

        let viewTapGestureRec = UITapGestureRecognizer(target: self, action: #selector(handleViewTap(_:)))
        //this line is important
        viewTapGestureRec.cancelsTouchesInView = false
        self.view.addGestureRecognizer(viewTapGestureRec)

         //.....
    }

    func handleViewTap(recognizer: UIGestureRecognizer) {
        myTextField.resignFirstResponder()
    }
1
lwdthe1
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
    super.view.endEditing(true)
    super.touchesBegan(touches, withEvent: event)
}
0
Derek Dawson

In viewDidLoad Swift 4.2このようなコード

let viewTap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action:#selector(dismissKeyboard))
        view.addGestureRecognizer(viewTap)
@objc func dismissKeyboard() {
        view.endEditing(true)
    }
0
CSE 1994

ユーザーがテキストフィールドの外側をタップしたときにテキストフィールドを辞任する.mファイルでこのコードを使用するだけです。

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

だから私はただこの問題を解決しなければならず、箱から出してすぐに私のために前の答えのどれもうまくいきませんでした。私の状況はUISearchBar、それに加えて画面上の他のいくつかのコントロールです。キーボードを消すには検索バーの外側をタップする必要がありますが、notは他のコントロールにも反映されます。キーボードが隠れているときは、すべてのコントロールが機能するようにします。

私がしたこと:

1)View Controllerにカスタムタッチハンドラを実装します。

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?)
{
    if searchBar.isFirstResponder()
    {
        // This causes the first responder, whoever it is, to resign first responder, and hide the keyboard.
        // We also "eat" the touch here and not allow it to propagate further.
        view.endEditing(true)
    }
    else
    {
        // OK to propagate the touch
        super.touchesBegan(touches, withEvent: event)
    }
}

2)いくつかのデリゲートメソッドを追加しました(私のものはUISearchBar用ですが、UITextField用のものもあります)。以下のコードのcontrolContainerViewは、ボタンがたくさん入っているUIViewです。スーパービューにuserInteractionEnabledを設定すると、そのすべてのサブビューが無効になることを忘れないでください。

 func searchBarTextDidBeginEditing(searchBar: UISearchBar)
 {
     controlContainerView.userInteractionEnabled = false
     someButton.userInteractionEnabled = false
 }

 func searchBarTextDidEndEditing(searchBar: UISearchBar)
 {
     searchBar.resignFirstResponder()

    // Done editing: enable the other controls again.

    controlContainerView.userInteractionEnabled = false
    someButton.userInteractionEnabled = false
}
0
Macondo2Seattle