28

キャンセル ボタンがある UISearchBar があります ( を使用して表示されます-(void)setShowsCancelButton:animated)。tintColor灰色がかった検索バーを取得するために、次のように検索バーを変更しました。

UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320, 40)];
searchBar.tintColor = [UIColor colorWithWhite:0.8 alpha:1.0];

これが現在の外観です - キャンセル ボタンもグレーになっていることに注意してください: http://twitpic.com/c0hte

キャンセル ボタンの色を個別に設定して、次のようにする方法はありますか: http://twitpic.com/c0i6q

4

21 に答える 21

27

UIAppearanceのサブビューを繰り返さずにキャンセルボタンのスタイルを設定するために使用できますUISearchBarUIButtonヘッダーには現在、。で注釈が付けられたメソッドがありませんUI_APPEARANCE_SELECTOR

編集:キャンセルボタンが表示されるまでサブビューをドリルダウンします

searchBar.setShowsCancelButton(true, animated: true)ただし、これは通常、が呼び出されるまでnilを返します 。

extension UISearchBar {

var cancelButton : UIButton? {
    if let view = self.subviews.first {
        for subView in view.subviews {
            if let cancelButton = subView as? UIButton {
                return cancelButton
            }
        }
    }
    return nil
}
}
于 2012-04-11T15:00:38.500 に答える
20

「キャンセル」ボタンのタイトルを変更します。

[[UIButton appearanceWhenContainedIn:[UISearchBar class], nil] setTitle:@"newTitle" forState:UIControlStateNormal];

Swiftと同等:

   let cancelButton = UIButton.appearance(whenContainedInInstancesOf: [UISearchBar.self])
   cancelButton?.setTitle("cancel".localized, for: .normal)
于 2012-10-01T10:26:15.857 に答える
20

appearnceiOS 5.0 以降では、プロキシを使用できます。

検索バーが表示される前:

UIBarButtonItem *searchBarButton = [UIBarButtonItem appearanceWhenContainedIn:[UISearchBar class], nil];
[searchBarButton setBackgroundImage:myCancelButtonImageNormal forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[searchBarButton setBackgroundImage:myCancelButtonImageHighlighted forState:UIControlStateHighlighted barMetrics:UIBarMetricsDefault];
[searchBarButton setTitleTextAttributes:barButtonTitleTextAttributesNormal forState:UIControlStateNormal];
[searchBarButton setTitleTextAttributes:barButtonTitleTextAttributesHighlighted forState:UIControlStateHighlighted];

を使用する[UIButton appearanceWhenContainedIn:[UISearchBar class], nil]と、他のボタン (クリア ボタンなど) に影響します。ですから、 の外観は使用しない方がよいでしょうUIButton。試してみてくださいUIBarButtonItem

于 2012-12-21T08:17:47.687 に答える
17

これは元の質問とは正確には関係ないかもしれませんが、UISearchBar の [キャンセル] ボタンをカスタマイズしようとするというより大きな意味で、解決策は引き続き適用できます。これは、そのようなシナリオで立ち往生している他の人を助けると思いました.

私の状況は、キャンセル ボタンのタイトルを変更することでしたが、ひねりを加えて、デフォルトではキャンセル ボタンを表示したくありませんでしたが、ユーザーが検索モードに入ったときに (検索テキスト フィールド内をクリックして) 表示したいだけでした。 )。この時点で、キャンセル ボタンに「完了」というキャプションを付けたいと思いました (「キャンセル」は画面に別の意味を与えていたため、カスタマイズされていました)。

それにもかかわらず、これが私がやったことです(caelavelとArenimのソリューションの組み合わせ):

次の 2 つのメソッドを使用して、UISearchBar を MyUISearchBar としてサブクラス化しました。

-(void) setCloseButtonTitle: (NSString *) title forState: (UIControlState)state
{
    [self setTitle: title forState: state forView:self];
}

