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)的樣子:
- barStyle
搜索框樣式
@property(nonatomic) UIBarStyle barStyle
下面是修改為黑色
search.searchBar.barStyle = UIBarStyleBlack;
- delegate
代理, 不用多說(shuō), 大家都很熟悉;
@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è)問題, 這里有兩種方法來(lái)解決:
方法一
修改searchBar的frame,
我在其代理方法打印了, 各個(gè)情況下的searchBar的frame:
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, 來(lái)更新其 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)不出來(lái)
@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)出來(lái).
- 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)來(lái)的時(shí)候, 就顯示了選項(xiàng)卡, 而且在激活搜索框的時(shí)候, 選項(xiàng)卡不見了, 而是多出來(lái)一部分空白. 而正常剛進(jìn)來(lái)的時(shí)候是不顯示選項(xiàng)卡的, 搜索框激活時(shí)才顯示, 所以設(shè)置時(shí)不用設(shè)置showsScopeBar;
設(shè)置選項(xiàng)卡的屬性
可以使用下面的方法, 來(lái)設(shè)置選項(xiàng)卡文字的屬性( 字體, 顏色, 大小等):
- (void)setScopeBarButtonTitleTextAttributes:(nullable NSDictionary<NSString *, id> *)attributes forState:(UIControlState)state
常用到的鍵為:
NSForegroundColorAttributeName // 修改文字顏色
NSFontAttributeName // 修改文字字體及大小
更多鍵名可參考
NSAttributedString.h
設(shè)置背景色
可參考下面 backgroundImage & scopeBarBackgroundImage, 使用純色圖片來(lái)設(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 后, 就可以使用 UISegmentedControl的 API來(lái)設(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è)置的, 效果圖如下:
- 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 來(lái)指定, 他是一個(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è), 下面我來(lái)介紹三種修改的方法:
方法一 : 找到這個(gè)button來(lái)修改,
由于搜索框剛創(chuàng)建的時(shí)候, 沒有顯示這個(gè)取消按鈕, 所以實(shí)際上, 這個(gè)按鈕不在searchBar 的子視圖中(懶加載), 所以, 我們可以在其代理方法中添加如下代碼:
// 由于其子控件是懶加載模式, 所以找之前先將其顯示
[searchBar setShowsCancelButton:YES animated:YES];
// 這個(gè)方法來(lái)遍歷其子視圖, 找到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
使用searchBar的tintColor來(lái)設(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)的顏色可以直接設(shè)置searchBar 的tintColor屬性, 缺點(diǎn)就是會(huì)影響整個(gè)搜索框的前景色.
目前, 還沒有找到特別有效的方法來(lái)單獨(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類來(lái)設(shè)置了
if (textField) {
textField.tintColor = [UIColor orangeColor];
}
這樣就修改為了, 橘黃色:
附
以上在遍歷子控件, 找自己需要的控件的時(shí)候, 判斷class時(shí)的類型, 我們?cè)趺粗朗鞘裁搭愋偷哪? 這里給出, searchController的searchBar的視圖層次結(jié)構(gòu):
這樣, 我們就可以看到各個(gè)子控件的類型了.