2009-07-29 97 views
26

我有一個UISearchBar有一個取消按鈕(它顯示使用-(void)setShowsCancelButton:animated)。我已經改變了這樣的搜索欄的tintColor,試圖得到一個淺灰色的搜索欄:造型取消按鈕在UISearchBar

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

+0

爲什麼不在這裏嵌入圖像? – 2017-03-25 08:03:03

回答

14

你想要做的事情非常艱難。沒有內置的鉤子來取消取消按鈕。

但是,如果您願意吉米打開引擎蓋,有幾個選項。

首先,UISearchBar是一個UIView,取消按鈕也是一個視圖,它被作爲子視圖添加到搜索欄中,就像您期望的那樣。

我已經試驗了一下,可以告訴你,當按鈕在屏幕上時,它的大小爲48,30。

因此,在viewWillAppear中,你可以做這樣的事情:

  1. 查找[搜索欄子視圖]取消按鈕視圖與尺寸48,30找一個。 (似乎只有一個 - 這可能會改變...)你可能會加倍小心,並尋找一個近似正確的位置(風景和肖像不同)。

  2. 將子視圖添加到取消按鈕。

  3. 子視圖應該是一個UIControl(使您可以設置啓用= NO,以確保觸摸事件獲得實際的取消按鈕)

  4. 它需要有正確的顏色和圓角;您需要根據我還不明白的原因來製作尺寸(55,30似乎可行)

  5. 如果searchBar.showsCancelButton始終爲YES,那麼這將起作用;如果您希望它在不編輯搜索字符串時消失,則每次出現取消按鈕時都需要找到一個掛鉤來添加疊加層。

  6. 正如你所看到的,這是一些醜陋的修補。用睜大眼睛去做吧。

+0

我希望它不會像這樣:)它的確如你所描述的那樣工作(除了取消按鈕的大小對我而言是55x30)。仍然需要玩弄正確的外觀,但它可能有效,除了這種方法的醜陋之外。非常感謝你的幫助! – 2009-07-29 17:19:16

+0

嗯!我想要做的就是改變Scope Button欄的tintColor。也許類似的東西也會讓我覺得......但它太脆弱了。 Yecch。決定決定。 – 2009-08-31 02:13:21

+0

jandrea - 提出你自己的問題,並指向我 - 我會盡力解釋如何做類似的事情。 – Amagrammer 2009-08-31 15:34:02

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]]; 
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]; 
    } 
} 
} 
17

雖然這可能不是原來的問題正好相應的解決方案仍然是適用於試圖定製的的UISearchBar取消按鈕的更大意義。認爲這將有助於陷入這種情況的其他人。

我的情況是改變取消按鈕的標題,但有一個轉折點,其中我不想在默認情況下顯示取消按鈕,但只希望顯示,當用戶進入搜索模式時(通過點擊裏面搜索文本字段)。在這個瞬間,我想要取消按鈕帶有「完成」標題(「取消」給我的屏幕不同的含義,因此定製)。

儘管如此,這裏是我做了什麼(caelavel的和Arenim的解決方案的組合):

子類的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]; 
} 

奇怪的是,我沒有哈我們有辦法隱藏取消按鈕,因爲它在默認情況下隱藏,當搜索模式退出時。

7

如果要在UISearchBar上配置取消按鈕,應從UISearchBar對象中獲取UIButton對象。下面

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; 
    } 
} 
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]; 
    } 
} 
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 

    } 

} 

對我很好!特別是漸變:)

25

您可以使用UIAppearance來取消按鈕的樣式,而不重複UISearchBar的子視圖,但是the UIButton header does not currently have any methods annotated with 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 
} 
} 
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]; 
18

變化的 '取消' 按鈕標題:

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

斯威夫特相當於:

let cancelButton = UIButton.appearance(whenContainedInInstancesOf: [UISearchBar.self]) 
    cancelButton?.setTitle("cancel".localized, for: .normal) 
0

我有很多UISearchBar項目遍及我的應用程序,所以我編寫了這個類別來添加一個屬性,以便您可以訪問mySearchBar.cancelButton。 (如果你是新來的類別,read more about extending objects with Categories here。)

請記住,你應該只有當取消按鈕可見因爲似乎的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 
20

在iOS 5.0及,您可以使用appearnce代理。

搜索欄之前顯示:

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

0

笨的辦法

