自定義UISearchBar外觀

最近,在項目過程中遇到要自定義SearchBar的外觀,雖然自己覺得用系統(tǒng)默認的外觀就行了,不過UI設(shè)計師要求不用系統(tǒng)的默認樣式,要跟app主題保持一致。

圖1:設(shè)計效果圖

從上圖可以看出,我們要做的UISearchBar要有圓角,邊框顏色,取消按鈕顏色,背景透明等等。

開始以為可能要自己寫一個自定義的UISearchBar控件了,后面研究了一番,發(fā)現(xiàn)可以設(shè)定系統(tǒng)UISearchBar屬性來更改,便把經(jīng)驗記錄下來跟大家分享一下。

首先,我們看下系統(tǒng)默認的SearchBar的樣式,離我們的目標樣式確實相差很大, 后面我會一步一步詳細說明做成我們的目標樣式。

圖2:UISearchBar默認樣式

1. 設(shè)置背景色

我以白色的背景色為例,下面看看代碼:

//1. 設(shè)置背景顏色
    //設(shè)置背景圖是為了去掉上下黑線
    self.customSearchBar.backgroundImage = [[UIImage alloc] init];
    // 設(shè)置SearchBar的顏色主題為白色
    self.customSearchBar.barTintColor = [UIColor whiteColor];
圖3:設(shè)置SearchBar背景色為白色

2. 設(shè)置邊框顏色和圓角

//2. 設(shè)置圓角和邊框顏色
    UITextField *searchField = [self.customSearchBar valueForKey:@"searchField"];
    if (searchField) {
        [searchField setBackgroundColor:[UIColor whiteColor]];
        searchField.layer.cornerRadius = 14.0f;
        searchField.layer.borderColor = [UIColor colorWithRed:247/255.0 green:75/255.0 blue:31/255.0 alpha:1].CGColor;
        searchField.layer.borderWidth = 1;
        searchField.layer.masksToBounds = YES;
    }

這段代碼有個特別的地方就是通過KVC獲得到UISearchBar的私有變量
searchField(類型為UITextField),設(shè)置SearchBar的邊框顏色和圓角實際上也就變成了設(shè)置searchField的邊框顏色和圓角,你可以試試直接設(shè)置SearchBar.layer.borderColor和cornerRadius,會發(fā)現(xiàn)這樣做是有問題的。

圖4:設(shè)置邊框顏色和圓角

嗯,離預期效果越來越近了!

3. 設(shè)置按鈕(取消按鈕)的文字和文字顏色

//3. 設(shè)置按鈕文字和顏色
    [self.customSearchBar fm_setCancelButtonTitle:@"取消"];
    self.customSearchBar.tintColor = [UIColor colorWithRed:86/255.0 green:179/255.0 blue:11/255.0 alpha:1];
    //修正光標顏色
    [searchField setTintColor:[UIColor blackColor]];

//其中fm_setCancelButtonTitle是我寫的UISearchBar一個分類的方法
- (void)fm_setCancelButtonTitle:(NSString *)title {
    if (IS_IOS9) {
        [[UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]] setTitle:title];
    }else {
        [[UIBarButtonItem appearanceWhenContainedIn:[UISearchBar class], nil] setTitle:title];
    }
}
圖5:設(shè)置按鈕文字和顏色

需要特別注意的是設(shè)置searchBar的tintColor會使輸入框的光標顏色改變,可以通過設(shè)置searchField的tintColor來修正。

4. 設(shè)置輸入框的文字顏色和字體

//4. 設(shè)置輸入框文字顏色和字體
    [self.customSearchBar fm_setTextColor:[UIColor blackColor]];
    [self.customSearchBar fm_setTextFont:[UIFont systemFontOfSize:14]];

//下面兩個方法是UISearchBar分類代碼
- (void)fm_setTextColor:(UIColor *)textColor {
    if (IS_IOS9) {
        [UITextField appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]].textColor = textColor;
    }else {
        [[UITextField appearanceWhenContainedIn:[UISearchBar class], nil] setTextColor:textColor];
    }
}

- (void)fm_setCancelButtonTitle:(NSString *)title {
    if (IS_IOS9) {
        [[UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]] setTitle:title];
    }else {
        [[UIBarButtonItem appearanceWhenContainedIn:[UISearchBar class], nil] setTitle:title];
    }
}
圖6:最終對比效果圖

5. 如何設(shè)置搜索圖標

