[iOS]關(guān)于UISearchBar, 看這個(gè)就夠了

UISearchBar一般我們不單獨(dú)使用他, 在iOS 8之后, 我們更多地是和UISearchController一起使用, 關(guān)于UISearchController的一些使用可參考[iOS]系統(tǒng)UISearchController詳解, 這里主要是關(guān)于UISearchBar的一些設(shè)置, 可以單獨(dú)使用, 也可以對(duì)UISearchController中的searchBar 進(jìn)行設(shè)置.
下面這個(gè)就是UISearchController默認(rèn)的樣子:

默認(rèn)

- barStyle

搜索框樣式

@property(nonatomic)        UIBarStyle              barStyle

下面是修改為黑色

search.searchBar.barStyle = UIBarStyleBlack;
黑色樣式

- delegate

代理, 不用多說, 大家都很熟悉;

@property(nullable,nonatomic,weak) id<UISearchBarDelegate> delegate;

- text & placeholder

這兩個(gè)屬性, 也很容易

// searchBar的文本內(nèi)容
@property(nullable,nonatomic,copy)   NSString               *text;
// 占位文本
@property(nullable,nonatomic,copy)   NSString               *placeholder;

- prompt

提示信息, 是在搜索框的上面可以設(shè)置一行提示文字

@property(nullable,nonatomic,copy)   NSString     *prompt;  

這里我設(shè)置為:

search.searchBar.prompt = @"這是一個(gè)prompt";

效果如下:

提示信息

這里在設(shè)置這個(gè)屬性的時(shí)候需要注意, 因?yàn)槎嗔艘粋€(gè)提示信息, 所以searchBar的高度變化了, 不再是默認(rèn)的44, 但是在剛剛創(chuàng)建的時(shí)候, 其高度還是 44, 這樣就會(huì)出現(xiàn)下面的情況:

可以看到, 剛進(jìn)去的時(shí)候, 視圖重疊了, 但是激活一次后, 就正常了; 所以, 我們需要處理一下這個(gè)問題, 這里有兩種方法來解決:

方法一

修改searchBarframe,
我在其代理方法打印了, 各個(gè)情況下的searchBarframe:

searchBarTextDidBeginEditing >>{{0, 0}, {320, 44}}
textDidChange >>{{0, 20}, {320, 75}}
searchBarTextDidEndEditing >>{{0, 20}, {320, 75}}

可以看出, 其高度變?yōu)?strong>75了, 也就是正常顯示的狀態(tài), 所以, 在開始的時(shí)候, 我們調(diào)整一下即可:

    CGRect rect = search.searchBar.frame;
    rect.size.height = 75;
    search.searchBar.frame = rect;

這樣就能, 正常顯示了;

方法二

直接在設(shè)置prompt 后, 調(diào)用一下sizeToFit, 來更新其 frame, 讓其重新布局子控件去自適應(yīng):

[search.searchBar sizeToFit];

- button

幾個(gè)搜索框的輔助按鈕

// 
@property(nonatomic)        BOOL                    showsBookmarkButton __TVOS_PROHIBITED;   // default is NO
@property(nonatomic)        BOOL                    showsCancelButton __TVOS_PROHIBITED;     // default is NO
@property(nonatomic)        BOOL                    showsSearchResultsButton NS_AVAILABLE_IOS(3_2) __TVOS_PROHIBITED; // default is NO

其點(diǎn)擊事件, 可以從其相應(yīng)的代理方法獲取:

- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar;                     // called when keyboard search button pressed
- (void)searchBarBookmarkButtonClicked:(UISearchBar *)searchBar __TVOS_PROHIBITED; // called when bookmark button pressed
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar __TVOS_PROHIBITED;   // called when cancel button pressed
- (void)searchBarResultsListButtonClicked:(UISearchBar *)searchBar NS_AVAILABLE_IOS(3_2) __TVOS_PROHIBITED; // called when search results button pressed

- tintColor & barTintColor

// 主要是修改了搜索框上所有子控件的顏色
@property(null_resettable, nonatomic,strong) UIColor *tintColor;
// 設(shè)置bar的前景色(背景色), 不要使用backgroundColor, 表現(xiàn)不出來
@property(nullable, nonatomic,strong) UIColor *barTintColor NS_AVAILABLE_IOS(7_0)

