検索テキスト ボックスの下とキーボードの上をタップしたときに、UISearchBar からキャンセルする (ファーストレスポンダーを辞任する) 方法を知っている人はいますか? これを処理するためのコードを投稿するのを手伝ってくれる人はいますか?
ありがとう
検索テキスト ボックスの下とキーボードの上をタップしたときに、UISearchBar からキャンセルする (ファーストレスポンダーを辞任する) 方法を知っている人はいますか? これを処理するためのコードを投稿するのを手伝ってくれる人はいますか?
ありがとう
(UISearchbar の) 親ビューにタップ ジェスチャを追加します。
[self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:searchBar action:@selector(resignFirstResponder)]];
UITapGestureRecognizer を使用してこれを実現しました。
UIGestureRecognizer* cancelGesture;
- (void) backgroundTouched:(id)sender {
[self.view endEditing:YES];
}
#pragma mark - UISearchBarDelegate
-(void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
cancelGesture = [UITapGestureRecognizer new];
[cancelGesture addTarget:self action:@selector(backgroundTouched:)];
[self.view addGestureRecognizer:cancelGesture];
}
-(void)searchBarTextDidEndEditing:(UISearchBar *)searchBar {
if (cancelGesture) {
[self.view removeGestureRecognizer:cancelGesture];
[cancelGesture release];
cancelGesture = nil;
}
}
コードはむき出しですが、意図はわかります。SearchBar が編集を開始したら、ビュー コントローラーのビューにタップ ジェスチャ レコグナイザーをアタッチし、編集が終了したらそれを削除します。
回避できるいくつかの注意事項があります。これを行うと、キーボードまたは検索バーのテキスト フィールド以外のものをクリックすると、認識エンジンがクリックをトラップします。したがって、クリア、キャンセル、スコープ、または結果を使用する場合ボタンは正しく反応しません。
私の特定のシナリオでは、ビューの公開領域をカバーする UITableView があったため、ビュー コントローラーのメイン ビューの代わりにジェスチャ レコグナイザーをアタッチし、ジェスチャが応答する領域を分離しました。
私がiphonedevbook、サンプルコードプロジェクト04から得た別のアイデアは、他のすべてのコントロールの背後にある1つの大きな透明なボタンを使用することでした。これは、タップするとすべてのファーストレスポンダーを辞任するだけです。つまり、ユーザーがより重要なコントロールがない場所(直感的な動作)をタップすると、検索バーとキーボードが消えます。
最終的には、Hauke のアプローチと Beau Scott のアプローチのハイブリッドを使用することになりました。彼らのソリューションを使用して遭遇した2つの問題がありました。
1) 画面に何か他のものがある場合、それをタップしても、resignFirstResponder は呼び出されません。たとえば、ユーザーがボタンの周囲のスペースではなくボタンをタップすると、ボタンはイベントを食べます。ただし、Beau Scott のソリューションはこの問題に対処しています。
2) 検索バー自体をタップすると、resignFirstResponder が呼び出されます。明らかに、UISearchBar をタップしたときにキーボードが消えるのは望ましくありません。以下に説明する小さな変更により、これに対処します。
私は最終的に次のようにビューを設定しました。親ビューには、UISearchBar と残りの UI 要素を保持するサブビューの 2 つの子があります。サブビューは、UISearchBar の下の画面全体を占めます。次に、Beau Scott の正確なコードを使用してジェスチャ認識エンジンを追加および削除しましたが、それを self.view に追加する代わりに、サブビューに追加しました。
IBOutlet UIView *gestureRecognizer;
...
-(void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
cancelGesture = [UITapGestureRecognizer new];
[cancelGesture addTarget:self action:@selector(backgroundTouch:)];
[gestureRecognizer addGestureRecognizer:cancelGesture];
}
-(void)searchBarTextDidEndEditing:(UISearchBar *)searchBar {
if (cancelGesture) {
[gestureRecognizer removeGestureRecognizer:cancelGesture];
[cancelGesture release];
cancelGesture = nil;
}
}
まず、検索バーへの参照が必要です。コントローラー オブジェクトにオブジェクト参照 UISearchBar *theSearchBar があり、UISearchBar オブジェクトを作成するときにそれを割り当てるとします。
次に、含まれているビューがタッチされたことを検出する必要があります。触れられたビューは「知っています」が、その情報をコントローラーに取得する必要があります。悲しいことに、Apple はこれを行うための簡単な方法を提供していませんが、それほど難しくもありません。
私の解決策は、UIViewController オブジェクトが通常 UIControl で作成する標準の UIView を置き換え、UIViewController をタッチ イベントに応答させることです。
MainController.m
- (void) loadView {
UIControl *control = [[UIControl alloc] initWithFrame: <desired frame>];
[control addTarget: self action: @selector(touchUpInside)
forControlEvents: UIControlEventTouchUpInside];
// or touch down events, or whatever you like
self.view = control;
[control release];
}
- (void) viewDidLoad {
[super viewDidLoad];
theSearchBar = [[UISearchBar alloc] initWithFrame: <desired frame>];
// insert code to finish customizing the search bar
[self.view addSubview: theSearchBar];
}
- (void) touchUpInside {
if [theSearchBar isFirstResponder] {
// grab any data you need from the search bar
[theSearchBar resignFirstResponder];
}
}
MainController.h
@interface MainController : UIViewController
{
UISearchBar *theSearchBar;
}
説明:
UIViewController のサブクラスであるクラス MainController を呼び出しましょう。上記のメソッドはすべて MainController に実装されています。theSearchBar は、.h ファイルで UISearchBar* として宣言されています。
Are you defining your view and controller using Interface Builder? If so, I suggest you learn how to NOT use it -- once you get into the kind of tricks we are discussing here, it becomes more of a hindrance than a help -- I don't use it at all, ever.
@Gia Dangの答えは最も簡単ですが、私はUIView
のみをサブクラス化しないUIViewController
ので、私の呼び出しは少し異なります。また、実際に を呼び出すためのオーバーヘッドがわからないので、resignFirstResponder
最初に確認することを好みます。これはより多くのコードですが、これはすべてメイン スレッドで行われるため (UI の速度が低下する可能性があります)、最初に確認したいと思います。
@implementation MyController : UIViewController {
@private
UISearchController *_uiSearchController;
}
- (void)viewDidLoad {
// add tap on view to resign the responder if we're in the middle of typing in the search
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(closeKeyboardIfNeeded)];
[self.view addGestureRecognizer:tapGestureRecognizer];
}
- (void)closeKeyboardIfNeeded {
if (![_uiSearchController.searchBar isFirstResponder]) {
return;
}
[_uiSearchController.searchBar resignFirstResponder];
}
@end
他の答えについては、常にオブジェクトを再作成することに注意してください。作成そのものであろうと、 ARCを介したガベージ コレクションであろうと、常にパフォーマンス ヒットが発生し、これらによってメイン スレッドが遅くなります。メインスレッドでも何をしているかによっては、パフォーマンスに大きな影響を与える可能性があります。