インターフェイスにUISearchBarがあり、テキストが入力された後に検索バーに表示される小さなクリアボタンの動作をカスタマイズしたいです(小さな灰色の円に十字が入ったものが右側に表示されます)検索フィールドの横)。
基本的に、検索バーのテキスト(デフォルトの実装)をクリアするだけでなく、インターフェースから他の項目もクリアするだけでなく、独自のメソッドの1つを呼び出すようにします。
UISearchBarクラスまたはUISearchBarDelegateプロトコルのドキュメントには何も見つかりません。この動作に直接アクセスできるようには見えません。
私が注意したことの1つは、ドキュメントがデリゲートメソッドについて説明したことです。
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText;
クリアボタンがタップされた後に呼び出されます。
最初にそのメソッドでコードを記述して、検索バーのテキストプロパティをチェックし、空の場合はクリアして、他のすべての処理を行うようにしました。
これは2つの問題:
まず、何らかの理由で、メソッドの最後に検索バーにresignFirstResponderを伝えるように言っても、どこかで、FirstResponderに戻るように設定しています。本当に忌々しい...
次に、ユーザーがクリアボタンを使用せず、キーボードの[削除]ボタンを使用してバーのテキストを削除するだけの場合、このメソッドは無効になり、検索結果が消えます。良くない。
正しい方向へのアドバイスや指針は素晴らしいでしょう!
ありがとう!
この問題のより良い解決策を見つけました:)
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{
if ([searchText length] == 0) {
[self performSelector:@selector(hideKeyboardWithSearchBar:) withObject:searchBar afterDelay:0];
}
}
- (void)hideKeyboardWithSearchBar:(UISearchBar *)searchBar{
[searchBar resignFirstResponder];
}
私のアプリにはこのコードがあります。違いは、「ライブ検索」をサポートしていないが、ユーザーがキーボードの検索ボタンに触れると検索を開始することです。
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
if ([searchBar.text isEqualToString:@""]) {
//Clear stuff here
}
}
クリアボタンのクリックで閉じるキーボードを処理するSwiftバージョン:
func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
if searchText.characters.count == 0 {
performSelector("hideKeyboardWithSearchBar:", withObject:searchBar, afterDelay:0)
}
}
func hideKeyboardWithSearchBar(bar:UISearchBar) {
bar.resignFirstResponder()
}
これが最初に出てきて、質問が実際に適切に対処されていないことがわかる限り、解決策を投稿すると思いました。
1)searchBar内のtextFieldへの参照を取得する必要があります2)起動時にtextFieldのクリアをキャッチする必要があります.
これは非常に簡単です。これが一つの方法です。
a)searchBar内でtextFieldのデリゲートメソッドを使用するため、クラスを必ずaにしてください。 b)また、searchBarをクラスのアウトレットに接続します。私はちょうど私のsearchBarを呼び出しました。 c)viewDidLoadから、searchBar内のtextFieldを取得します。私はこのようにしました。
UITextField *textField = [self.searchBar valueForKey:@"_searchField"];
if (textField) {
textField.delegate = self;
textField.tag = 1000;
}
再度取得できるように、そのtextFieldにタグを割り当て、textFieldデリゲートにしました。プロパティを作成し、このtextFieldをそのプロパティに割り当てて後で取得することもできますが、タグを使用しました。
ここから、デリゲートメソッドを呼び出すだけです。
-(BOOL)textFieldShouldClear:(UITextField *)textField {
if (textField.tag == 1000) {
// do something
return YES;
}
return NO;
}
それでおしまい。あなたはプライベートなvalueForKeyを参照しているので、それがあなたをトラブルに巻き込まないことを保証することはできません。
これを試すことができます:
- (void)viewDidLoad
{
[super viewDidLoad];
for (UIView *view in searchBar.subviews){
for (UITextField *tf in view.subviews) {
if ([tf isKindOfClass: [UITextField class]]) {
tf.delegate = self;
break;
}
}
}
}
- (BOOL)textFieldShouldClear:(UITextField *)textField {
// your code
return YES;
}
UITextFieldのrightView
およびrightViewMode
メソッドを使用して、同じ画像を使用する独自のクリアボタンを作成することをお勧めします。もちろん、UISearchBarはその中のUITextFieldにアクセスできると仮定しています。そうなると思います。
iPhone OSリファレンスライブラリのこのことに注意してください。
If an overlay view overlaps the clear button, however, the clear button always takes precedence in receiving events. By default, the right overlay view does overlap the clear button.
そのため、おそらく元のクリアボタンも無効にする必要があります。
ここでプライベートAPIを使用していない、またはプルーフをアップグレードしなかったソリューションを見つけることができませんでしたAppleはUISearchBarのビュー構造を変更します。
- (void)viewDidLoad {
[super viewDidLoad];
UITextField* textfield = [self findTextFieldInside:self.searchBar];
[textfield setDelegate:self];
}
- (UITextField*)findTextFieldInside:(id)mainView {
for (id view in [mainView subviews]) {
if ([view isKindOfClass:[UITextField class]]) {
return view;
}
id subview = [self findTextFieldInside:view];
if (subview != nil) {
return subview;
}
}
return nil;
}
次に、UITextFieldDelegateプロトコルをクラスに実装し、textFieldShouldClear:メソッドを上書きします。
- (BOOL)textFieldShouldClear:(UITextField*)textField {
// Put your code in here.
return YES;
}
編集: iOS8の検索バーのテキストフィールドにデリゲートを設定すると、クラッシュが発生します。ただし、searchBar:textDidChange:メソッドはiOS8でクリア時に呼び出されるように見えます。
私の経験からの最良の解決策は、システムのクリアボタンの上にUIButton(クリアな背景とテキストなし)を配置し、IBActionを接続することです。
- (IBAction)searchCancelButtonPressed:(id)sender {
[self.searchBar resignFirstResponder];
self.searchBar.text = @"";
// some of my stuff
self.model.fastSearchText = nil;
[self.model fetchData];
[self reloadTableViewAnimated:NO];
}