1. 程式人生 > >如何基於UISearchController深度自定義搜尋UI

如何基於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