for(id cc in [SearchBar subviews]) 
{ 
    if([cc isKindOfClass:[UIButton class]]) 
    { 
     UIButton *btn = (UIButton *)cc; 
     ...... 
     Do whatever you want 
     .......   
    } 
} 
4

我給一個詳細的關於UIAppearance技術回答。首先,你需要明白取消按鈕是一個私人的UINavigationButton:UIButton。一些檢查後,似乎UINavigationButton將這些UIAppearance選擇迴應:

// inherited from UINavigationButton 
@selector(setTintColor:) 
@selector(setBackgroundImage:forState:style:barMetrics:) 
@selector(setBackgroundImage:forState:barMetrics:) 
@selector(setTitleTextAttributes:forState:) 
@selector(setBackgroundVerticalPositionAdjustment:forBarMetrics:) 
@selector(setTitlePositionAdjustment:forBarMetrics:) 
@selector(setBackButtonBackgroundImage:forState:barMetrics:) 
@selector(setBackButtonTitlePositionAdjustment:forBarMetrics:) 
@selector(setBackButtonBackgroundVerticalPositionAdjustment:forBarMetrics:) 

// inherited from UIButton 
@selector(setTitle:forState:) 

巧合的是,那些選擇匹配的UIBarButtonItem一個的。這意味着使用兩個獨立的UIAppearance來處理私有類UINavigationButton。

/* dual appearance technique by Cœur to customize a UINavigationButton */ 
Class barClass = [UISearchBar self]; 

UIBarButtonItem<UIAppearance> *barButtonItemAppearanceInBar = [UIBarButtonItem appearanceWhenContainedIn:barClass, nil]; 
[barButtonItemAppearanceInBar setTintColor:...]; 
[barButtonItemAppearanceInBar setBackgroundImage:... forState:... style:... barMetrics:...]; 
[barButtonItemAppearanceInBar setBackgroundImage:... forState:... barMetrics:...]; 
[barButtonItemAppearanceInBar setTitleTextAttributes:... forState:...]; 
[barButtonItemAppearanceInBar setBackgroundVerticalPositionAdjustment:... forBarMetrics:...]; 
[barButtonItemAppearanceInBar setTitlePositionAdjustment:... forBarMetrics:...]; 
// only for a backButton in an UINavigationBar, not for a cancelButton in an UISearchBar 
//[barButtonItemAppearanceInBar setBackButtonBackgroundImage:... forState:... barMetrics:...]; 
//[barButtonItemAppearanceInBar setBackButtonTitlePositionAdjustment:... forBarMetrics:...]; 
//[barButtonItemAppearanceInBar setBackButtonBackgroundVerticalPositionAdjustment:... forBarMetrics:...]; 

UIButton<UIAppearance> *buttonAppearanceInBar = [UIButton appearanceWhenContainedIn:barClass, nil]; 
// warning: doesn't work for iOS7+ 
[buttonAppearanceInBar setTitle:... forState:...]; 

這將讓你自定義你的取消按鈕,只要你想。

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 
    } 
} 
1

所有我想從這個https://stackoverflow.com/a/37381821/1473144

我不得不做出一些調整,他的回答在我的規格低於去上班感謝@Eliott第一。 請問,OP會更新已接受的答案,因爲它非常過時。

Swift 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) 
     } 
    } 

} 
0
extension UISearchBar { 
var cancelButton : UIButton? { 
    let topView: UIView = self.subviews[0] as UIView 

    if let pvtClass = NSClassFromString("UINavigationButton") { 
     for v in topView.subviews { 
      if v.isKind(of: pvtClass) { 
       return v as? UIButton 
      } 
     } 
    } 

    return nil 
} 
} 
0
UISearchBar *searchBar; 
[searchBar setShowsCancelButton:YES animated:YES]; 

UIButton *cancelButton = 
YES == [searchBar respondsToSelector:NSSelectorFromString(@"cancelButton")] ? 
[searchBar valueForKeyPath:@"_cancelButton"] : nil; 

cancelButton.titleEdgeInsets = UIEdgeInsetsMake(0, -10, 0, 10); 
[cancelButton setTitle:@"New :)" forState:UIControlStateNormal]; 
0

對於iOS 11和夫特4. 創建UISearchController的子類。 替代方法:

override func viewDidLayoutSubviews() { 
     super.viewDidLayoutSubviews() 
     print("layout") 
     if let btn = searchBar.subviews[0].subviews[2] as? UIButton { 
      btn.frame = CGRect(x: 306, y: 20, width: 53, height: 30) 
     } 
}