UITableViewの背景をタッチしてキーボードを閉じます


105

私が持っているUITableViewUITextField細胞などの。の背景をUITableViewタッチしたらキーボードを消したい。UIButtonのサイズを作成しUITableViewての後ろに配置することで、これを実現しようとしていUITableViewます。唯一の問題は、UIButtonタッチがUITableViewにある場合でも、すべてのタッチをキャッチすることです。何が悪いのですか?

ありがとう!


関連する質問と回答:Q1Q2Q3
Yantao Xie

これが最良の回答であるstackoverflow.com/a/12851794/1418457
onmyway133

回答:


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内部セルなどで発生します。


4
私がこれを試したとき、それはテーブルがセルを選択するのを妨げることに気づきました:(。それ以外の素晴らしい解決策
ブライアン

109
あなたが設定でより良いこの作業を行うことができます指摘怒鳴るの解決策として:gestureRecognizer.cancelsTouchesInView = NO;
Zebs

3
そして、それがtableViewにアタッチされたらジェスチャーレコグナイザーをリリースすることを忘れないでください。
ポールリンチ

39
hideKeyboardメソッドについては、テキストフィールドと直接通信する代わりに、を使用できます[self.view endEditing:NO];。Apple docsから:「このメソッドは、現在最初のレスポンダであるテキストフィールドの現在のビューとそのサブビュー階層を調べます。見つかった場合、そのテキストフィールドにファーストレスポンダとして辞任するように要求します。forceパラメータがはい、テキストフィールドが要求されることさえありません。辞任を余儀なくされます。
Gobot

1
この方法を使用すると、「didSelectRowAtIndexPath」メソッドが呼び出されません。このための解決策はありますか?
uniruddh 2013年

127

以下を設定した場合、UITapGestureRecognizerソリューションはテーブルセル選択で機能します。

gestureRecognizer.cancelsTouchesInView = NO;

1
これにより、セルに触れることができますが、ジェスチャーも認識されます。おそらく、このデリゲートメソッドを実装する必要がありますshouldReceiveTouch
onmyway133

61

これを行う最善の方法を次に示します。これをしてください

[self.view endEditing:YES];

または

[[self.tableView superView] endEditing:YES];

このコードはどこに置くべきですか?すみません、初心者です。そして迅速なコードを提供してください。
ジョン

54

ストーリーボードからも実行できます。 ここに画像の説明を入力してください


1
選択したものは何でも:ドラッグで閉じる、インタラクティブに閉じる、テーブルのセルに触れると、それが選択されます。私はXcode 8、Swift 3を使用しています。助けてください
John

22

UITableViewサブクラスと同様にUIScrollView、以下のデリゲートメソッドを1つ実装すると、非常に簡単で迅速なソリューションが提供されます。resignFirstResponderビュー階層は現在のレスポンダを内省して見つけ、レスポンダのステータスを辞任するように要求するため、関与する必要さえありません。

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

またUIScrollViewDelegate、ヘッダーファイルに必ず追加してください。


2
あなたはiOS7と上をターゲットにしている場合、これは@Joe Masilottiで尖ったうち、この1つのライナーを介して行うことができます: self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;
atulkhatri

上にスクロールしてキーボードを表示するはずの画面下部のテキストフィールドをタップするとどうなりますか?-キーボードが非表示になります。
イスラムQ.

Swift 4 — self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissMode.onDrag
RobLabs 2017年

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]; 

}

誰でも検索に役立つことを願っています!!



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
}

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:内でこの操作を実行しているためです。これが何らかの方法で調整されて、テーブルビューの他の場所をタップすることで機能する場合(それ以外の場合はキーボードフォーカスは必要ありません)、ここに勝者がいると思います!
Joe D'Andrea、

jdandreaと同じ問題があります。それはdidSelectRowAtIndexPathあなたがテーブルビュー自体をタップした場合に発生しません。
ゼケル

didSelectRowAtIndexPathが十分でない場合は、touchesBeganでも同じことをしてください!
Amogh Talpallikar

5

私は持っていましたがUITableViewController、実装touchesBegan:withEvent:はうまくいきませんでした。

これがうまくいきました:

迅速:

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

Objective-C:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [self.view endEditing:YES];
}

いい考えだね。
HotFudgeSunday 2016

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に設定していることを確認してください。


4

iOS7をターゲットにしている場合は、次のいずれかを使用できます。

tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;

tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;

前者はテーブルビューがスクロールされるときにキーボードを画面外にアニメーション化し、後者は標準のメッセージアプリのようにキーボードを非表示にします。

これらからであることに注意してくださいUIScrollViewUITableView継承しています。