-(void) setTitle: (NSString *) title forState: (UIControlState)state forView: (UIView *)view
{
    UIButton *cancelButton = nil;
    for(UIView *subView in view.subviews){
        if([subView isKindOfClass:UIButton.class])
        {
            cancelButton = (UIButton*)subView;
        }
        else
        {
            [self setTitle:title forState:state forView:subView];
        }
    }

    if (cancelButton)
        [cancelButton setTitle:title forState:state];

}

そして、この検索バーを使用するビューコントローラーでは、次のコードがキャンセル ボタンの表示とそのタイトルのカスタマイズを処理します。

- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
    MyUISearchBar *sBar = (MyUISearchBar *)searchBar;
    [sBar setShowsCancelButton:YES];
    [sBar setCloseButtonTitle:@"Done" forState:UIControlStateNormal];   
}

奇妙なことに、検索モードを終了すると、キャンセル ボタンはデフォルトで非表示になっているため、キャンセル ボタンを非表示にするために何もする必要はありませんでした。

于 2010-10-03T15:27:38.057 に答える
13

あなたがやりたいことはかなり難しいです。キャンセル ボタンを取得する組み込みのフックはありません。

ただし、ボンネットをジミーで開けたい場合は、いくつかのオプションがあります。

まず、UISearchBar は UIView であり、[キャンセル] ボタンもビューであり、ご想像のとおり、サブビューとして検索バーに追加されます。

少し実験したところ、ボタンが画面上にあるときのサイズは 48.30 であることがわかります。

したがって、viewWillAppear では、次のようなことができます。

  1. [searchBar subviews] でサイズ 48,30 のキャンセル ボタン ビューを探します。(1 つだけのようです -- これは変更される可能性があります...) 2 重に注意して、ほぼ正しい位置にあるものを探すことができます (横向きと縦向きでは異なります)。

  2. キャンセル ボタンにサブビューを追加します。

  3. サブビューはUIControlである必要があります(タッチイベントが実際のキャンセルボタンに到達するようにするために、有効= NOに設定できるようにします)

  4. 適切な色と丸みを帯びた角が必要です。私がまだ理解していない理由でサイズをごまかす必要があります(55,30はうまくいくようです)

  5. これは、searchBar.showsCancelButton が常に YES の場合に機能します。検索文字列を編集していないときに非表示にしたい場合は、キャンセル ボタンが表示されるたびにオーバーレイを追加するフックを見つける必要があります。

  6. ご覧のとおり、これはいじくり回しです。目を大きく開いた状態で行います。

于 2009-07-29T15:00:19.053 に答える
7

キャンセル ボタンを設定する場合は、オブジェクトからオブジェクトUISearchBarを取得する必要があります。以下の例UIButtonUISearchBar

UISearchBar *s_bar = [[UISearchBar alloc] initWithFrame:CGRectMake(50,20,300,30)];
s_bar.delegate = self;
s_bar.barStyle = UIBarStyleDefault;
s_bar.showsCancelButton = YES;
UIButton *cancelButton;
for (id button in s_bar.subviews)
{
    if ([button isKindOfClass:[UIButton class]])
    {
        cancelButton=(UIButton*)button;
        break;
    }
}
于 2011-03-03T11:08:11.143 に答える
7

検索バーのサブビューをループして (サイズではなく) クラス タイプをチェックすることで、キャンセル ボタンを見つけることができます。

UIButton *cancelButton = nil;
for(UIView *subView in yourSearchBar.subviews){
    if([subView isKindOfClass:UIButton.class]){
    cancelButton = (UIButton*)subView;
    }
}

次に、色合いを変更します。

[cancelButton setTintColor:[UIColor colorWithRed:145.0/255.0 green:159.0/255.0 blue:179.0/255.0 alpha:1.0]];
于 2010-05-11T23:17:28.363 に答える
4

カスタム UISearchBar とオーバーライド メソッド -addSubview:

