美文网首页iOS大咖说
iOS UISearchBar 封装 自定义UISearchBa

iOS UISearchBar 封装 自定义UISearchBa

作者: 我的名字就这么长 | 来源:发表于2018-08-06 12:45 被阅读474次

    鉴于UISearchBar样式修改不好操作,以及它的一些系统默认处理不符合实际产品需求,和iOS 11之后UISearchBar的placeholder居中问题跟之前版本不一样,特此封装了一个UISearchBar的子类,以后用的时候直接拿来用就方便多了。附上地址项目地址

    先总结:本demo封装、修改的内容

    1、UISearchBar 样式

    2、iOS11之前placeholder文字默认是居左的,iOS 11默认居中的,为了样式统一,且两个样式都支持,做了一下封装。只要继承该控件,控件内部已经实现placeholder居中和居左方案。

    3、UISearchBar 的clearBtn的显示方式

    4、取消按钮的title 文字内容、颜色

    5、UISearchBar当失去焦点时,系统会把取消按钮的enable设为no,这样点击取消按钮的时候默认输入框会获得焦点,而不是取消搜索,实际应用中很少这样用,所以封装的控件中对改功能做了支持,既可以支持原系统默认事件,亦可以直接响应取消事件。

    具体支持哪些修改,详见头文件

    @interfaceFLJSearchBar :UISearchBar

    /**

     这里根据实际应用来做的封装,一般情况都是 UITextFieldViewModeWhileEditing和UITextFieldViewModeNever

     yes-UITextFieldViewModeNever    no-UITextFieldViewModeWhileEditing

     默认 no

     */

    @property(nonatomic,assign)BOOL clearBtnHidden;

    //placeHolder 是否居中 iOS11之前默认是居中的 iOS11之后居左

    @property(nonatomic,assign)BOOL placeHolderCenter;

    //placeHolder文字

    @property(nonatomic,copy)NSString* placeHolderString;

    //placeHolder字号 默认16 和输入框文字字号一样

    @property(nonatomic,strong)UIFont* placeHolderStringFont;

    //placeHolder文字颜色

    @property(nonatomic,strong)UIColor* placeHolderStringColor;

    //取消按钮文字  系统默认cancel,这里默认 取消

    @property(nonatomic,copy)NSString* cancelBtnTitle;

    //取消按钮文字颜色

    @property(nonatomic,strong)UIColor* cancelBtnTitleColor;

    //圆角

    @property(nonatomic,assign)CGFloat cornerRadius;

    //边框颜色

    @property(nonatomic,strong)UIColor* borderColor;

    //边框宽度

    @property(nonatomic,assign)CGFloat borderWidth;

    //记录默认情况下的搜索图片偏移

    @property(nonatomic,assign)UIOffsetoriginPositionSearchOffSet;

    //系统searchbar,如果search没有获得焦点,点击取消默认会获得焦点(而不会响应取消事件)

    //cancelInputDisabled yes 直接响应取消事件

    @property(nonatomic,assign)BOOL cancelInputDisabled;

    .m实现

    #import "FLJSearchBar.h"

    #import "UIImage+Extension.h"

    #define kDefaultBorderColor [UIColor colorWithRed:(225)/255.0green:(226)/255.0blue:(227)/255.0alpha:1.0]

    #define kDefaultPlaceHolderTextFont [UIFont systemFontOfSize:16]

    #define kDefaultPlaceHolerTextColor [UIColor colorWithRed:(187)/255.0green:(187)/255.0blue:(187)/255.0alpha:1.0]

    #define kDefaultCancelBtnTitleFont [UIFont systemFontOfSize:16]

    #define kDefaultCancelBtnTitleColor [UIColor colorWithRed:(102)/255.0green:(102)/255.0blue:(102)/255.0alpha:1.0]

    @interface FLJSearchBar ()

    @property(nonatomic,assign)BOOL hideClearBtn;

    @end

    @implementation FLJSearchBar

    -(instancetype)initWithFrame:(CGRect)frame

    {

        if(self== [superinitWithFrame:frame]) {

            [self setBackgroundColor:[UIColor whiteColor]];

            //cancel按钮显示

            self.showsCancelButton = YES;

            //光标颜色tintColor

    //        self.tintColor = [UIColor clearColor];

            self.backgroundImage = [UIImage imageWithColor:[UIColor whiteColor] size:CGSizeMake(100, self.bounds.size.height)];

            [self setImage:[UIImage imageNamed:@"icon_search"] forSearchBarIcon:UISearchBarIconSearch state:UIControlStateNormal];

            [self setImage:[UIImage imageNamed:@"icon_search_clear"] forSearchBarIcon:UISearchBarIconClear state:UIControlStateNormal];

            //ios11 之前这个高度决定textfield高度 默认28

            [self setSearchFieldBackgroundImage:[UIImage imageWithColor:[UIColor clearColor] size:CGSizeMake(100, self.bounds.size.height)] forState:UIControlStateNormal];

            self.originPositionSearchOffSet = UIOffsetMake(10, 0);

            //搜索图标偏移

            [self setPositionAdjustment:self.originPositionSearchOffSet forSearchBarIcon:UISearchBarIconSearch];

            //清除按钮偏移向左偏移10

            [self setPositionAdjustment:UIOffsetMake(-10, 0) forSearchBarIcon:UISearchBarIconClear];

            //整个输入框(textfield)的偏移量

    //        [self setSearchFieldBackgroundPositionAdjustment:UIOffsetMake(10, 0)];

            //文字距离搜索图标的偏移,默认是紧挨着的

            [self setSearchTextPositionAdjustment:UIOffsetMake(10, 0)];

            self.placeHolderString = @"请输入搜索内容";

            self.cornerRadius=self.bounds.size.height/2.f;

            self.borderWidth=1.f;

            self.borderColor = kDefaultBorderColor;

            self.placeHolderCenter = NO;

            [self setCancelBtnTitle:@"取消"];

        }

        return self;

    }

    #pragma mark  setter & getter

    /**

     设置placeHolder

     @param placeHolderString placeHolder

     */

    -(void)setPlaceHolderString:(NSString*)placeHolderString

    {

        _placeHolderString= [placeHolderStringcopy];

        UITextField*textField = [selftextField];

        if(textField) {

            textField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:_placeHolderString attributes:@{NSForegroundColorAttributeName:_placeHolderStringColor?_placeHolderStringColor:kDefaultPlaceHolerTextColor,NSFontAttributeName:_placeHolderStringFont?_placeHolderStringFont:kDefaultPlaceHolderTextFont}];

        }

    }

    /**

     设置placeHolder字号

     @param placeHolderStringFont 字号

     */

    -(void)setPlaceHolderStringFont:(UIFont*)placeHolderStringFont

    {

        _placeHolderStringFont= placeHolderStringFont;

        UITextField*textField = [selftextField];

        if(textField) {

            textField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:_placeHolderString attributes:@{NSForegroundColorAttributeName:_placeHolderStringColor?_placeHolderStringColor:kDefaultPlaceHolerTextColor,NSFontAttributeName:_placeHolderStringFont}];

            textField.font = _placeHolderStringFont;

        }

    }

    /**

     设置placehHolder字体颜色

     @param placeHolderStringColor placehHolder字体颜色

     */

    -(void)setPlaceHolderStringColor:(UIColor*)placeHolderStringColor

    {

        _placeHolderStringColor= placeHolderStringColor;

        UITextField*textField = [selftextField];

        if(textField) {

            textField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:_placeHolderString attributes:@{NSForegroundColorAttributeName:_placeHolderStringColor,NSFontAttributeName:_placeHolderStringFont?_placeHolderStringFont:kDefaultPlaceHolderTextFont}];

        }

    }

    /**

     设置取消按钮文字

     */

    -(void)setCancelBtnTitle:(NSString*)cancelBtnTitle

    {

        _cancelBtnTitle= [cancelBtnTitlecopy];

        UIButton*cancel = [selfcancelBtn];

        if(cancel) {

            [cancelsetTitle:cancelBtnTitle forState:UIControlStateNormal];

            if (!self.cancelBtnTitleColor) {

                [cancelsetTitleColor:kDefaultCancelBtnTitleColor forState:UIControlStateNormal];

            }

            cancel.titleLabel.font = kDefaultCancelBtnTitleFont;

        }

    }

    /**

     设置取消按钮文字颜色

     */

    -(void)setCancelBtnTitleColor:(UIColor*)cancelBtnTitleColor

    {

        _cancelBtnTitleColor= cancelBtnTitleColor;

        UIButton*cancel = [selfcancelBtn];

        if(cancel) {

            [cancelsetTitleColor:_cancelBtnTitleColor forState:UIControlStateNormal];

        }

    }

    /**

     隐藏清除按钮

     @param clearBtnHidden yes隐藏 no输入的时候显示

     */

    -(void)setClearBtnHidden:(BOOL)clearBtnHidden

    {

        _clearBtnHidden= clearBtnHidden;

        self.hideClearBtn = _clearBtnHidden;

    }

    -(void)setHideClearBtn:(BOOL)hideClearBtn

    {

        _hideClearBtn= hideClearBtn;

        UITextField*textField = [selftextField];

        if(textField) {

            if (_hideClearBtn) {

                textField.clearButtonMode=UITextFieldViewModeNever;

            }else

                textField.clearButtonMode = UITextFieldViewModeWhileEditing;

        }

    }

    /**

     设置搜索框圆角

     */

    -(void)setCornerRadius:(CGFloat)cornerRadius

    {

        _cornerRadius= cornerRadius;

        UITextField*textField = [selftextField];

        if(textField) {

            textField.layer.cornerRadius=_cornerRadius;

            textField.layer.masksToBounds=YES;

            textField.clipsToBounds=YES;

        }

    }

    /**

     设置搜索框边框颜色

     */

    -(void)setBorderColor:(UIColor*)borderColor

    {

        _borderColor= borderColor;

        UITextField*textField = [selftextField];

        if(textField) {

            textField.layer.borderColor= borderColor.CGColor;

        }

    }

    /**

     设置搜索框边框 宽度

     */

    -(void)setBorderWidth:(CGFloat)borderWidth

    {

        _borderWidth= borderWidth;

        UITextField*textField = [selftextField];

        if(textField) {

            textField.layer.borderWidth= borderWidth;

            textField.layer.masksToBounds=YES;

        }

    }

    /**

     设置placeholder是否居中显示

     */

    - (void)setPlaceHolderCenter:(BOOL)placeHolderCenter

    {

        _placeHolderCenter= placeHolderCenter;

        if(@available(iOS11.0, *)) {

            UITextField* textField = [selftextField];

            textField.delegate=self;

            if (_placeHolderCenter) {

                [self setPositionAdjustment:UIOffsetMake((textField.frame.size.width-[self placeHolderTextWidth])/2, 0) forSearchBarIcon:UISearchBarIconSearch];

            }else

                [self setPositionAdjustment:self.originPositionSearchOffSet forSearchBarIcon:UISearchBarIconSearch];

        }else

        {

            SELcenterSelector =NSSelectorFromString([NSStringstringWithFormat:@"%@%@",@"setCenter",@"Placeholder:"]);

            if([selfrespondsToSelector:centerSelector])

            {

    //方法1         [self setValue:@(_placeHolderCenter) forKeyPath:@"centerPlaceholder"];

    //方法2

                NSMethodSignature*signature = [[UISearchBarclass]instanceMethodSignatureForSelector:centerSelector];

                NSInvocation*invocation = [NSInvocationinvocationWithMethodSignature:signature];

                [invocationsetTarget:self];

                [invocationsetSelector:centerSelector];

                [invocationsetArgument:&_placeHolderCenteratIndex:2];

                [invocationinvoke];

            }

        }

    }

    /**

     设置当输入框没有获得焦点时,点击取消按钮是否直接响应取消事件,而不是响应输入事件

     */

    -(void)setCancelInputDisabled:(BOOL)cancelInputDisabled

    {

        _cancelInputDisabled= cancelInputDisabled;

        UIButton*cancelBtn = [selfcancelBtn];

        cancelBtn.enabled=YES;

    }

    #pragma mark UITextFieldDelegate

    #warning 实现这两个代理方法后 searchbar的textFieldShouldBeginEditing 和textFieldShouldEndEditing将不执行 需要代理调起方法

    -(BOOL)textFieldShouldBeginEditing:(UITextField*)textField

    {

        if([self.delegaterespondsToSelector:@selector(searchBarShouldBeginEditing:)]) {

           BOOL begin = [self.delegate searchBarShouldBeginEditing:self];

            if(begin) {

                if(@available(iOS11.0, *) &&self.placeHolderCenter) {

                    [self setPositionAdjustment:self.originPositionSearchOffSet forSearchBarIcon:UISearchBarIconSearch];

                }

                if(!self.clearBtnHidden) {

                    self.hideClearBtn=NO;

                }

            }

            returnbegin;

        }

        if(@available(iOS11.0, *) &&self.placeHolderCenter) {

            [self setPositionAdjustment:self.originPositionSearchOffSet forSearchBarIcon:UISearchBarIconSearch];

        }

        if (!self.clearBtnHidden) {

            self.hideClearBtn=NO;

        }

        return YES;

    }

    -(BOOL)textFieldShouldEndEditing:(UITextField*)textField

    {

        if([self.delegaterespondsToSelector:@selector(searchBarShouldEndEditing:)]){

            BOOL end = [self.delegate searchBarShouldEndEditing:self];

            if(end) {

                if(@available(iOS11.0, *) &&self.placeHolderCenter) {

                    if(textField.text.length==0) {

                        [self setPositionAdjustment:UIOffsetMake((textField.frame.size.width-[self placeHolderTextWidth])/2, 0) forSearchBarIcon:UISearchBarIconSearch];

                    }

                }

                if(self.clearBtnHidden) {

                    self.hideClearBtn=YES;

                }

            }

            returnend;

        }

        if(@available(iOS11.0, *) &&self.placeHolderCenter) {

            if(textField.text.length==0) {

                [self setPositionAdjustment:UIOffsetMake((textField.frame.size.width-[self placeHolderTextWidth])/2, 0) forSearchBarIcon:UISearchBarIconSearch];

            }

        }

        if (self.clearBtnHidden) {

            self.hideClearBtn=YES;

        }

        return YES;

    }

    -(void)textFieldDidEndEditing:(UITextField*)textField

    {

        if (self.cancelInputDisabled) {

            self.cancelInputDisabled = YES;

        }

    }

    /**

     获得搜索框

     */

    -(UITextField*)textField

    {

        UITextField*searchField = [selfvalueForKey:@"searchField"];

        //    for (UIView *view in self.subviews.lastObject.subviews) {

        //        if([view isKindOfClass:NSClassFromString(@"UISearchBarTextField")]) {

        //            return (UITextField*)view;

        //        }

        //    }

        returnsearchField;

    }

    /**

     获得取消按钮

     */

    -(UIButton*)cancelBtn

    {

        UIView* view = [selfvalueForKeyPath:@"cancelButton"];

        //    if ([view isKindOfClass:NSClassFromString(@"UINavigationButton")]) {

        UIButton*cancelBtn = (UIButton*)view;

        //    }

        returncancelBtn;

    }

    /**

     计算placeHolder的宽度

     */

    -(CGFloat)placeHolderTextWidth

    {

        UITextField* textField = [selftextField];

        return [self.placeHolderString boundingRectWithSize:textField.frame.size options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSForegroundColorAttributeName:_placeHolderStringColor?_placeHolderStringColor:kDefaultPlaceHolerTextColor,NSFontAttributeName:_placeHolderStringFont?_placeHolderStringFont:kDefaultPlaceHolderTextFont} context:nil].size.width;

    }

    -(void)layoutSubviews

    {

        [super layoutSubviews];

        if(@available(iOS11.0, *) &&self.placeHolderCenter) {

            UITextField* textField = [selftextField];

            [self setPositionAdjustment:UIOffsetMake((textField.frame.size.width-[self placeHolderTextWidth])/2, 0) forSearchBarIcon:UISearchBarIconSearch];

        }

    }

    相关文章

      网友评论

      • 目染江夏:希望加上 markdown,代码看着更舒服
      • allulogn:请问楼主封装的这个searchbar在iOS11之前的版本使用,placeholder在点击的时候是不是会有从中间到左边的动画(设置居左的话),楼主是怎么解决的呢?
        allulogn:@我的名字就这么长 我已经知道我这边出现动画不是这个方法的原因,而是其他的,谢谢
        我的名字就这么长:代码只是控制了placeholder是居左还是居中的,文字输入都是从左向右的。1、当placeholder居左的时候,开始输入没有动画2、placeholder居中,开始输入搜索图标和placeholder跑到左边动画是由系统默认的。searchbar有个私有属性centerPlaceholder,iOS11前是来控制placeholder是否居中的,可以用 [self setValue:@(_placeHolderCenter) forKeyPath:@"centerPlaceholder"];来控制。我的项目代码中使用NSInvocation来实现的(主要是想记录下NSInvocation的用法),稍后我会更新下。

      本文标题:iOS UISearchBar 封装 自定义UISearchBa

      本文链接:https://www.haomeiwen.com/subject/tliwvftx.html