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, 這樣就會出現下面的情況:
可以看到, 剛進去的時候, 視圖重疊了, 但是激活一次后, 就正常了; 所以, 我們需要處理一下這個問題, 這里有兩種方法來解決:
方法一
修改searchBar的frame,
我在其代理方法打印了, 各個情況下的searchBar的frame:
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 后, 就可以使用 UISegmentedControl的 API來設置相關的屬性了;
- 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 中起作用的是高度, 其他的設置了沒效果;
以上設置的, 效果圖如下:
- 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
使用searchBar的tintColor來設置, 也能改變這個按鈕的文字顏色, 但是底部的選項卡也會跟著變色:
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);
效果是這樣的:
修改光標顏色
修改光標的顏色可以直接設置searchBar 的tintColor屬性, 缺點就是會影響整個搜索框的前景色.
目前, 還沒有找到特別有效的方法來單獨設置光標的顏色, 能想到的就是遍歷其子視圖, 找到輸入框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時的類型, 我們怎么知道是什么類型的呢? 這里給出, searchController的searchBar的視圖層次結構:
這樣, 我們就可以看到各個子控件的類型了.