iOS搜索框样例

每个App的搜索界面下边都会有热门搜索,历史搜索之类的标签,这里介绍个框架,

可以非常容易实现标签类的不规则流式布局,也可以实现固定宽度和高度的布局,也

支持Autolayout,使用起来也是非常舒服。SKTagView原框架下只有根据文字宽度不固

定的的模式,那么如果需求有固定宽高模式的,老规矩,只能改源码了.


请看图:


传统模式:



TableView cell模式的不规则模式和固定宽高模式:


   

电影放完了,开始简单介绍下


这里有两个能用到的地方(截图来自淘宝)

   


OK,根据以上两个用途,写了两个简单的Demo,无需再繁琐的计算了,直接导入

SKTagView来进行布局,非常简单

Demo地址:https://github.com/DeftMKJ/SKTag




Demo1

首先:

创建一个UISearchBar来进行模拟搜索

[objc]  view plain  copy
  1. - (void)viewDidLoad {  
  2.     [super viewDidLoad];  
  3.     // Do any additional setup after loading the view from its nib.  
  4.     UIView *titleView = [[UIView alloc] initWithFrame:CGRectMake(0037544)];  
  5.     titleView.backgroundColor = [UIColor clearColor];  
  6.     self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0036044)];  
  7.     self.searchBar.delegate = self;  
  8.     self.searchBar.placeholder = @"请输入要搜索的文字";  
  9. //    self.searchBar.showsCancelButton = YES;  
  10.     // 键盘确认按钮的名字  
  11.     self.searchBar.returnKeyType = UIReturnKeyNext;  
  12.     // 把默认灰色背景浮层给去掉  
  13.     self.searchBar.backgroundColor = [UIColor clearColor];  
  14.     self.searchBar.backgroundImage = [UIImage new];  
  15.     UITextField *searBarTextField = [self.searchBar valueForKey:@"_searchField"];  
  16.     if (searBarTextField)  
  17.     {  
  18.         [searBarTextField setBackgroundColor:[UIColor colorWithRed:243/255.0 green:243/255.0 blue:243/255.0 alpha:1]];  
  19.         searBarTextField.borderStyle = UITextBorderStyleRoundedRect;  
  20.         searBarTextField.layer.cornerRadius = 5.0f;  
  21.     }  
  22.     else  
  23.     {  
  24.         // 通过颜色画一个Image出来  
  25.         UIImage *image = [UIImage imageWithColor:[UIColor colorWithRed:243/255.0 green:243/255.0 blue:243/255.0 alpha:1] forSize:CGSizeMake(2828)];  
  26.         [self.searchBar setSearchFieldBackgroundImage:image forState:UIControlStateNormal];  
  27.     }  
  28.     [titleView addSubview:self.searchBar];  
  29.     self.navigationItem.titleView = titleView;  
  30.     [self.searchBar becomeFirstResponder];  
  31.     [self configTagView];  
  32. }  


来看看效果哈



但是你们有没有觉得他右边的Cancel一点都协调么,要改了它,但是这东西

系统又没有给属性接口让你改......



那么试着咱们把SearchBar下面的Subviews统统打印出来看一下


咦???这个数组里面只有个UIView么,不科学啊,要不再拨开一层看看


NICE啊,这波操作可以啊,找到了,藏那么里面,既然找到了,就在这个代理方法里面进行修改

