如何基於UISearchController深度自定義搜尋UI
一、搜尋功能我相信很多app都用得上,iOS系統提供做搜尋的類有那幾種呢?
1.UISearchBar,這個相信大多數開發者都用過,這個只是提供搜尋框,其實就是跟一個UITextField沒啥區別,只是在textfield封裝了多點內容。
2.UISearchDisplayController,這個玩意是iOS8之前,專門用來做搜尋功能,對的,它就是一個控制器,他為你提供蘋果那種搜尋風格的轉場動畫以及搜尋檢視顯示邏輯等,但是使用起來相對複雜。所以在iOS8這個類已經被拋棄了,而引申一個新的搜尋類,就是以下要介紹的UISearchController。
3.UISearchController,這個類其實跟UISearchDisplayController功能差不多,只是蘋果對其再進行了高階封裝,從而使用起來更加簡單了。
二、其實自己在搞UISearchController之前,我已經到網上找過一下相關的資料,發現網上寫的都是千遍一律,教你怎麼用,就我個人覺得,難的是你要在它基礎上去對改它的UI,這就要你對它的檢視層次結構要很清楚了,那我們下面來開始幹活吧。
我們首先看一下系統自帶的搜尋框是怎樣的。
normal狀態下的searchBar
這個是正常狀態下的搜尋框,但是那灰色的背景真是醜出翔了,試問有那個產品設計能接受這個樣式的搜尋框?我們再看下編輯狀態下的吧。
編輯無文字狀態下
從normal到edit狀態會有一個轉場動畫,雖然介面還是很醜,而我們需要的正式這個動畫,如果我們完全自定義的話還需要做這個動畫就未免有點複雜了。
編輯有文字狀態
當你輸入文字是,你發現它那個蒙版消失了,而展現新的檢視,沒錯,那個就是你自己的搜尋結果控制器檢視了,下面再詳細介紹。
三、看了上面幾張圖,我們大概知道UISearchController的互動大概怎樣。
那我們再進去標頭檔案看一下他的一些屬性和方法吧
它的指定初始化方法就是
```
- (instancetype)initWithSearchResultsController:(nullableUIViewController*)searchResultsController;
```
所以你能定製屬於你自己的搜尋結果view。當你傳nil的時候,預設是當前view就是搜尋結果view。
UISearchResultsUpdating -> 搜尋結果更新回撥的協議,實現裡面的方法就能更新搜尋邏輯了,這裡不詳細說,網上一大堆教這個的。
再說下比較常用的屬性吧
dimsBackgroundDuringPresentation -> 是否顯示灰色透明的蒙版,預設YES
hidesNavigationBarDuringPresentation -> 是否隱藏導航條,這個一般不需要管,都是隱藏的
searchResultsController -> 就是你初始化傳進去的搜尋結果VC
searchBar -> 它內部會建立一個搜尋框給你。
UISearchController就這幾個屬性了。我們看下先怎麼去用?
```
UISearchController *searchController= [[UISearchController alloc] init];
self.tableView.tableHeaderView=searchController.searchBar;
searchController.searchResultsUpdater=self;
searchController.searchBar.delegate=self;
[email protected]"搜尋"; // placeholder
[searchController.searchBar setSearchFieldBackgroundImage:[UIImagehcq_imageNamed:@"business_search_bg"] forState:UIControlStateNormal]; // 設定搜尋框內部textField的背景圖
[self.searchBar setBackgroundImage:@""] // 設定搜尋框背景圖,要跟上面的區分哦,兩者不一樣
[searchController.searchBarsetImage:[UIImagehcq_imageNamed:@"business_search_icon"] forSearchBarIcon:UISearchBarIconSearchstate:UIControlStateNormal];// 設定搜尋框內放大鏡圖片
searchController.searchBar.tintColor=KC_RGB_COLOR(225,225,225);// 設定搜尋框內按鈕文字顏色,以及搜尋游標顏色。
searchController.searchBar.barTintColor=HCQ_VIEW_BACKGROUND_COLOR;// 設定搜尋框背景顏色
// Get the instance of the UITextField of the search bar
// 用KVC修改placeholder文字顏色
UITextField*searchField = [self.searchBarvalueForKey:@"_searchField"]; // 先取出textfield
// Change the search bar placeholder text color
[searchFieldsetValue:self.searchBar.tintColorforKeyPath:@"_placeholderLabel.textColor"]; // 然後setValueForKey,搞定
[searchController.searchBarsetValue:@"完成"forKey:@"_cancelButtonText"]; // 設定搜尋框那個取消按鈕文字
// 如果你不想要搜尋框的背景或者希望背景透明,你加上這句程式碼吧
[[[searchController.searchBar.subviews.firstObject subviews] firstObject] removeFromSuperview];// 直接把背景imageView幹掉。在iOS8,9是沒問題的,7沒測試過。
```
到這裡,UISearchBar的UI就自定義完畢,想了解UISearchBar層次結構的話,可以用Xcode執行後開啟那個檢視層次結構看一下就一目瞭然。
四、下面介紹怎樣定義編輯無文字狀態下的搜尋UI,例如微信點選搜尋框後會出現3個按鈕《朋友圈,文章,公眾號》。
要定義這些UI,那麼我們需要自定義一個自己的searchController了,建立一個類MySearchController繼承UISearchController。
首先我們重寫初始化方法
```
- (instancetype)initWithSearchResultsController:(UIViewController*)searchResultsController
{
UINavigationController*nav = [[UINavigationController alloc] initWithRootViewController:[MyResultViewController new]];
if(self= [super initWithSearchResultsController:nav]) {
[selfsetup];
}
returnself;
}
- (instancetype)init
{
UINavigationController*nav = [[UINavigationController alloc]initWithRootViewController:[MyResultViewController new]];
if(self= [super initWithSearchResultsController:nav]) {
[selfsetup];
}
returnself;
}
// 重寫init方法,好讓外部怎麼建立都是我們自己的搜尋結果控制器。外部使用不需要關心太多
// 可以把剛才自定義SearchBarUI程式碼放到內部了。
- (void)setup
{
[email protected]"搜尋商家";
[self.searchBarsetSearchFieldBackgroundImage:[UIImagehcq_imageNamed:@"business_search_bg"]forState:UIControlStateNormal];
[self.searchBarsetImage:[UIImagehcq_imageNamed:@"business_search_icon"]forSearchBarIcon:UISearchBarIconSearchstate:UIControlStateNormal];
self.searchBar.tintColor=KC_RGB_COLOR(225,225,225);
self.searchBar.barTintColor=HCQ_VIEW_BACKGROUND_COLOR;
// Get the instance of the UITextField of the search bar
UITextField*searchField = [self.searchBarvalueForKey:@"_searchField"];
// Change the search bar placeholder text color
[searchFieldsetValue:self.searchBar.tintColorforKeyPath:@"_placeholderLabel.textColor"];
[[[self.searchBar.subviews.firstObjectsubviews]firstObject]removeFromSuperview];
[self.searchBarsetValue:@"完成"forKey:@"_cancelButtonText"];
}
```
然後來到viewDidLoad方法,新增我們需要定義的UI。
例如我想加一個switch到中間
```
UISwitch*st = [UISwitch new];
[self.view addSubview:st];
st.center = self.view.center;
```
一般我們會這樣寫,執行後點擊搜尋框進入編輯狀態,發現開關出來了,但是當你輸入文字的時候,開關還在顯示還能點選。這就神奇了。會不會是檢視層級不對呢?沒錯,就是檢視層級問題,SearchController.view內部還有一個containerView(其實就是那個蒙版),而SearchController是把搜尋結果控制器view新增到containerView上,所以開關跟containerView是同一層次,而且在containerView之上,所以不會消失。也可以開啟層次結果圖看一下。
我們可以新增一個屬性
```
@property(nonatomic,weak)UIView*containerView;
```
重寫get方法
```
- (UIView*)containerView
{
if(!_containerView) {
_containerView=self.view.subviews.firstObject;
_containerView.backgroundColor=HCQ_VIEW_BACKGROUND_COLOR;
}
return_containerView;
}
```
然後在viewdidload中新增開關的程式碼改一下
```
[self.containerView addSubview:st];
```
繼續執行,發現還是不行,還是不會消失,為什麼呢?我們知道view的subview有先後順序,後新增的越在上面,因為你的搜尋結果view先新增到containerView,開關是後面加的,固然開關還是能看到。所以,你不能直接add,正確姿勢是插入insert
```
[self.containerView insertSubview:st atIndex:0];
```
這樣就沒問題了。
再補充一點,如果你想改containerView的frame,可以在這個方法修改
```
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
}
```
如果想做一些轉場過度動畫,那麼重寫viewWillAppear、viewWillDisappear在裡邊做吧
例如
```
- (void)viewWillAppear:(BOOL)animated
{
[superviewWillAppear:animated];
/**
*此處隱藏tabbar,否則會有bug
*/
// 隱藏tabbar,不隱藏發現有檢視錯亂問題,會黑屏,估計是系統內部問題
[UIViewanimateWithDuration:KCDefaultAnimationDurationanimations:^{
UITabBarController*tbc = [UIApplication sharedApplication].keyWindow.rootViewController
tbc.tabBar.transform=CGAffineTransformMakeTranslation(0,49);
}];
// 修改textfield背景圖
[self.searchBar setSearchFieldBackgroundImage:[UIImagehcq_imageNamed:@"business_search_bg_highlighted"] forState:UIControlStateNormal];
}
- (void)viewWillDisappear:(BOOL)animated
{
[superviewWillDisappear:animated];
// 這裡再改回來
[UIView animateWithDuration:KCDefaultAnimationDuration animations:^{
UITabBarController*tbc = [UIApplication sharedApplication].keyWindow.rootViewController
tbc.tabBar.transform=CGAffineTransformIdentity;
}];
[self.searchBar setSearchFieldBackgroundImage:[UIImagehcq_imageNamed:@"business_search_bg"]forState:UIControlStateNormal];
}
```
五、結語
基本上按照上面所說的就能自定義基於系統的,屬於自己風格的搜尋框了。用系統提供的轉場動畫還是挺好看的。定製起來也比較簡單,有這個需求的可以參考下我寫的這編文章。
相關推薦
如何基於UISearchController深度自定義搜尋UI
一、搜尋功能我相信很多app都用得上,iOS系統提供做搜尋的類有那幾種呢? 1.UISearchBar,這個相信大多數開發者都用過,這個只是提供搜尋框,其實就是跟一個UITextField沒啥區別,只是在textfield封裝了多點內容。 2.UISearchDisp
下載基於LigerUI+JBPM5自定義表單+Node.js的J2EE大型金融項目《財務預算系統》開發全程實錄
財務預算系統 大型金融項目 jbpm5自定義表單 基於LigerUI+JBPM5自定義表單+Node.js的J2EE大型金融項目《財務預算系統》開發全程實錄地址:http://pan.baidu.com/s/1eRBSHGY 密碼:q8x8課程分為三季:第一季:基礎篇,主要內容包括:基礎設置,主要
自定義element-ui主題,修改樣式
改版 引入 一個 css template div 應用 根據 得到 項目需求 之前項目中引用的select選框有bug,所以需要改動,考慮到還有許多需求,果斷將餓了麽組件全移過來 安裝element-ui2.0.1版本 安裝完之後,我就將element-ui的組件應用上,
基於JQ的自定義彈窗組件
spl middle ipad extend 操作 init amp -- after <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF
Java類載入器( CLassLoader ) 死磕7: 基於加密的自定義網路載入器 本小節目錄
【正文】Java類載入器( CLassLoader ) 死磕7: 基於加密的自定義網路載入器 本小節目錄 7.1. 加密傳輸Server端的原始碼 7.2. 加密傳輸Client端的原始碼 7.3. 使用亦或實現簡單加密和解密演算法 7. 網路加密SafeClassLoader的原
Android自定義View——自定義搜尋框(SearchView) 非常實用的控制元件
好多東西寫起來太麻煩了,而且我在最開始用的也不是自己寫的,所以找了一個非常棒的測試了一下. 轉載的 在 Android開發中,當系統資料項比較多時,常常會在app新增搜尋功能,方便使用者能快速獲得需要的資料。搜尋欄對於我們並不陌生,在許多app都能見到它,比如豌
JEECG V3 0 版本(jbpm5 工作流自定義+WEB UI快速開發庫+程式碼生成器) spring mvc +hi
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
基於springboot通過自定義註解和AOP實現許可權驗證
這篇文章主要介紹自定義註解配合AOP的使用來完成一個簡單的許可權驗證的功能。 一、移入依賴 <parent> <groupId>org.springframework.boot</groupId> <artifactId>sprin
Qt-自定義搜尋框
1.建立輸入框 QLineEdit* text = new QLineEdit(this); text->setGeometry(50,80,200,25); text->setObjectName(QString("text")); 2.建
今晚8點直播 | 詳解基於百度自定義模板的OCR結果結構化處理技術
隨著行業的發展和技術的成熟,文字識別(OCR)目前已經應用到了多個行業中,比如物流行業快遞包裹的分揀,金融行業的支票單據識別輸入,交通領域中的車牌識別,以及日常生活中的卡證、票據識別等等。OCR(文字識別)技術是目前常用的一種AI能力。但一般OCR的識別結果是一種按行輸出的半結構化輸出。
DataTable 自定義搜尋條件 _ 自定義查詢引數
var table =$('#orderInfoTable').DataTable({ processing: true, //載入 serverSide: true, //後臺分頁 searching: false, //索引 ajax : { url : reque
android 自定義搜尋框
1.編寫佈局 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+
織夢繫統中“自定義搜尋模型不存在”的解決方法
搜尋了一下關於自定義搜尋模型不存在這個問題 重新整理下:1.mysql 資料庫在5.0版本以上2. 自定義搜尋表dede_advancedsearch 這個表的結構把256 改成255 3.還有就是搜
echarts之基於geojson的自定義地圖
應用場景:需要在平面圖或者特殊地理區域上展示資料,比如 geojson作為echarts的地圖資料來源,能實現簡單平面圖(如果是立體圖就需要研究svg)上的資料互動。優點:技術低,學習起來沒難度;缺點:耗時耗力,複雜的平面圖有難度。 實現步驟: 1、在 http:/
Dede自定義搜尋結果頁顯示自定義欄位
1。修改puls/advancedsearch.php檔案,找到 $query = "select arctype.* FROM $addontable addon left join dede2_arctype arctype on arctype.id=a
Android基於wheelView的自定義日期選擇器(可拓展樣式)
基於wheelView的自定義日期選擇器 專案要求效果圖: 要求 “6月20 星期五” 這一項作為一個整體可以滑動,”7時”、”48分”分別作為一個滑動整體。 系統自帶的DatePicker、TimePicker大家都知道,只有這種效果:
基於SRP建立自定義渲染管線
這篇文章為翻譯文章,為避免翻譯的文章不在原創列表列裡,設定為原創,特此宣告 原文地址: https://catlikecoding.com/unity/tutorials/scriptable-render-pipeline/custom-pipeline/ 建立一
為自己的站點新增Google自定義搜尋
這裡面很多都不需要設定,呼叫的時候一般都是設定在程式碼中。點選獲取程式碼,可以檢視你的程式碼,其實是一段js程式碼,格式如下:<script> (function() { var cx = '000737368xxxxxxxxxxx:yyyyyyyyy'; var gcse = do
基於jQuery的自定義Video視訊播放元件(相容IE6~8)
之前用過video.js外掛寫過視訊元件,但是自己一般僅僅是播放個視訊,裡面有好多功能用不到,改著不太方便,於是就自己用jQuery封裝了一個外掛,控制器之類的樣式是可以自定義的,支援中英文切換,廢話不多說,下面上圖。 高版本瀏覽器video樣式 注:如果遇到進度
【稀飯】react native 實戰系列教程之自定義原生UI元件
上一節,講了關於RN的自定義原生模組,本節是關於自定義原生UI元件,學習完本節,你將瞭解到原生UI元件的開發流程,以及js如何向native傳送命令和native如何向js傳送事件。 原生UI元件之VideoView視訊播放器開發 React Nativ