37

UISearchBarをテーブルビューに実装しましたが、1つの小さなことを除いて、ほとんどすべてが機能しています。テキストを入力してからキーボードの検索ボタンを押すと、キーボードが消え、検索結果だけが表に表示されます。テキストはUISearchBarに残りますが、キャンセルボタンは無効になります。

私は自分のリストをAppleの連絡先アプリの機能にできるだけ近づけようとしてきましたが、そのアプリで検索を押してもキャンセルボタンが無効になりません。

UISearchBarヘッダーファイルを見ると、_searchBarFlags構造体の下にあるautoDisableCancelButtonのフラグに気づきましたが、これはプライベートです。

UISearchBarをセットアップするときに欠けているものはありますか?

4

11 に答える 11

51

解決策を見つけました。この for ループを使用して、検索バーのサブビューをループし、キーボードの検索ボタンが押されたときに有効にすることができます。

for (UIView *possibleButton in searchBar.subviews)
{
    if ([possibleButton isKindOfClass:[UIButton class]])
    {
        UIButton *cancelButton = (UIButton*)possibleButton;
        cancelButton.enabled = YES;
        break;
    }
}
于 2010-12-03T19:10:57.670 に答える
3

これが私にとってiOS6で動作するようになった理由です。

searchBar.showsCancelButton = YES;
searchBar.showsScopeBar = YES;
[searchBar sizeToFit];
[searchBar setShowsCancelButton:YES animated:YES];
于 2012-11-01T02:11:19.827 に答える
3

iOS のすべてのバージョンのすべての状況で機能する私のソリューションを次に示します。

IE、ユーザーがスクロールビューをドラッグしたためにキーボードが閉じられた場合、他のソリューションは処理しません。

- (void)enableCancelButton:(UIView *)view {
    if ([view isKindOfClass:[UIButton class]]) {
        [(UIButton *)view setEnabled:YES];
    } else {
        for (UIView *subview in view.subviews) {
            [self enableCancelButton:subview];
        }
    }
}

// This will handle whenever the text field is resigned non-programatically
// (IE, because it's set to resign when the scroll view is dragged in your storyboard.)
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar {
    [self performSelector:@selector(enableCancelButton:) withObject:searchBar afterDelay:0.001];
}

// Also follow up every [searchBar resignFirstResponder];
// with [self enableCancelButton:searchBar];
于 2014-01-13T05:39:48.057 に答える
3

私の答え hereに従って、これを searchBar デリゲートに配置します。

- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar
{   
    dispatch_async(dispatch_get_main_queue(), ^{
        __block __weak void (^weakEnsureCancelButtonRemainsEnabled)(UIView *);
        void (^ensureCancelButtonRemainsEnabled)(UIView *);
        weakEnsureCancelButtonRemainsEnabled = ensureCancelButtonRemainsEnabled = ^(UIView *view) {
            for (UIView *subview in view.subviews) {
                if ([subview isKindOfClass:[UIControl class]]) {
                    [(UIControl *)subview setEnabled:YES];
                }
                weakEnsureCancelButtonRemainsEnabled(subview);
            }
        };

        ensureCancelButtonRemainsEnabled(searchBar);
    });
}
于 2014-09-05T12:53:08.213 に答える
2

答えはどれも私にとってはまったく役に立ちませんでした。iOS 7 をターゲットにしていますが、答えが見つかりました。

私が試しているのは、Twitter iOS アプリのようなものです。[タイムライン] タブの虫めがねをクリックUISearchBarすると、[キャンセル] ボタンがアクティブになり、キーボードが表示され、最近の検索画面が表示されます。最近の検索画面をスクロールすると、キーボードが非表示になりますが、[キャンセル] ボタンがアクティブなままになります。

これは私の作業コードです:

UIView *searchBarSubview = self.searchBar.subviews[0];
NSArray *subviewCache = [searchBarSubview valueForKeyPath:@"subviewCache"];
if ([subviewCache[2] respondsToSelector:@selector(setEnabled:)]) {
    [subviewCache[2] setValue:@YES forKeyPath:@"enabled"];
}

テーブルビューにブレークポイントを設定することで、この解決策にたどり着きましたscrollViewWillBeginDragging:。私は自分を調べて、UISearchBarそのサブビューをむき出しにしました。それは常にタイプUIView( my variable searchBarSubview)の1つだけを持っています。

ここに画像の説明を入力

次に、それは呼び出されたものをUIView保持し、最後の要素である 3 番目の要素がパブリック API ではなくタイプであることに気付きました。そこで、代わりにキー値コーディングを使用することにしました。が に応答するかどうかを確認したところ、幸いにも応答しました。そこで、プロパティを に設定しました。それキャンセルボタンであることがわかりました。NSArraysubviewCacheUINavigationButtonUINavigationButtonsetEnabled:@YESUINavigationButton

Apple が a の内部の実装を変更することを決定した場合、これは壊れるにUISearchBar違いありませんが、一体何でしょう。今のところ動作します。

于 2014-02-25T17:20:49.780 に答える
1

より完全な答え:

  • iOS 7 以降、searchBar の下に追加レベルのサブビューがあります。
  • キャンセルボタンを有効にするのに適した場所はsearchBarTextDidEndEditing

.

extension MyController: UISearchBarDelegate {
  public func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
    DispatchQueue.main.async {
    // you need that since the disabling will
    // happen after searchBarTextDidEndEditing is called
      searchBar.subviews.forEach({ view in
        view.subviews.forEach({ subview in
          // ios 7+
          if let cancelButton = subview as? UIButton {
            cancelButton.isEnabled = true
            cancelButton.isUserInteractionEnabled = true
            return
          }
        })
        // ios 7-
        if let cancelButton = subview as? UIButton {
          cancelButton.isEnabled = true
          cancelButton.isUserInteractionEnabled = true
          return
        }
      })
    }
  }
}
于 2016-12-04T04:05:59.620 に答える
1

Monotouch または Xamarin iOS の場合、iOS 7 および iOS 8 で動作する次の C# ソリューションがあります。

foreach(UIView view in searchBar.Subviews)
{
    foreach(var subview in view.Subviews)
    {
        //Console.WriteLine(subview.GetType());
        if(subview.GetType() == typeof(UIButton))
        {
            if(subview.RespondsToSelector(new Selector("setEnabled:")))
            {
                UIButton cancelButton = (UIButton)subview;
                cancelButton.Enabled = true;
                Console.WriteLine("enabledCancelButton");
                return;
            }
        }
    }
}

この回答は、 David Douglasソリューションに基づいています。

于 2015-01-09T14:31:26.547 に答える