例如:

search.searchBar.tintColor = [UIColor redColor];
search.searchBar.barTintColor = [UIColor greenColor];

效果:

效果圖

下面設(shè)置一下backgroundColor, 看看效果:

search.searchBar.backgroundColor = [UIColor orangeColor];

可以看出, 背景色被上面的前景色覆蓋了, 所以沒有表現(xiàn)出來.

- ScopeBar

選項(xiàng)卡

// 選項(xiàng)按鈕標(biāo)題(大于等于2個(gè), 才會(huì)顯示)
@property(nullable, nonatomic,copy) NSArray<NSString *>   *scopeButtonTitles  
// 默認(rèn)選中的選項(xiàng)卡
@property(nonatomic)      NSInteger  selectedScopeButtonIndex  
// 是否顯示選項(xiàng)卡(一般不需設(shè)置)
@property(nonatomic)      BOOL       showsScopeBar 

其點(diǎn)擊事件, 在代理方法中獲取:

- (void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope

這里需要注意, 在設(shè)置了scopeButtonTitles 后, 就不用設(shè)置showsScopeBar 了, 或者將其設(shè)置為NO, 如果為YES, 會(huì)發(fā)生下面的情況:


正常情況應(yīng)該是這樣的:

上面的問題是在剛進(jìn)來的時(shí)候, 就顯示了選項(xiàng)卡, 而且在激活搜索框的時(shí)候, 選項(xiàng)卡不見了, 而是多出來一部分空白. 而正常剛進(jìn)來的時(shí)候是不顯示選項(xiàng)卡的, 搜索框激活時(shí)才顯示, 所以設(shè)置時(shí)不用設(shè)置showsScopeBar;

設(shè)置選項(xiàng)卡的屬性

可以使用下面的方法, 來設(shè)置選項(xiàng)卡文字的屬性( 字體, 顏色, 大小等):

- (void)setScopeBarButtonTitleTextAttributes:(nullable NSDictionary<NSString *, id> *)attributes forState:(UIControlState)state

常用到的鍵為:

 NSForegroundColorAttributeName // 修改文字顏色
NSFontAttributeName // 修改文字字體及大小

更多鍵名可參考
NSAttributedString.h
設(shè)置背景色

可參考下面 backgroundImage & scopeBarBackgroundImage, 使用純色圖片來設(shè)置背景圖, 達(dá)到設(shè)置背景色的目的; 也可以使用下面的方法:

 UIView *backView = [[searchBar.subviews firstObject].subviews firstObject];
    
    UISegmentedControl *segmentedController = nil;
    // 找到 UISegmentedControl
    for (UIView *tmp in backView.subviews) {
        
        if ([tmp isKindOfClass:[UISegmentedControl class]]) {
            
            segmentedController = (UISegmentedControl *)tmp;
            break;
        }
    }
    // 如果存在
    if (segmentedController) {
        
        [segmentedController setTitleTextAttributes:@{NSForegroundColorAttributeName: [UIColor redColor]} forState:UIControlStateNormal];
        [segmentedController setTitleTextAttributes:@{NSForegroundColorAttributeName: [UIColor blackColor]} forState:UIControlStateSelected];

// 設(shè)置中顏色
        segmentedController.tintColor = [UIColor redColor];
    }

找到這個(gè)UISegmentedControl 后, 就可以使用 UISegmentedControlAPI來設(shè)置相關(guān)的屬性了;

- inputAccessoryView

為搜索框的鍵盤添加一個(gè)輔助視圖

@property (nullable, nonatomic, readwrite, strong) UIView *inputAccessoryView;

可以這樣使用:

UILabel *label = [[UILabel alloc]init];
    label.text = @"這是一個(gè)inputAccessoryView";
    label.textAlignment = NSTextAlignmentCenter;
    label.textColor = [UIColor blackColor];
    
    label.frame = CGRectMake(0, 0, 0, 30);
    label.backgroundColor = [UIColor redColor];
    search.searchBar.inputAccessoryView = label;

這里的frame 中起作用的是高度, 其他的設(shè)置了沒效果;

以上設(shè)置的, 效果圖如下:

search.searchBar.inputAccessoryView

- backgroundImage & scopeBarBackgroundImage

背景圖和選項(xiàng)卡的背景圖

// 搜索框的背景圖
@property(nullable, nonatomic,strong) UIImage *backgroundImage 
// 選項(xiàng)卡的背景圖
@property(nullable, nonatomic,strong) UIImage *scopeBarBackgroundImage 

還有幾個(gè)設(shè)置相關(guān)背景圖的方法:

// 設(shè)置tabbar背景圖
- (void)setBackgroundImage:(nullable UIImage *)backgroundImage forBarPosition:(UIBarPosition)barPosition barMetrics:(UIBarMetrics)barMetrics
// 設(shè)置搜索文本框背景圖, state的取值只能是: UIControlStateNormal and UIControlStateDisabled
- (void)setSearchFieldBackgroundImage:(nullable UIImage *)backgroundImage forState:(UIControlState)state 

- (void)setScopeBarButtonBackgroundImage:(nullable UIImage *)backgroundImage forState:(UIControlState)state

修改搜索框默認(rèn)圖標(biāo)

這個(gè)方法可以修改搜索框默認(rèn)的一些圖標(biāo),:

- (void)setImage:(nullable UIImage *)iconImage forSearchBarIcon:(UISearchBarIcon)icon state:(UIControlState)state

修改哪個(gè)圖標(biāo), 是用參數(shù)icon 來指定, 他是一個(gè)枚舉:

typedef NS_ENUM(NSInteger, UISearchBarIcon) {
    UISearchBarIconSearch, // The magnifying glass
    UISearchBarIconClear __TVOS_PROHIBITED, // The circle with an x in it
    UISearchBarIconBookmark __TVOS_PROHIBITED, // The open book icon
    UISearchBarIconResultsList __TVOS_PROHIBITED, // The list lozenge icon
};

如下, 我修改了默認(rèn)的搜索圖標(biāo):

[search.searchBar setImage:[UIImage imageNamed:@"MoreExpressionShops"] forSearchBarIcon:UISearchBarIconSearch state:UIControlStateNormal];

修改默認(rèn)圖標(biāo)偏移量

修改偏移量可使用下面的方法, 參數(shù)就是你要修改的是哪個(gè)圖標(biāo)(搜索, 刪除等):

- (void)setPositionAdjustment:(UIOffset)adjustment forSearchBarIcon:(UISearchBarIcon)icon 

參數(shù)是一個(gè)枚舉:

typedef NS_ENUM(NSInteger, UISearchBarIcon) {
    UISearchBarIconSearch, // 搜索圖標(biāo)
    UISearchBarIconClear // 刪除圖標(biāo)
    UISearchBarIconBookmark // 閱讀樣式圖標(biāo)
    UISearchBarIconResultsList // 詳細(xì)結(jié)果展示圖標(biāo)
};

- 修改右側(cè)取消按鈕

搜索框右側(cè)的取消按鈕, 默認(rèn)是藍(lán)色的英文cancel, 大多數(shù)情況下我們都要修改這個(gè), 下面我來介紹三種修改的方法:

方法一 : 找到這個(gè)button來修改,

由于搜索框剛創(chuàng)建的時(shí)候, 沒有顯示這個(gè)取消按鈕, 所以實(shí)際上, 這個(gè)按鈕不在searchBar 的子視圖中(懶加載), 所以, 我們可以在其代理方法中添加如下代碼:

// 由于其子控件是懶加載模式, 所以找之前先將其顯示
[searchBar setShowsCancelButton:YES animated:YES];
    // 這個(gè)方法來遍歷其子視圖, 找到cancel按鈕
    for (UIView *subview in searchBar.subviews) {
        
        for (UIView *tempView in subview.subviews) {
            // 找到cancelButton
            if ([tempView isKindOfClass:NSClassFromString(@"UINavigationButton")]) {
                // 在這里轉(zhuǎn)化為UIButton, 設(shè)置其屬性
                UIButton *btn = (UIButton*)tempView;
                [btn setTitle:@"取消" forState:UIControlStateNormal];
            }
        }
    }

效果如下:

這個(gè)方法可以設(shè)置, 按鈕標(biāo)題及其屬性(顏色, 字體等)
注意, 這里設(shè)置文字顏色的時(shí)候, 如果使用按鈕的方式設(shè)置, 會(huì)有一些問題, 第一次激活搜索框的時(shí)候, 他的顏色并沒有改變, 第二次之后才會(huì)改變:

// 這樣首次激活搜索框 ,顏色沒有改變
[btn setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
方式二 : 設(shè)置tintColor

使用searchBartintColor來設(shè)置, 也能改變這個(gè)按鈕的文字顏色, 但是底部的選項(xiàng)卡也會(huì)跟著變色:

search.searchBar.tintColor = [UIColor redColor];

因?yàn)? 這樣雖然改變了按鈕標(biāo)題顏色, 但是其他的控件也受到了影響, 所以, 有時(shí)候也不是我們想要的.

方式三 : 最優(yōu)解決

下面介紹一種, 直接修改按鈕標(biāo)題顏色, 而不影響其他的控件( 例如: 選項(xiàng)卡 ); 在初始化UISearchController的時(shí)候, 添加如下代碼即可:

// 修改按鈕標(biāo)題文字屬性( 顏色, 大小, 字體)
[[UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]] setTitleTextAttributes:@{NSForegroundColorAttributeName: [UIColor redColor], NSFontAttributeName: [UIFont systemFontOfSize:16]} forState:UIControlStateNormal];
  
 // 修改標(biāo)題文字
 [[UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]] setTitle:@"souSuo"];

