[iOS]關于UISearchBar, 看這個就夠了

UISearchBar一般我們不單獨使用他, 在iOS 8之后, 我們更多地是和UISearchController一起使用, 關于UISearchController的一些使用可參考[iOS]系統UISearchController詳解, 這里主要是關于UISearchBar的一些設置, 可以單獨使用, 也可以對UISearchController中的searchBar 進行設置.
下面這個就是UISearchController默認的樣子:

默認

- barStyle

搜索框樣式

@property(nonatomic)        UIBarStyle              barStyle

下面是修改為黑色

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

- delegate

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

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

- text & placeholder

這兩個屬性, 也很容易

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

- prompt

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

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

這里我設置為:

search.searchBar.prompt = @"這是一個prompt";

效果如下:

提示信息

這里在設置這個屬性的時候需要注意, 因為多了一個提示信息, 所以searchBar的高度變化了, 不再是默認的44, 但是在剛剛創建的時候, 其高度還是 44, 這樣就會出現下面的情況:

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

方法一

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

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

可以看出, 其高度變為75了, 也就是正常顯示的狀態, 所以, 在開始的時候, 我們調整一下即可:

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

這樣就能, 正常顯示了;

方法二

直接在設置prompt 后, 調用一下sizeToFit, 來更新其 frame, 讓其重新布局子控件去自適應:

[search.searchBar sizeToFit];

- button

幾個搜索框的輔助按鈕

// 
@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

其點擊事件, 可以從其相應的代理方法獲取:

- (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;
// 設置bar的前景色(背景色), 不要使用backgroundColor, 表現不出來
@property(nullable, nonatomic,strong) UIColor *barTintColor NS_AVAILABLE_IOS(7_0)

例如:

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

效果:

效果圖

下面設置一下backgroundColor, 看看效果:

search.searchBar.backgroundColor = [UIColor orangeColor];

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

- ScopeBar

選項卡

// 選項按鈕標題(大于等于2個, 才會顯示)
@property(nullable, nonatomic,copy) NSArray<NSString *>   *scopeButtonTitles  
// 默認選中的選項卡
@property(nonatomic)      NSInteger  selectedScopeButtonIndex  
// 是否顯示選項卡(一般不需設置)
@property(nonatomic)      BOOL       showsScopeBar 

其點擊事件, 在代理方法中獲取:

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

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


正常情況應該是這樣的:

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

設置選項卡的屬性

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

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

常用到的鍵為:

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

更多鍵名可參考
NSAttributedString.h
設置背景色

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

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

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

找到這個UISegmentedControl 后, 就可以使用 UISegmentedControlAPI來設置相關的屬性了;

- inputAccessoryView

為搜索框的鍵盤添加一個輔助視圖

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

可以這樣使用:

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

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

以上設置的, 效果圖如下:

search.searchBar.inputAccessoryView

- backgroundImage & scopeBarBackgroundImage

背景圖和選項卡的背景圖

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

還有幾個設置相關背景圖的方法:

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

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

修改搜索框默認圖標

這個方法可以修改搜索框默認的一些圖標,:

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

修改哪個圖標, 是用參數icon 來指定, 他是一個枚舉:

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

如下, 我修改了默認的搜索圖標:

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

修改默認圖標偏移量

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

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

參數是一個枚舉:

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

- 修改右側取消按鈕

搜索框右側的取消按鈕, 默認是藍色的英文cancel, 大多數情況下我們都要修改這個, 下面我來介紹三種修改的方法:

方法一 : 找到這個button來修改,

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

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

效果如下:

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

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

使用searchBartintColor來設置, 也能改變這個按鈕的文字顏色, 但是底部的選項卡也會跟著變色:

search.searchBar.tintColor = [UIColor redColor];

因為, 這樣雖然改變了按鈕標題顏色, 但是其他的控件也受到了影響, 所以, 有時候也不是我們想要的.

方式三 : 最優解決

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

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

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

設置光標

設置光標偏移量

searchBar 有兩個UIOffset類型的屬性:

// 搜索框光標偏移量
@property(nonatomic) UIOffset searchFieldBackgroundPositionAdjustment 
// 搜索框在searchBar內的位置偏移量
@property(nonatomic) UIOffset searchTextPositionAdjustment

例如, 如下設置后:

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

效果是這樣的:

搜索框的偏移量
光標偏移
修改光標顏色

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

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

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

以上在遍歷子控件, 找自己需要的控件的時候, 判斷class時的類型, 我們怎么知道是什么類型的呢? 這里給出, searchControllersearchBar的視圖層次結構:

子視圖層次關系
可視化視圖

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

(完)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,443評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,530評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,407評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,981評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,759評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,204評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,263評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,415評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,955評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,650評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,892評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,675評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,967評論 2 374

推薦閱讀更多精彩內容

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