- (void) addSubview:(UIView *)view {
    [super addSubview:view];

    if ([view isKindOfClass:UIButton.class]) {
        UIButton *cancelButton = (UIButton *)view;
        [cancelButton setBackgroundImage:[UIImage imageNamed:@"xxxx.png"] forState:UIControlStateNormal];
        [cancelButton setBackgroundImage:[UIImage imageNamed:@"yyyy.png"] forState:UIControlStateHighlighted];
    }
}
于 2011-09-21T09:03:44.400 に答える
1

スウィフト 2.1.1:

検索バーをフックしてスタイルを設定する簡単な方法はありません。検索バーから手動でサブビューを取得してから、変更を適用する必要があります。

var cancelButton: UIButton
let topView: UIView = self.customSearchController.customSearchBar.subviews[0] as UIView
for subView in topView.subviews {
 if subView.isKindOfClass(NSClassFromString("UINavigationButton")!) {
    cancelButton = subView as! UIButton
    cancelButton.enabled = true
    cancelButton.setTitle("TestTitle", forState: UIControlState.Normal) // Change to set the title
    cancelButton.setBackgroundImage(UIImage(named: "ImageName"), forState: .Normal) // Change this to set a custom cancel button image, set the title to "" to remove 'Cancel' text
   }
}
于 2016-05-23T02:31:55.103 に答える
1

まず、このhttps://stackoverflow.com/a/37381821/1473144から @Eliott に感謝したいと思います。

彼の答えが以下の仕様で機能するように、いくつかの調整を行う必要がありました。受け入れられた回答は非常に古くなっているため、OPに更新を依頼してください。

スウィフト 3、iOS 10 & Xcode 8.2.1

searchBar.showsCancelButton = true
var cancelButton: UIButton
let topView: UIView = self.searchBar.subviews[0] as UIView
for subView in topView.subviews {
    if let pvtClass = NSClassFromString("UINavigationButton") {
        if subView.isKind(of: pvtClass) {
            cancelButton = subView as! UIButton

            cancelButton.setTitle("", for: .normal)
            cancelButton.tintColor = UIColor.black
            cancelButton.setImage(#imageLiteral(resourceName: "searchX"), for: .normal)
        }
    }

}
于 2017-01-05T17:02:27.843 に答える
1

UISearchBar を初期化したら、そのサブビューを調べて、それぞれをカスタマイズできます。例:

for (UIView *view in searchBar.subviews) {

    //if subview is the button
    if ([[view.class description] isEqualToString:@"UINavigationButton"]) {

        //change the button images and text for different states
        [((UIButton *)view) setEnabled:YES];
        [((UIButton *)view) setTitle:nil forState:UIControlStateNormal];
        [((UIButton *)view) setImage:[UIImage imageNamed:@"button image"] forState:UIControlStateNormal];
        [((UIButton *)view) setBackgroundImage:[UIImage imageNamed:@"button"] forState:UIControlStateNormal];
        [((UIButton *)view) setBackgroundImage:[UIImage imageNamed:@"button_pressed"] forState:UIControlStateSelected];
        [((UIButton *)view) setBackgroundImage:[UIImage imageNamed:@"button_pressed"] forState:UIControlStateHighlighted];

    //if the subview is the background
    }else if([[view.class description] isEqualToString:@"UISearchBarBackground"]) {

        //put a custom gradient overtop the background
        CAGradientLayer *gradient = [CAGradientLayer layer];
        gradient.frame = view.bounds;
        gradient.colors = [NSArray arrayWithObjects:(id)[[some uicolor] CGColor], (id)[[another uicolor] CGColor], nil];
        [view.layer insertSublayer:gradient atIndex:0];

    //if the subview is the textfield
    }else if([[view.class description] isEqualToString:@"UISearchBarTextField"]){

        //change the text field if you wish

    }

}

私にとってはうまくいきました!特にグラデーション:)

于 2011-10-14T14:15:12.927 に答える
0