いいね。画面の上から下にスワイプしてキーボードが下に移動し始め、キーボードが少し上に移動するまで上にスワイプしてから離すことで、なんとかそれを壊しました。スクロールビューは、本来のトップに戻りません。
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オブジェクトが発火するイベントの数は非常に大きく包括的なものです。また、プロトコルを簡単に実装してから、サブクラス化することもできます。


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
gilsaints88

2

セルの一部が選択されているときにキーボードでキーボードを開き、セル外の任意の場所をクリックした場合はキーボードを閉じたいと思っていました。キーボードを開くには:

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

(注:セルをサブクラス化しましたが、tableView:didSelectRowAtIndexPath:デリゲートメソッドでこれを簡単に実現できますUITableView

これを行うと、上位のソリューションでは、セルを2回クリックするとキーボードが揺れ、最初にジェスチャー認識機能がキーボードを閉じようとし、次にセルが再選択されてキーボードを開こうとします。

解決策は、現在選択されているセル内でクリックが発生したかどうかを確認することです。

- (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

UITableViewbackgroundView以下のSwiftに示すように、セルの選択をいじることなくこの動作を実現する便利なプロパティがあります。

let tableBackTapRecognizer = UITapGestureRecognizer(target: self, action: #selector(hideKeyboard))
tableView.backgroundView = UIView()
tableView.backgroundView?.addGestureRecognizer(tableBackTapRecognizer)


1

単にUITapGestureRecognizerを使用して、cancelsTouchesInView = NOセルとUITextViewsをタップすると、非表示もトリガーされます。複数のUITextViewがあり、次の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:がトリガーされるためには、tableViewのscrollEnabledプロパティがYES

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

私にぴったりです。texboxをtableviewセルに追加しました。キーボードの外側をタッチした場合
ニコラ

0

なぜテキストフィールドでいっぱいのテーブルを作成したいのですか?テキストフィールドを含む各行の詳細ビューを使用する必要があります。詳細ビューをプッシュするときは、「[myTextFieldがFirstResponder]」を呼び出して、ユーザーがテーブルリストからワンクリックで編集を開始できるようにしてください。


Appleの連絡先アプリはまさにこれを行います。それ自体がテキストフィールドでいっぱいだとは言いませんが、効果的に使用します。
Joe D'Andrea、

2
テーブルビューでテキストをインラインで編集する方が、ユーザーが編集するすべてのテキストフィールドに対して詳細ビューをプッシュするよりもはるかに迅速で直感的です...最も近いHTMLフォーム、iPhoneの設定ペイン、または連絡先アプリのテキストフィールドに尋ねるだけです。 etc etc etc ... Appleがこれを標準のセルタイプにしていないのは本当に残念ですが、これを達成することについてはWebに多くの情報があります。
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

Returnキーが押されているときにキーボードを閉じるには、textFieldに次のコードを追加して、メソッドを返す必要があります。

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

一部のテキストフィールドにはピッカービューまたはサブビューとして他のビューがある場合があるため、上記のメソッドは機能しないため、UITapGestureRecognizerクラスを使用する必要があります。つまり、次のコードスニペットをviewDidLoadメソッドに追加します。

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

    [self.view addGestureRecognizer:tap];

ここで、単純にresignレスポンダをセレクタメソッドに追加します。

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

それが役に立てば幸い、:)


0

多くの興味深い答え。UITableViewシナリオ(私が通常使用するもの)に最適だと考えたソリューションにさまざまなアプローチをコンパイルしたいと思います。通常、私たちが望むのは、基本的に2つのシナリオでキーボードを非表示にすることです。テキストUI要素の外側をタップすることで、または、UITableViewを上下にスクロールします。最初のシナリオはTapGestureRecognizerを介して簡単に追加でき、2番目のシナリオはUIScrollViewDelegate scrollViewWillBeginDragging:メソッドを介して追加できます。ビジネスの最初の注文、キーボードを非表示にする方法:

   /**
     *  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];

    }

このメソッドは、UITableViewビュー階層内のサブビューのすべてのtextField UIを再署名するため、すべての要素を個別に再署名するよりも実用的です。

次に、次のようにして、外部タップジェスチャを介して閉じる処理を行います。

- (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に設定することは、ジェスチャー・レコグナイザーがUITableViewの通常の内部動作をオーバーライドしないようにすることです(例えば、セルの選択を妨害しないため)。

最後に、UITableViewを上下にスクロールしてキーボードを非表示にするには、次のようにUIScrollViewDelegateプロトコルのscrollViewWillBeginDragging:メソッドを実装する必要があります。

.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
    }

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.