テーブル内の多くのテーブルセルにかなりの数のコントロールが散在しているので、すべてのコントロールをループしてすべてをファーストレスポンダーとして辞任することなく、キーボードを閉じる簡単な方法があるかどうか疑問に思いました。質問は..キーボードへの現在のファーストレスポンダーをどのように取得しますか?
31 に答える
試す:
[self.view endEditing:YES];
nil ターゲット アクションをアプリケーションに送信できます。アプリケーションは、現在どのビューがファーストレスポンダー ステータスになっているかを気にすることなく、いつでもファーストレスポンダーを辞任します。
目的 C:
[[UIApplication sharedApplication] sendAction:@selector(resignFirstResponder) to:nil from:nil forEvent:nil];
スウィフト 3.0:
UIApplication.shared.sendAction(#selector(resignFirstResponder), to: nil, from: nil, for: nil)
メニュー コマンドの Mac OS X では Nil ターゲット アクションが一般的であり、iOS での使用例を次に示します。
正直に言うと、ここで提案されている解決策のどれにも夢中になっているわけではありません。問題の核心に到達すると思われる TapGestureRecognizer を使用する良い方法を見つけました。キーボード以外のものをクリックすると、キーボードが閉じます。
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:)];
キーボードの表示/非表示レスポンダーを追加します。そこで、タップ時にキーボードを閉じる必要がある UIView に TapGestureRecognizer を追加および削除します。注: すべてのサブビューまたはコントロールに追加する必要はありません。
-(void) keyboardWillShow:(NSNotification *) note { [self.view addGestureRecognizer:tapRecognizer]; } -(void) keyboardWillHide:(NSNotification *) note { [self.view removeGestureRecognizer:tapRecognizer]; }
TapGestureRecognizer はタップを取得すると関数を呼び出し、次のようにキーボードを閉じることができます。
-(void)didTapAnywhere: (UITapGestureRecognizer*) recognizer { [textField resignFirstResponder]; }
このソリューションの優れた点は、スワイプではなくタップのみをフィルタリングすることです。そのため、キーボードの上にスクロールするコンテンツがある場合、スワイプしてもスクロールされ、キーボードは表示されたままになります。キーボードがなくなった後にジェスチャ レコグナイザーを削除することで、ビューでの今後のタップが正常に処理されるようになります。
これは、コードを 1 か所に追加することで、任意のreturn
テキスト フィールドでヒットしたときにキーボードが消えるようにするためのソリューションです(テキスト フィールドごとにハンドラーを追加する必要はありません)。
次のシナリオを検討してください。
2viewcontroller
つのテキストフィールド (ユーザー名とパスワード) があります。そしてviewcontroller
実装UITextFieldDelegate
プロトコル
私はviewDidLoadでこれを行います
- (void)viewDidLoad
{
[super viewDidLoad];
username.delegate = self;
password.delegate = self;
}
ビューコントローラーはオプションのメソッドを次のように実装します
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
あなたがいるテキストフィールドに関係なくreturn
、キーボードを押すとすぐに消えます!
あなたの場合、すべてのテキストフィールドのデリゲートを自分自身に設定して実装する限り、同じことが機能しますtextFieldShouldReturn
より良いアプローチは、ファーストレスポンダーのステータスを「盗む」何かを持つことです。
UIApplication は UIResponder のサブクラスであるため、以下を試すことができます。
[[UIApplication sharedApplication] becomeFirstResponder]
[[UIApplication sharedApplication] resignFirstResponder]
それに失敗した場合は、サイズがゼロのフレームで新しい UITextField を作成し、それをどこかのビューに追加して、同様のことを行います (become の後に辞任します)。
これをいくつかのユーティリティ クラスに隠します。
+ (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];
}
}
@Nicholas Riley & @Kendall Helmstetter Geln & @cannyboy:
絶対に素晴らしいです!
ありがとうございました。
あなたのアドバイスとこのスレッドの他の人のアドバイスを考慮して、これは私がやったことです:
使用時の外観:
[[self appDelegate] dismissKeyboard];
(注:NSObjectへの追加としてappDelegateを追加したので、どこでもどこでも使用できます)
ボンネットの下は次のようになります。
- (void)dismissKeyboard
{
UITextField *tempTextField = [[[UITextField alloc] initWithFrame:CGRectZero] autorelease];
tempTextField.enabled = NO;
[myRootViewController.view addSubview:tempTextField];
[tempTextField becomeFirstResponder];
[tempTextField resignFirstResponder];
[tempTextField removeFromSuperview];
}
編集
included に対する私の回答の修正tempTextField.enabled = NO;
。テキスト フィールドを無効にすると、アプリ全体でこれらの通知に依存している場合UIKeyboardWillShowNotification
、キーボード通知が送信されなくなります。UIKeyboardWillHideNotification
ユーザーが UITextField またはキーボード以外の画面上の任意の場所に触れたときに、iOS でキーボードを閉じる方法に関する簡単なヒント。iOS キーボードがどれだけの領域を占めるかを考えると、ユーザーがキーボードを閉じるための簡単で直感的な方法を用意することは理にかなっています。
これが私のコードで使用するものです。それは魅力のように機能します!
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];
}
おそらく、これはiOSのドキュメントで見つけるのが簡単ではないため、ここには非常に複雑な答えがたくさんあります。JosephHはそれを真上に持っていました:
[[view window] endEditing:YES];
Megarの答えよりもさらに簡単
上書きtouchesBegan:withEvent:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[textField resignFirstResponder];`
}
これはdismiss the keyboard
、 のどこかをタッチしたときに発生しますbackground
。
endEditing:
のサブクラスである作業ウィンドウに送信する必要がありますUIView
[[UIApplication sharedApplication].windows.firstObject endEditing:NO];
ビューコントローラーのヘッダーファイル<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;
}
場合によっては、これを機能させるために UIViewController disablesAutomaticKeyboardDismissal をオーバーライドする必要がある場合もあります。UINavigationController がある場合、これを行う必要があるかもしれません。
テキストフィールドをサブクラス化...そしてテキストビューも
サブクラスにこのコードを入れます..
-(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];
}
すべて設定..コードのどこからでも通知を投稿するだけです。それは、任意のキーボードを辞任します。
そして迅速にできること
UIApplication.sharedApplication().sendAction("resignFirstResponder", to: nil, from: nil, forEvent: nil)
ジェレミーの答えは私にとってはうまくいきませんでした.タブビューにナビゲーションスタックがあり、その上にモーダルダイアログがあったためだと思います. 私は現在以下を使用しており、うまく機能していますが、マイレージは異なる場合があります。
// 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];
}
キーボードがポップアップした後にキーボードを閉じるには、2 つのケースがあります。
UITextField がUIScrollView 内にある場合
UITextField がUIScrollView の外にある場合
2. UITextField が UIScrollView の外側にある場合、UIViewController サブクラスのメソッドをオーバーライドします
すべての UITextView のデリゲートも追加する必要があります
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self.view endEditing:YES];
}
- スクロール ビューでは、外側をタップしてもイベントは発生しないため、その場合は Tap Gesture Recognizer を使用し、スクロール ビューのUITapGestureをドラッグ アンド ドロップして、 IBAction を作成します。
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/
最も簡単な方法は、メソッドを呼び出すことです
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if(![txtfld resignFirstResponder])
{
[txtfld resignFirstResponder];
}
else
{
}
[super touchesBegan:touches withEvent:event];
}
サブビューを再帰的に反復し、すべての UITextField の配列を保存してから、それらをループしてすべて再署名することができます。
特にサブビューがたくさんある場合は、それほど優れたソリューションではありませんが、単純なアプリの場合はうまくいくはずです。
私はこれをはるかに複雑でよりパフォーマンスの高い方法で解決しましたが、アプリのアニメーションエンジンにシングルトン/マネージャーを使用し、テキストフィールドがレスポンダーになるたびに、それを取得する静的に割り当てます他の特定の出来事に基づいて一掃された(辞任した)... 私が段落で説明することはほとんど不可能です.
この質問を見つけてから、自分のアプリについて考えるのに 10 分しかかかりませんでした。
迅速に:
self.view.endEditing(true)
これらの方法のいずれかを使用する必要があります。
[self.view endEditing:YES];
また
[self.textField resignFirstResponder];
アップデート
別の簡単な方法を見つけました
プロパティを宣言するだけです:-
@property( strong , nonatomic) UITextfield *currentTextfield;
およびタップ ジェスチャー ジェコグナイザー:-
@property (strong , nonatomic) UITapGestureRecognizer *resignTextField;
ビューでDidLoad
_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];
}
きれいではありませんが、レスポンダーが何であるかわからない場合に firstResponder を辞任する方法は次のとおりです。
IB またはプログラムで UITextField を作成します。非表示にします。IB で作成した場合は、コードにリンクします。次に、キーボードを閉じたい場合は、レスポンダーを非表示のテキスト フィールドに切り替えて、すぐに辞任します。
[self.invisibleField becomeFirstResponder];
[self.invisibleField resignFirstResponder];
最近使用する必要があった、もう少し堅牢な方法:
- (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];
}
他の「グローバル」メソッドのいくつかが機能しないことがわかりました (たとえば、UIWebView
&WKWebView
は辞任を拒否しました)。
View に 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];
}
それは私のために働いた
私は、プライベート API 呼び出しを使用せずにプログラムでキーボードを閉じる「グローバル」な方法がないことを嫌います。どのオブジェクトがファーストレスポンダなのかを知らずに、プログラムでキーボードを閉じる必要があることがよくあります。私はself
、Objective-C ランタイム API を使用して を検査し、そのすべてのプロパティを列挙し、タイプのものを取り出し、それらにメッセージUITextField
を送信することに頼りました。resignFirstResponder
これを行うのはそれほど難しくないはずです...