這樣也能達(dá)到修改按鈕文字及其顏色的效果, 但是不會(huì)影響其他的控件.

設(shè)置光標(biāo)

設(shè)置光標(biāo)偏移量

searchBar 有兩個(gè)UIOffset類型的屬性:

// 搜索框光標(biāo)偏移量
@property(nonatomic) UIOffset searchFieldBackgroundPositionAdjustment 
// 搜索框在searchBar內(nèi)的位置偏移量
@property(nonatomic) UIOffset searchTextPositionAdjustment

例如, 如下設(shè)置后:

search.searchBar.searchTextPositionAdjustment = UIOffsetMake(20, 0);
search.searchBar.searchFieldBackgroundPositionAdjustment = UIOffsetMake(20, 0);

效果是這樣的:

搜索框的偏移量
光標(biāo)偏移
修改光標(biāo)顏色

修改光標(biāo)的顏色可以直接設(shè)置searchBartintColor屬性, 缺點(diǎn)就是會(huì)影響整個(gè)搜索框的前景色.
目前, 還沒有找到特別有效的方法來單獨(dú)設(shè)置光標(biāo)的顏色, 能想到的就是遍歷其子視圖, 找到輸入框UITextField, 方法類似上面找cancelButton :

UITextField *textField = nil;
    
    for (UIView *tmp in backView.subviews) {
        
        if ([tmp isKindOfClass:NSClassFromString(@"UISearchBarTextField")]) {
            
            textField = (UITextField *)tmp;
            break;
        }
    }
    // 找到這個(gè)textField, 就可以按UITextField類來設(shè)置了
    if (textField) {
        
        textField.tintColor = [UIColor orangeColor];
    }

這樣就修改為了, 橘黃色:

以上在遍歷子控件, 找自己需要的控件的時(shí)候, 判斷class時(shí)的類型, 我們?cè)趺粗朗鞘裁搭愋偷哪? 這里給出, searchControllersearchBar的視圖層次結(jié)構(gòu):

子視圖層次關(guān)系
可視化視圖

這樣, 我們就可以看到各個(gè)子控件的類型了.

(完)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,684評(píng)論 4 61
  • ¥開啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個(gè)線程,因...
    小菜c閱讀 7,388評(píng)論 0 17
  • import "AppDelegate.h" // 宏定義顏色 define COLORRGB(r,g,b,a) ...
    ThEAll閱讀 439評(píng)論 0 0
  • 不知你是否會(huì)有這種感覺 白天各種正能量,夜幕來臨回到家不開燈,葛優(yōu)癱在沙發(fā)上,感覺好累,懷疑現(xiàn)在的生活與選擇。感覺...
    L_Yao閱讀 356評(píng)論 0 1

友情鏈接更多精彩內(nèi)容