さて、ここにキャンセルのボタンラベルを変更できる関数があります。必要に応じて変更してください。使用法は次のとおりです。

nStaticReplaceStringInView(mySearchBar, @"Cancel", @"NewCancelButtonLabel");

void nStaticReplaceStringInView(UIView * view, NSString * haystack, NSString * needle)
{
 for(int i=0; i<[view.subviews count]; i++)
 {
  nStaticReplaceStringInView([view.subviews objectAtIndex:i], haystack,needle);
 }
 if([view respondsToSelector:@selector(titleForState:)])
 {
  //NSLog(@"%@ || %@",[view titleForState:UIControlStateNormal], haystack);
  if(NSStrEq([view titleForState:UIControlStateNormal] , haystack))
  {
   [view setTitle: needle forState: UIControlStateNormal];
  }
 }
}
于 2010-08-19T08:08:00.187 に答える
0

アプリ全体にUISearchBarアイテムがたくさんあるので、このカテゴリを作成して、にアクセスできるようにプロパティを追加しましたmySearchBar.cancelButton。(カテゴリを初めて使用する場合は、カテゴリを使用したオブジェクトの拡張について詳しくは、こちらをご覧ください。)

UISearchBarは表示されるたびに新しいボタンオブジェクトを作成するように見えるため、[キャンセル]ボタンが表示されている場合にのみこれにアクセスする必要があることに注意してください。cancelButtonへのポインターを保存せず、必要なときに取得してください。

@interface UISearchBar (cancelButton)

@property (readonly) UIButton* cancelButton;

- (UIButton *) cancelButton;

@end

@implementation UISearchBar (cancelButton)

- (UIButton *) cancelButton {
    for (UIView *subView in self.subviews) {
        //Find the button
        if([subView isKindOfClass:[UIButton class]])
        {
            return (UIButton *)subView;
        }
    }

    NSLog(@"Error: no cancel button found on %@", self);

    return nil;
}

@end
于 2012-12-17T19:30:04.780 に答える
0
- (void) searchBarTextDidBeginEditing:(UISearchBar *)theSearchBar 
{        
    NSArray *arr = [theSearchBar subviews];
    UIButton *cancelButton = [arr objectAtIndex:3];
    [cancelButton setTitle:@"yourtitle" forState:UIControlStateNormal];    
}

arr amd のログを取って、インデックス コントロールがどこにあるかを確認してください。UITextField同様に、プロパティを設定できます。

    NSArray *arr = [searchbar subviews];
    UITextField *searchfield = [arr objectAtIndex:2];
    [searchfield setTextAlignment:UITextAlignmentRight];
于 2012-08-08T06:05:40.053 に答える
0

愚かな方法

for(id cc in [SearchBar subviews])
{
    if([cc isKindOfClass:[UIButton class]])
    {
        UIButton *btn = (UIButton *)cc;
        ......
        Do whatever you want
        .......        
    }
}
于 2013-03-29T08:38:29.237 に答える
0

cancelButtonを使用せずにスタイリングする最良の方法UIAppearanceは、このようなものであり、あまりにもSwift5 iOS13うまく機能しますUISearchResultController.searchBar

extension UISearchBar {
    func changeSearchBarAppearance(appearance: MyAppearance) {
        self.barTintColor = appearance.searchbar.barTintColor
        self.tintColor  =  appearance.searchbar.tintColor
        if let textField = self.subviews.first?.subviews.last?.subviews.first {
            textField.tintColor = .black
        }
    }
}

設定serachBar tintColortintColorを含むすべての項目の を設定しますcancelButtonが、これにより のウインカーsearchFieldも同じtintColorように設定されるので、 を見つけてtextfield設定するtintColorと、ウインカーの問題が解決します

于 2019-12-17T08:19:11.710 に答える
0

iOS 10 以降の場合、次の方法を使用します

[[UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]] setTintColor:[UIColor blackColor]];
于 2019-10-03T10:25:33.770 に答える