下面評論中有簡友問我怎么更改默認的搜索圖標,我查了下UISearchBar的API,發(fā)現(xiàn)有方法可以更改的。

//5. 設(shè)置搜索Icon
    [self.customSearchBar setImage:[UIImage imageNamed:@"Search_Icon"]
                  forSearchBarIcon:UISearchBarIconSearch
                             state:UIControlStateNormal];

為了跟系統(tǒng)默認Icon的有個明顯的對比,我特殊找了張綠色的搜索Icon,效果見下圖:

設(shè)置搜索Icon.png

Tips: 還可以設(shè)置其他的Icon(如清除按鈕圖標),也是用上面的方法,具體要設(shè)置什么,可以去看看UISearchBarIcon這個枚舉。

2016-10-20新增

6.實現(xiàn)類似微信的搜索框

圖8:提問.png

這里有位簡友問到怎么實現(xiàn)類似微信的搜索框,下面我將詳細說說我的思路。

首先,要告訴大家的是 UISearchBar 是一個由多個控件組合成的比較復雜的控件。用Reveal查看 UISearchBar 組成如下 :

圖9:UISearchBar組成圖.png

從上圖可以看出UISearch的組成結(jié)構(gòu),下面我總結(jié)了一張思維導圖,更加的清晰直觀:

圖10:UISearchBar思維導圖.png

UISearchBar 的主要部分是 UISearchBarTextFieldUISearchBarTextField 又包含好幾個subView,其中那個 UIButton 指的是清除按鈕(輸入文字時會出現(xiàn))。

好了,上面說了一堆,其實我主要是想表達:既然 UISearchBar 是由這么多個子控件組成,我再往里面加一個按鈕又何妨?

最終解決思路就是這樣了:在 UISearchBarTextField 添加一個 UIButton,我暫且將它叫做 voiceButton,然后 voiceButton 設(shè)置好自動布局以及點擊事件處理(點擊按鈕后,顯示錄音界面...),最后還要監(jiān)控文本的變化,有輸入了文本時,voiceButton 隱藏,沒有文本時, 顯示 voiceButton

所有代碼如下:

//6. 實現(xiàn)類似微信的搜索框
    UIButton *voiceButton = [UIButton buttonWithType:UIButtonTypeCustom];
    [voiceButton setImage:[UIImage imageNamed:@"Voice_button_icon"] forState:UIControlStateNormal];
    [voiceButton addTarget:self action:@selector(tapVoiceButton:) forControlEvents:UIControlEventTouchUpInside];
    [searchField addSubview:voiceButton];
    self.voiceButton = voiceButton;
    
    //Autolayout
    voiceButton.translatesAutoresizingMaskIntoConstraints = NO;
    NSDictionary *views = NSDictionaryOfVariableBindings(voiceButton);
    //設(shè)置水平方向約束
    [searchField addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"[voiceButton(21)]-|" options:NSLayoutFormatAlignAllRight | NSLayoutFormatAlignAllLeft metrics:nil views:views]];
    //設(shè)置高度約束
    [searchField addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[voiceButton(21)]" options:NSLayoutFormatAlignAllTop | NSLayoutFormatAlignAllBottom metrics:nil views:views]];
    //設(shè)置垂直方向居中約束
    [searchField addConstraint:[NSLayoutConstraint constraintWithItem:voiceButton attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:searchField attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];

//按鈕觸摸事件
- (IBAction)tapVoiceButton:(id)sender {
    NSLog(@"Tap voiceButton");
}

//監(jiān)控文本變化
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
    self.voiceButton.hidden = searchText.length > 0;
}

好了,打完收工,最終效果圖如下:

record.gif

完整代碼在這里。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 前言 在iOS8中,Apple在UIKit框架中給我們提供了UISearchController來代替之前的UIS...
    SeraZheng閱讀 3,350評論 12 23
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,200評論 4 61
  • UISearchBar屬性相關(guān) _searchBar = [[UISearchBar alloc] initWit...
    zhong_JF閱讀 2,218評論 0 9
  • 概述在iOS開發(fā)中UITableView可以說是使用最廣泛的控件,我們平時使用的軟件中到處都可以看到它的影子,類似...
    liudhkk閱讀 9,086評論 3 38
  • 文︱袁方 懵懂的孩提時節(jié)對死亡的記憶也和興奮聯(lián)系在一起。在楊村,能夠回憶起來的第一個死亡的人是三爺。那是一個春天的...
    袁方童鞋閱讀 1,865評論 9 11