很多APP都会涉及到搜索框,苹果也为我们提供了默认的搜索框UISearchBar。但实际项目中我们通常需要更改系统默认搜索框的样式。为了实现这一目标,我们需要先搞懂UISearchBar的属性及方法。在系统的掌握了这些基础的前提下才能更好的去应用它,包括修改样式、或者是模仿系统搜索框的样式自定义一个自己的搜索框等。
本文主要介绍内容分为以下三个部分:
UISearchBar的属性
UISearchBar的方法
自定义UISearchBar的样式
1.UISearchBar的属性
介绍之前先说一下UISearchBar的初始化方法:UISearchBar是UIView的子类,它的初始化方法有三种:
-(instancetype)init
-(instancetype)initWithFrame:(CGRect)frame
-(nullableinstancetype)initWithCoder:(NSCoder*)aDecoder
这三个初始化方法是我们常见的初始化UIView以及它的子类的方法,比较常见,而且也不是介绍重点,所以这里不展开说明。
1.1搜索框风格
属性
//搜索框风格
@property(nonatomic)UIBarStylebarStyle;
UIBarStyle有四种枚举值,但后两种已经禁用。
typedefNS_ENUM(NSInteger,UIBarStyle){
UIBarStyleDefault//白色搜索框,灰色背景
UIBarStyleBlack//黑色搜索框,
UIBarStyleBlackOpaque=1,//禁用.UseUIBarStyleBlack
UIBarStyleBlackTranslucent=2,//禁用.UseUIBarStyleBlackandsetthetranslucentpropertytoYES
}
效果图:
UIBarStyleDefault样式
UIBarStyleBlack样式
1.2搜索的文本、搜索框顶部的提示信息、占位符
//搜索的文本
@property(nullable,nonatomic,copy)NSString*text;
//搜索框顶部的提示信息
@property(nullable,nonatomic,copy)NSString*prompt;
//占位符,默认nil,若有值则在输入文本后消失
@property(nullable,nonatomic,copy)NSString*placeholder;
prompt和placeholder
输入文本为text后placeholder消失
1.3搜索框右侧的按钮
//搜索框右侧是否显示图书按钮
@property(nonatomic)BOOLshowsBookmarkButton;
//搜索框右侧是否显示取消按钮
@property(nonatomic)BOOLshowsCancelButton;
//搜索框右侧是否显示搜索结果按钮
@property(nonatomic)BOOLshowsSearchResultsButton;
//搜索结果按钮为选中状态
@property(nonatomic,getter=isSearchResultsButtonSelected)BOOLsearchResultsButtonSelected;
以上四个属性的默认值都是NO
showsBookmarkButton=YES效果
showsCancelButton=YES效果
showsSearchResultsButton=YES效果
searchResultsButtonSelected=YES效果,要结合showsSearchResultsButton=YES使用
1.4风格颜色、背景颜色
//风格颜色,可用于修改输入框的光标颜色,取消按钮和选择栏被选中时候都会变成设置的颜色
@property(null_resettable,nonatomic,strong)UIColor*tintColor;
//搜索框背景颜色
@property(nullable,nonatomic,strong)UIColor*barTintColor;
测试代码
self.tintColor=[UIColororangeColor];//设置光标颜色为橘色
self.barTintColor=[UIColorgrayColor];//设置搜索框背景颜色为灰色
tintColor和barTintColor
1.5搜索框样式
//搜索框样式
@property(nonatomic)UISearchBarStylesearchBarStyle
它有三种枚举值:
typedefNS_ENUM(NSUInteger,UISearchBarStyle){
UISearchBarStyleDefault,//默认样式,和UISearchBarStyleProminent一样
UISearchBarStyleProminent,//显示背景,常用在myMail,MessagesandContacts
UISearchBarStyleMinimal//不显示背景,系统自带的背景色无效,自定义的有效,常用在Calendar,NotesandMusic
UISearchBarStyleMinimal不显示背景
UISearchBarStyleDefault和UISearchBarStyleProminent都显示背景
1.6搜索栏的附件选择按钮视图
//选择按钮试图的按钮标题
@property(nullable,nonatomic,copy)NSArray*scopeButtonTitles;
//选中的按钮下标值,默认0.如果超出范围则忽略
@property(nonatomic)NSIntegerselectedScopeButtonIndex;
//是否显示搜索栏的附件选择按钮视图
@property(nonatomic)BOOLshowsScopeBar;
self.placeholder=@"搜索";
self.showsScopeBar=YES;
self.scopeButtonTitles=@[@"One",@"Two",@"Three"];
self.selectedScopeButtonIndex=1;
带选择按钮视图的搜索栏
1.7搜索框背景图片、搜索框附属分栏条的背景颜色
//搜索框背景图片
@property(nullable,nonatomic,strong)UIImage*backgroundImage;
//搜索框附属分栏条的背景颜色
@property(nullable,nonatomic,strong)UIImage*scopeBarBackgroundImage;
//设置搜索框背景图片
UIImage*backgroundImage=[UIImageimageNamed:@"image001"];
self.backgroundImage=backgroundImage;
UIImage*scopeBarBackgroundImage=[UIImageimageNamed:@"image002"];
self.scopeBarBackgroundImage=scopeBarBackgroundImage;
设置backgroundImage和scopeBarBackgroundImage
1.8索框中文本框的背景偏移量和文本偏移量
//搜索框中文本框的背景偏移量
@property(nonatomic)UIOffsetsearchFieldBackgroundPositionAdjustment;
//搜索框中文本框的文本偏移量
@property(nonatomic)UIOffsetsearchTextPositionAdjustment;
self.searchFieldBackgroundPositionAdjustment=UIOffsetMake(5,3);
self.searchTextPositionAdjustment=UIOffsetMake(10,5);
设置偏移量前后对比图
PS:UITextInputAssistantItem*inputAssistantItem、BOOLtranslucent、UIView*inputAccessoryView经过测试这三个属性并不太清楚具体实现效果,之后会继续深入了解一下,记在这里,作为提醒,如果有谁刚好了解它们,希望能够给与帮助,非常感谢。
2.UISearchBar的方法
2.1设置是否动画效果的显示或隐藏取消按钮
方法:
//设置是否动画效果的显示或隐藏取消按钮
-(void)setShowsCancelButton:(BOOL)showsCancelButtonanimated:(BOOL)animated
通常在开始编辑文本时将调用该方法,让取消按钮显示出来。
测试代码:
-(void)searchBarTextDidBeginEditing:(UISearchBar*)searchBar{
NSLog(@"开始输入搜索内容");
[searchBarsetShowsCancelButton:YESanimated:YES];//动画显示取消按钮
setShowsCancelButton:animated:
2.2设置(获取)搜索框背景图片、选择按钮视图的背景图片、文本框的背景图片
//1.设置搜索框背景图片
-(void)setBackgroundImage:(nullableUIImage*)backgroundImageforBarPosition:(UIBarPosition)barPositionbarMetrics:(UIBarMetrics)barMetrics
//获取置搜索框背景图片
-(nullableUIImage*)backgroundImageForBarPosition:(UIBarPosition)barPositionbarMetrics:(UIBarMetrics)barMetrics
//2.设置选择按钮视图的背景图片
-(void)setScopeBarButtonBackgroundImage:(nullableUIImage*)backgroundImageforState:(UIControlState)state
//获取选择按钮视图的背景图片
-(nullableUIImage*)scopeBarButtonBackgroundImageForState:(UIControlState)state
//3.设置搜索框文本框的背景图片
-(void)setSearchFieldBackgroundImage:(nullableUIImage*)backgroundImageforState:(UIControlState)state
//获取搜索框文本框的背景图片
-(nullableUIImage*)searchFieldBackgroundImageForState:(UIControlState)state
[selfsetBackgroundImage:[UIImageimageNamed:@"image001"]forBarPosition:UIBarPositionAnybarMetrics:UIBarMetricsDefault];
//设置选择按钮视图的背景图片
[selfsetScopeBarButtonBackgroundImage:[UIImageimageNamed:@"image002"]forState:UIControlStateNormal];
//设置搜索框文本框的背景图片
[selfsetSearchFieldBackgroundImage:[UIImageimageNamed:@"image003"]forState:UIControlStateNormal];
设置搜索框背景图片、选择按钮视图的背景图片、文本框的背景图片
我们可以观察一下选择按钮视图的背景图片,发现这个图片只是设置在三个按钮的底部视图,而大的外面的空余背景依旧是灰色,对比1.7中使用属性UIImage*scopeBarBackgroundImage设置的背景图片,发现使用属性设置背景图片不会有空余的灰色背景,该属性针对的是大的scopeBar,而不是一个scopeBarButton,这一点需要注意区分。
2.3设置(获取)搜索框的图标(包括搜索图标、清除输入的文字的图标、图书图标、搜索结果列表图标)
//设置搜索框的图标
-(void)setImage:(nullableUIImage*)iconImageforSearchBarIcon:(UISearchBarIcon)iconstate:(UIControlState)state;
//获取搜索框的图标
-(nullableUIImage*)imageForSearchBarIcon:(UISearchBarIcon)iconstate:(UIControlState)state;
搜索框图标UISearchBarIcon有四个枚举值:
typedefNS_ENUM(NSInteger,UISearchBarIcon){
UISearchBarIconSearch,//搜索框放大镜图标
UISearchBarIconClear,//搜索框右侧可用于清除输入的文字的图标x
UISearchBarIconBookmark,//搜索框右侧的图书图标
UISearchBarIconResultsList,//搜索框右侧的搜索结果列表图标
};
self.showsSearchResultsButton=YES;
//设置搜索框放大镜图标
UIImage*searchIcon=[UIImageimageNamed:@"searchIcon"];
[selfsetImage:searchIconforSearchBarIcon:UISearchBarIconSearchstate:UIControlStateNormal];
//设置搜索结果列表图标
UIImage*resultListIcon=[UIImageimageNamed:@"arrow"];
[selfsetImage:resultListIconforSearchBarIcon:UISearchBarIconResultsListstate:UIControlStateNormal];
效果图
重新设置搜索框搜索图标和显示结果列表的图标
可以发现搜索图标和搜索结果列表图标已经改变,至于其他的两个图标仿照上面代码修改即可实现。
2.4设置(获取)选择按钮视图的分割线图片、按钮上显示的标题样式
方法
//设置选择按钮视图的分割线图片
-(void)setScopeBarButtonDividerImage:(nullableUIImage*)dividerImageforLeftSegmentState:(UIControlState)leftStaterightSegmentState:(UIControlState)rightState;
//获取选择按钮视图的分割线图片
-(nullableUIImage*)scopeBarButtonDividerImageForLeftSegmentState:(UIControlState)leftStaterightSegmentState:(UIControlState)rightState;
//设置选择按钮视图的标题样式
-(void)setScopeBarButtonTitleTextAttributes:(nullableNSDictionary*)attributesforState:(UIControlState)state;
//获取选择按钮视图的标题样式
-(nullableNSDictionary*)scopeBarButtonTitleTextAttributesForState:(UIControlState)state
self.scopeButtonTitles=@[@"One",@"Two",@"Three",@"Four"];
//设置选择按钮视图的分割线图片为一个橘色的线条
[selfsetScopeBarButtonDividerImage:[UIImageimageNamed:@"divider"]forLeftSegmentState:UIControlStateNormalrightSegmentState:UIControlStateNormal];
//设置选择按钮视图的标题样式为20号橘色空心的系统字体
NSDictionary*attributeDic=@{NSFontAttributeName:[UIFontsystemFontOfSize:20],NSStrokeColorAttributeName:[UIColororangeColor],NSStrokeWidthAttributeName:@(3)};
[selfsetScopeBarButtonTitleTextAttributes:attributeDicforState:UIControlStateNormal];
设置选择按钮视图的分割线图片和按钮上显示的标题样式的效果图
2.5设置(获取)搜索框四种图标的偏移量
//设置搜索框图标的偏移量
-(void)setPositionAdjustment:(UIOffset)adjustmentforSearchBarIcon:(UISearchBarIcon)icon;
//获取搜索框图标的偏移量
-(UIOffset)positionAdjustmentForSearchBarIcon:(UISearchBarIcon)icon;
[selfsetPositionAdjustment:UIOffsetMake(15,5)forSearchBarIcon:UISearchBarIconSearch];
设置搜索图标向有偏移15个单位,向下偏移5个单位后的效果图
2.6UISearchBarDelegate代理方法
//1.将要开始编辑文本时会调用该方法,返回NO将不会变成第一响应者
-(BOOL)searchBarShouldBeginEditing:(UISearchBar*)searchBar;
//2.开始输入文本会调用该方法
-(void)searchBarTextDidBeginEditing:(UISearchBar*)searchBar;
//3.将要结束编辑文本时会调用该方法,返回NO将不会释放第一响应者
-(BOOL)searchBarShouldEndEditing:(UISearchBar*)searchBar;
//4.结束编辑文本时调用该方法
-(void)searchBarTextDidEndEditing:(UISearchBar*)searchBar;
//5.文本改变会调用该方法(包含clear文本)
-(void)searchBar:(UISearchBar*)searchBartextDidChange:(NSString*)searchText;
//6.文字改变前会调用该方法,返回NO则不能加入新的编辑文字
-(BOOL)searchBar:(UISearchBar*)searchBarshouldChangeTextInRange:(NSRange)rangereplacementText:(NSString*)text;
//7.键盘上的搜索按钮点击的会调用该方法
-(void)searchBarSearchButtonClicked:(UISearchBar*)searchBar;
//8.搜索框右侧图书按钮点击会调用该方法
-(void)searchBarBookmarkButtonClicked:(UISearchBar*)searchBar;
//9.点击取消按钮会调用该方法
-(void)searchBarCancelButtonClicked:(UISearchBar*)searchBar;
//10.搜索结果列表按钮被按下会调用该方法
-(void)searchBarResultsListButtonClicked:(UISearchBar*)searchBar;
//11.搜索框的附属按钮视图中切换按钮会调用该方法
-(void)searchBar:(UISearchBar*)searchBarselectedScopeButtonIndexDidChange:(NSInteger)selectedScope;
-(BOOL)searchBarShouldBeginEditing:(UISearchBar*)searchBar{
returnYES;
searchBar.prompt=@"1.开始编辑文本";
[searchBarsetShowsCancelButton:YESanimated:YES];//动画效果显示取消按钮
-(BOOL)searchBar:(UISearchBar*)searchBarshouldChangeTextInRange:(NSRange)rangereplacementText:(NSString*)text{
-(void)searchBar:(UISearchBar*)searchBartextDidChange:(NSString*)searchText{
searchBar.prompt=@"2.在改变文本过程中。。。";
-(void)searchBarSearchButtonClicked:(UISearchBar*)searchBar{
searchBar.prompt=@"3.点击键盘上的搜索按钮";
-(void)searchBarCancelButtonClicked:(UISearchBar*)searchBar{
searchBar.prompt=@"4.点击取消按钮";
searchBar.text=@"";
[selfsetShowsCancelButton:NOanimated:YES];
//如果希望在点击取消按钮调用结束编辑方法需要让加上这句代码
//[searchBarresignFirstResponder];
-(BOOL)searchBarShouldEndEditing:(UISearchBar*)searchBar{
-(void)searchBarTextDidEndEditing:(UISearchBar*)searchBar{
searchBar.prompt=@"5.已经结束编辑文本";
点击取消按钮但没有释放搜索框的第一响应者身份效果图:
gif1
点击取消按钮用时释放搜索框的第一响应者身份会调用结束编辑文本的方法:
gif2
3.自定义UISearchBar的样式
在自定义UISearchBar样式之前我们先来看一下UISearchBar的组成:
UISearchBar层次结构截图
根据这个截图我们可以概括为下图:
简单概括的UISearchBar层次结构
根据这个简单的层次结构图,我们可以更好的了解UISearchBar的组成部分,这样有助于我们更方便的进行自定义样式,下面开始自定义样式!
目标搜索框样式
首先看一下目标样式
目标搜索框样式.gif
实现代码
//委托
[searchBarsetShowsCancelButton:YESanimated:YES];
[searchBarresignFirstResponder];
self.voiceButton.hidden=searchText.length>0YES:NO;
self.voiceButton.hidden=NO;
//样式设计
-(void)modifyStyleByTraversal{
//修改搜索框背景图片为自定义的灰色
UIColor*backgroundImageColor=[UIColorcolorwithHex:0xE3DFDA];
UIImage*clearImg=[selfimageWithColor:backgroundImageColorandHeight:45.0];
self.backgroundImage=clearImg;
//修改搜索框光标颜色
self.tintColor=[UIColorP2Color];
//修改搜索框的搜索图标
[selfsetImage:[UIImageimageNamed:@"searchIcon"]forSearchBarIcon:UISearchBarIconSearchstate:UIControlStateNormal];
for(UIView*viewinself.subviews.lastObject.subviews){
if([viewisKindOfClass:NSClassFromString(@"UISearchBarTextField")]){
UITextField*textField=(UITextField*)view;
//添加话筒按钮
[selfaddVoiceButton:textField];
//设置输入框的背景颜色
textField.clipsToBounds=YES;
textField.backgroundColor=[UIColorP1Color];
//设置输入框边框的圆角以及颜色
textField.layer.cornerRadius=10.0f;
textField.layer.borderColor=[UIColorP2Color].CGColor;
textField.layer.borderWidth=1;
//设置输入字体颜色
textField.textColor=[UIColorP2Color];
//设置默认文字颜色
textField.attributedPlaceholder=[[NSAttributedStringalloc]initWithString:@"搜索"attributes:@{NSForegroundColorAttributeName:[UIColorP2Color]}];
if([viewisKindOfClass:NSClassFromString(@"UINavigationButton")]){
UIButton*cancel=(UIButton*)view;
[cancelsetTitle:@"取消"forState:UIControlStateNormal];
[cancelsetTitleColor:[UIColorP2Color]forState:UIControlStateNormal];
//画指定高度和颜色的图片
-(UIImage*)imageWithColor:(UIColor*)colorandHeight:(CGFloat)height{
CGRectrect=CGRectMake(0.0,0.0,1.0,height);
UIGraphicsBeginImageContext(rect.size);
CGContextRefcontext=UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context,[colorCGColor]);
CGContextFillRect(context,rect);
UIImage*image=UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
returnimage;
-(void)addVoiceButton:(UIView*)view{
if(!self.voiceButton){
self.voiceButton=[UIButtonbuttonWithType:UIButtonTypeCustom];
[self.voiceButtonsetImage:[UIImageimageNamed:@"voice"]forState:UIControlStateNormal];
[self.voiceButtonaddTarget:selfaction:@selector(say)forControlEvents:UIControlEventTouchUpInside];
[viewaddSubview:self.voiceButton];
self.voiceButton.translatesAutoresizingMaskIntoConstraints=NO;
[self.voiceButtonaddWidthConstraint:15];
[self.voiceButtonaddHeightConstraint:15];
[self.voiceButtonaddTopConstraintToView:viewconstant:8];
[self.voiceButtonaddTrailingConstraintToView:viewconstant:-15];
//点击话筒触发该方法
-(void)say{
//self.prompt=@"在讲话哦!";
补充:修改UISearchBar宽高
UISearchBar有默认的布局样式,我们想要修改他的宽高,需要重写layoutSubviews方法。然后在这个方法里面修改UISearchBarTextField的宽高。
-(void)layoutSubviews{
[superlayoutSubviews];
UITextField*textField=[selfvalueForKey:@"searchBarTextField"];
if(textField){
textField.frame=CGRectMake(50,10,self.bounds.size.width-100,35);