[objc]  view plain  copy
  1. - (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar{  
  2. //    (lldb) po self.searchBar.subviews[0].subviews  
  3. //    <__NSArrayM 0x7ffba1e08330>(  
  4. //                                <UISearchBarBackground: 0x7ffba1c670e0; frame = (0 0; 360 44); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x7ffba1c201a0>>,  
  5. //                                <UISearchBarTextField: 0x7ffba1c905b0; frame = (0 0; 0 0); text = ''; clipsToBounds = YES; opaque = NO; layer = <CALayer: 0x7ffba1c90360>>,  
  6. //                                <UINavigationButton: 0x7ffba1c982c0; frame = (0 0; 53 30); opaque = NO; layer = <CALayer: 0x7ffba1c98800>>  
  7. //                                )  
  8.       
  9.       
  10. //      
  11. //    (lldb) po self.searchBar.subviews  
  12. //    <__NSArrayM 0x7ffba1e77280>(  
  13. //                                <UIView: 0x7ffba1c8a470; frame = (0 0; 360 44); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x7ffba1c7ddc0>>  
  14. //                                )  
  15.     searchBar.showsCancelButton = YES;  
  16.     for(UIView *view in  [[[searchBar subviews] objectAtIndex:0] subviews]) {  
  17.         if([view isKindOfClass:[NSClassFromString(@"UINavigationButton") class]]) {  
  18.             UIButton * cancel =(UIButton *)view;  
  19.             [cancel setTitle:@"搜索" forState:UIControlStateNormal];  
  20.             cancel.titleLabel.font = [UIFont systemFontOfSize:14];  
  21.             cancel.tintColor = [UIColor redColor];  
  22.         }  
  23.     }}  

修改完后的效果(Mac这截图效果也是醉了


然后

我们来创建SKTagView,各种属性已经加上注释

[objc]  view plain  copy
  1. // 配置  
  2. - (void)configTagView  
  3. {  
  4.     self.label = [[UILabel alloc] initWithFrame:CGRectMake(109010030)];  
  5.     self.label.textColor = [UIColor blackColor];  
  6.     self.label.font = [UIFont systemFontOfSize:13];  
  7.     self.label.text = @"历史搜索";  
  8.     [self.view addSubview:self.label];  
  9.       
  10.     // 先移除掉所有  
  11.     [self.tagView removeAllTags];  
  12.     // 初始化  
  13.     self.tagView = [[SKTagView alloc] init];  
  14.     // 整个tagView对应其SuperView的上左下右距离  
  15.     self.tagView.padding = UIEdgeInsetsMake(10101010);  
  16.     // 上下行之间的距离  
  17.     self.tagView.lineSpacing = 10;  
  18.     // item之间的距离  
  19.     self.tagView.interitemSpacing = 20;  
  20.     // 最大宽度  
  21.     self.tagView.preferredMaxLayoutWidth = 375;  
  22. //    @property (assign, nonatomic) CGFloat regularWidth; //!< 固定宽度  
  23. //    @property (nonatomic,assign ) CGFloat regularHeight; //!< 固定高度  
  24.     // 原作者没有能加固定宽度的,自己修改源码加上了固定宽度和高度,默认是0,就是标签式布局,如果实现了,那么就是固定宽度高度  
  25. //    self.tagView.regularWidth = 100;  
  26. //    self.tagView.regularHeight = 30;  
  27.     // 开始加载  
  28.     [self.dataSource enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOLBOOL * _Nonnull stop) {  
  29.        // 初始化标签  
  30.         SKTag *tag = [[SKTag alloc] initWithText:self.dataSource[idx]];  
  31.         // 标签相对于自己容器的上左下右的距离  
  32.         tag.padding = UIEdgeInsetsMake(315315);  
  33.         // 弧度  
  34.         tag.cornerRadius = 3.0f;  
  35.         // 字体  
  36.         tag.font = [UIFont boldSystemFontOfSize:12];  
  37.         // 边框宽度  
  38.         tag.borderWidth = 0;  
  39.         // 背景  
  40.         tag.bgColor = [UIColor colorWithRed:244/255.0 green:244/255.0 blue:244/255.0 alpha:1];  
  41.         // 边框颜色  
  42.         tag.borderColor = [UIColor colorWithRed:191/255.0 green:191/255.0 blue:191/255.0 alpha:1];  
  43.         // 字体颜色  
  44.         tag.textColor = [UIColor colorWithRed:53/255.0 green:53/255.0 blue:53/255.0 alpha:1];  
  45.         // 是否可点击  
  46.         tag.enable = YES;  
  47.         // 加入到tagView  
  48.         [self.tagView addTag:tag];  
  49.     }];  
  50.     // 点击事件回调  
  51.     self.tagView.didTapTagAtIndex = ^(NSUInteger idx){  
  52.           
  53.         NSLog(@"点击了第%ld个",idx);  
  54.           
  55.     };  
  56.       
  57.     // 获取刚才加入所有tag之后的内在高度  
  58.     CGFloat tagHeight = self.tagView.intrinsicContentSize.height;  
  59.     NSLog(@"高度%lf",tagHeight);  
  60.     // 根据已经得到的内在高度给SKTagView创建frame  
  61.     self.tagView.frame = CGRectMake(0120375, tagHeight);  
  62.     [self.tagView layoutSubviews];  
  63.     [self.view addSubview:self.tagView];  
  64. }  

最后

在UISearchBar的代理方法里面实现搜索的时候隐藏,不搜索的时候显示

[objc]  view plain  copy
  1. - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText  
  2. {  
  3.     NSLog(@"%@",searchText);  
  4.     if (searchText.length == 0) {  
  5.         // 没有文字了  
  6.         self.label.hidden = NO;  
  7.         self.tagView.hidden = NO;  
  8.     }  
  9.     else  
  10.     {  
  11.         self.label.hidden = YES;  
  12.         self.tagView.hidden = YES;  
  13.     }  
  14. }  


三步做完,一个简单的Demo就做完了,简单到爆......

下面咱们来看看如何让他在TableViewCell里面实现高度自适应的

(需要用到的库UITableView+FDTemplateLayoutCell--->传送门

Demo2

首先

用Xib做一个SKTagView的Cell



然后

不需要给SKTagView指定Frame了,约束已经做好,只要实现下面的代码就好了

[objc]  view plain  copy
  1. - (void)configCell:(MKJTagViewTableViewCell *)cell indexpath:(NSIndexPath *)indexpath  
  2. {  
  3.     [cell.tagView removeAllTags];  
  4.     cell.tagView.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width;  
  5.     cell.tagView.padding = UIEdgeInsetsMake(20202020);  
  6.     cell.tagView.lineSpacing = 20;  
  7.     cell.tagView.interitemSpacing = 30;  
  8.     cell.tagView.singleLine = NO;  
  9.     // 给出两个字段,如果给的是0,那么就是变化的,如果给的不是0,那么就是固定的  
  10.         cell.tagView.regularWidth = 80;  
  11.         cell.tagView.regularHeight = 30;  
  12.     NSArray *arr = [self.dataSource[indexpath.row] valueForKey:@"first"];  
  13.       
  14.     [arr enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOLBOOL * _Nonnull stop) {  
  15.           
  16.         SKTag *tag = [[SKTag alloc] initWithText:arr[idx]];  
  17.           
  18.         tag.font = [UIFont systemFontOfSize:12];  
  19.         tag.textColor = [UIColor colorWithRed:arc4random() % 256 / 255.0 green:arc4random() % 256 / 255.0  blue:arc4random() % 256 / 255.0  alpha:1];  
  20.         tag.bgColor =[UIColor colorWithRed:arc4random() % 256 / 255.0 green:arc4random() % 256 / 255.0  blue:arc4random() % 256 / 255.0  alpha:1];  
  21.         tag.cornerRadius = 5;  
  22.         tag.enable = YES;  
  23.         tag.padding = UIEdgeInsetsMake(510510);  
  24.         [cell.tagView addTag:tag];  
  25.     }];  
  26.       
  27.     cell.tagView.didTapTagAtIndex = ^(NSUInteger index)  
  28.     {  
  29.         NSLog(@"点击了%ld",index);  
  30.     };  
  31.       
  32. }  
  33.   
  34. - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath  
  35. {  
  36.     return [tableView fd_heightForCellWithIdentifier:identyfy configuration:^(id cell) {  
  37.          
  38.         [self configCell:cell indexpath:indexPath];  
  39.     }];  
  40. }  


差不多两个简单的Demo就介绍到这里了,再提一点东西,原作者是没有固定宽度这个属性的,没办法,自己动手丰衣足食了,我改了下源码,主要加了两个字段,默认是0,那么出来的效果就是不规则的,宽度随文字而变化,如果赋值这两个字段,那么就是固定宽高,上面已经给出了效果图

[objc]  view plain  copy
  1. @property (assign, nonatomic) CGFloat regularWidth; //!< 固定宽度  
  2. @property (nonatomic,assign ) CGFloat regularHeight; //!< 固定高度  

给BOOL属性进行复赋值

[objc]  view plain  copy
  1. @interface SKTagView ()  
  2.   
  3. @property (strongnonatomic, nullable) NSMutableArray *tags;  
  4. @property (assign, nonatomicBOOL didSetup;  
  5. @property (nonatomic,assign) BOOL isIntrinsicWidth;  //!<是否宽度固定  
  6. @property (nonatomic,assign) BOOL isIntrinsicHeight; //!<是否高度固定  
  7.   
  8. @end  
  9.   
  10. @implementation SKTagView  
  11.   
  12. // 重写setter给bool赋值  
  13. - (void)setRegularWidth:(CGFloat)intrinsicWidth  
  14. {  
  15.     if (_regularWidth != intrinsicWidth) {  
  16.         _regularWidth = intrinsicWidth;  
  17.         if (intrinsicWidth == 0) {  
  18.             self.isIntrinsicWidth = NO;  
  19.         }  
  20.         else  
  21.         {  
  22.             self.isIntrinsicWidth = YES;  
  23.         }  
  24.     }  
  25.       
  26. }  


主要在下面这个放里面引入了两个判断

CGFloat width1 = self.isIntrinsicWidth?self.regularWidth:size.width;

CGFloat height1 = self.isIntrinsicHeight?self.regularHeight:size.height;

[objc]  view plain  copy
  1. #pragma mark - Private  
  2.   
  3. - (void)layoutTags {  
  4.     if (self.didSetup || !self.tags.count) {  
  5.         return;  
  6.     }  
  7.       
  8.     NSArray *subviews = self.subviews;  
  9.     UIView *previousView = nil;  
  10.     CGFloat topPadding = self.padding.top;  
  11.     CGFloat leftPadding = self.padding.left;  
  12.     CGFloat rightPadding = self.padding.right;  
  13.     CGFloat itemSpacing = self.interitemSpacing;  
  14.     CGFloat lineSpacing = self.lineSpacing;  
  15.     CGFloat currentX = leftPadding;  
  16.       
  17.     if (!self.singleLine && self.preferredMaxLayoutWidth > 0) {  
  18.         for (UIView *view in subviews) {  
  19.             CGSize size = view.intrinsicContentSize;  
  20.             CGFloat width1 = self.isIntrinsicWidth?self.regularWidth:size.width;  
  21.             CGFloat height1 = self.isIntrinsicHeight?self.regularHeight:size.height;  
  22.             if (previousView) {  
  23. //                CGFloat width = size.width;  
  24.                 currentX += itemSpacing;  
  25.                 if (currentX + width1 + rightPadding <= self.preferredMaxLayoutWidth) {  
  26.                     view.frame = CGRectMake(currentX, CGRectGetMinY(previousView.frame), width1, height1);  
  27.                     currentX += width1;  
  28.                 } else {  
  29.                     CGFloat width = MIN(width1self.preferredMaxLayoutWidth - leftPadding - rightPadding);  
  30.                     view.frame = CGRectMake(leftPadding, CGRectGetMaxY(previousView.frame) + lineSpacing, width, height1);  
  31.                     currentX = leftPadding + width;  
  32.                 }  
  33.             } else {  
  34.                 CGFloat width = MIN(width1self.preferredMaxLayoutWidth - leftPadding - rightPadding);  
  35.                 view.frame = CGRectMake(leftPadding, topPadding, width, height1);  
  36.                 currentX += width;  
  37.             }  
  38.               
  39.             previousView = view;  
  40.         }  
  41.     } else {  
  42.         for (UIView *view in subviews) {  
  43.             CGSize size = view.intrinsicContentSize;  
  44.             view.frame = CGRectMake(currentX, topPadding, self.isIntrinsicWidth?self.regularWidth:size.widthself.isIntrinsicHeight?self.regularHeight:size.height);  
  45.             currentX += self.isIntrinsicWidth?self.regularWidth:size.width;  
  46.               
  47.             previousView = view;  
  48.         }  
  49.     }  
  50.       
  51.     self.didSetup = YES;  
  52. }  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值