iOS 主流搜索界面下的Tag标签布局框架,各种样式任君挑选,包您满意(SKTagView)

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

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

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

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

请看图:

传统模式:

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

   

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

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

   

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

SKTagView来进行布局,非常简单

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

Demo1

首先:

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

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    UIView *titleView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 375, 44)];
    titleView.backgroundColor = [UIColor clearColor];
    self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 360, 44)];
    self.searchBar.delegate = self;
    self.searchBar.placeholder = @"请输入要搜索的文字";
//    self.searchBar.showsCancelButton = YES;
    // 键盘确认按钮的名字
    self.searchBar.returnKeyType = UIReturnKeyNext;
    // 把默认灰色背景浮层给去掉
    self.searchBar.backgroundColor = [UIColor clearColor];
    self.searchBar.backgroundImage = [UIImage new];
    UITextField *searBarTextField = [self.searchBar valueForKey:@"_searchField"];
    if (searBarTextField)
    {
        [searBarTextField setBackgroundColor:[UIColor colorWithRed:243/255.0 green:243/255.0 blue:243/255.0 alpha:1]];
        searBarTextField.borderStyle = UITextBorderStyleRoundedRect;
        searBarTextField.layer.cornerRadius = 5.0f;
    }
    else
    {
        // 通过颜色画一个Image出来
        UIImage *image = [UIImage imageWithColor:[UIColor colorWithRed:243/255.0 green:243/255.0 blue:243/255.0 alpha:1] forSize:CGSizeMake(28, 28)];
        [self.searchBar setSearchFieldBackgroundImage:image forState:UIControlStateNormal];
    }
    [titleView addSubview:self.searchBar];
    self.navigationItem.titleView = titleView;
    [self.searchBar becomeFirstResponder];
    [self configTagView];
}

来看看效果哈

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

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

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

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

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

- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar{
//    (lldb) po self.searchBar.subviews[0].subviews
//    <__NSArrayM 0x7ffba1e08330>(
//                                <UISearchBarBackground: 0x7ffba1c670e0; frame = (0 0; 360 44); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x7ffba1c201a0>>,
//                                <UISearchBarTextField: 0x7ffba1c905b0; frame = (0 0; 0 0); text = ''; clipsToBounds = YES; opaque = NO; layer = <CALayer: 0x7ffba1c90360>>,
//                                <UINavigationButton: 0x7ffba1c982c0; frame = (0 0; 53 30); opaque = NO; layer = <CALayer: 0x7ffba1c98800>>
//                                )

//
//    (lldb) po self.searchBar.subviews
//    <__NSArrayM 0x7ffba1e77280>(
//                                <UIView: 0x7ffba1c8a470; frame = (0 0; 360 44); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x7ffba1c7ddc0>>
//                                )
    searchBar.showsCancelButton = YES;
    for(UIView *view in  [[[searchBar subviews] objectAtIndex:0] subviews]) {
        if([view isKindOfClass:[NSClassFromString(@"UINavigationButton") class]]) {
            UIButton * cancel =(UIButton *)view;
            [cancel setTitle:@"搜索" forState:UIControlStateNormal];
            cancel.titleLabel.font = [UIFont systemFontOfSize:14];
            cancel.tintColor = [UIColor redColor];
        }
    }}

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

然后

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

// 配置
- (void)configTagView
{
    self.label = [[UILabel alloc] initWithFrame:CGRectMake(10, 90, 100, 30)];
    self.label.textColor = [UIColor blackColor];
    self.label.font = [UIFont systemFontOfSize:13];
    self.label.text = @"历史搜索";
    [self.view addSubview:self.label];

    // 先移除掉所有
    [self.tagView removeAllTags];
    // 初始化
    self.tagView = [[SKTagView alloc] init];
    // 整个tagView对应其SuperView的上左下右距离
    self.tagView.padding = UIEdgeInsetsMake(10, 10, 10, 10);
    // 上下行之间的距离
    self.tagView.lineSpacing = 10;
    // item之间的距离
    self.tagView.interitemSpacing = 20;
    // 最大宽度
    self.tagView.preferredMaxLayoutWidth = 375;
//    @property (assign, nonatomic) CGFloat regularWidth; //!< 固定宽度
//    @property (nonatomic,assign ) CGFloat regularHeight; //!< 固定高度
    // 原作者没有能加固定宽度的,自己修改源码加上了固定宽度和高度,默认是0,就是标签式布局,如果实现了,那么就是固定宽度高度
//    self.tagView.regularWidth = 100;
//    self.tagView.regularHeight = 30;
    // 开始加载
    [self.dataSource enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
       // 初始化标签
        SKTag *tag = [[SKTag alloc] initWithText:self.dataSource[idx]];
        // 标签相对于自己容器的上左下右的距离
        tag.padding = UIEdgeInsetsMake(3, 15, 3, 15);
        // 弧度
        tag.cornerRadius = 3.0f;
        // 字体
        tag.font = [UIFont boldSystemFontOfSize:12];
        // 边框宽度
        tag.borderWidth = 0;
        // 背景
        tag.bgColor = [UIColor colorWithRed:244/255.0 green:244/255.0 blue:244/255.0 alpha:1];
        // 边框颜色
        tag.borderColor = [UIColor colorWithRed:191/255.0 green:191/255.0 blue:191/255.0 alpha:1];
        // 字体颜色
        tag.textColor = [UIColor colorWithRed:53/255.0 green:53/255.0 blue:53/255.0 alpha:1];
        // 是否可点击
        tag.enable = YES;
        // 加入到tagView
        [self.tagView addTag:tag];
    }];
    // 点击事件回调
    self.tagView.didTapTagAtIndex = ^(NSUInteger idx){

        NSLog(@"点击了第%ld个",idx);

    };

    // 获取刚才加入所有tag之后的内在高度
    CGFloat tagHeight = self.tagView.intrinsicContentSize.height;
    NSLog(@"高度%lf",tagHeight);
    // 根据已经得到的内在高度给SKTagView创建frame
    self.tagView.frame = CGRectMake(0, 120, 375, tagHeight);
    [self.tagView layoutSubviews];
    [self.view addSubview:self.tagView];
}

最后

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

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
    NSLog(@"%@",searchText);
    if (searchText.length == 0) {
        // 没有文字了
        self.label.hidden = NO;
        self.tagView.hidden = NO;
    }
    else
    {
        self.label.hidden = YES;
        self.tagView.hidden = YES;
    }
}

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

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

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

Demo2

首先

用Xib做一个SKTagView的Cell

然后

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

- (void)configCell:(MKJTagViewTableViewCell *)cell indexpath:(NSIndexPath *)indexpath
{
    [cell.tagView removeAllTags];
    cell.tagView.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width;
    cell.tagView.padding = UIEdgeInsetsMake(20, 20, 20, 20);
    cell.tagView.lineSpacing = 20;
    cell.tagView.interitemSpacing = 30;
    cell.tagView.singleLine = NO;
    // 给出两个字段,如果给的是0,那么就是变化的,如果给的不是0,那么就是固定的
        cell.tagView.regularWidth = 80;
        cell.tagView.regularHeight = 30;
    NSArray *arr = [self.dataSource[indexpath.row] valueForKey:@"first"];

    [arr enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {

        SKTag *tag = [[SKTag alloc] initWithText:arr[idx]];

        tag.font = [UIFont systemFontOfSize:12];
        tag.textColor = [UIColor colorWithRed:arc4random() % 256 / 255.0 green:arc4random() % 256 / 255.0  blue:arc4random() % 256 / 255.0  alpha:1];
        tag.bgColor =[UIColor colorWithRed:arc4random() % 256 / 255.0 green:arc4random() % 256 / 255.0  blue:arc4random() % 256 / 255.0  alpha:1];
        tag.cornerRadius = 5;
        tag.enable = YES;
        tag.padding = UIEdgeInsetsMake(5, 10, 5, 10);
        [cell.tagView addTag:tag];
    }];

    cell.tagView.didTapTagAtIndex = ^(NSUInteger index)
    {
        NSLog(@"点击了%ld",index);
    };

}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return [tableView fd_heightForCellWithIdentifier:identyfy configuration:^(id cell) {

        [self configCell:cell indexpath:indexPath];
    }];
}

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

@property (assign, nonatomic) CGFloat regularWidth; //!< 固定宽度
@property (nonatomic,assign ) CGFloat regularHeight; //!< 固定高度

给BOOL属性进行复赋值

@interface SKTagView ()

@property (strong, nonatomic, nullable) NSMutableArray *tags;
@property (assign, nonatomic) BOOL didSetup;
@property (nonatomic,assign) BOOL isIntrinsicWidth;  //!<是否宽度固定
@property (nonatomic,assign) BOOL isIntrinsicHeight; //!<是否高度固定

@end

@implementation SKTagView

// 重写setter给bool赋值
- (void)setRegularWidth:(CGFloat)intrinsicWidth
{
    if (_regularWidth != intrinsicWidth) {
        _regularWidth = intrinsicWidth;
        if (intrinsicWidth == 0) {
            self.isIntrinsicWidth = NO;
        }
        else
        {
            self.isIntrinsicWidth = YES;
        }
    }

}

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

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

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

#pragma mark - Private

- (void)layoutTags {
    if (self.didSetup || !self.tags.count) {
        return;
    }

    NSArray *subviews = self.subviews;
    UIView *previousView = nil;
    CGFloat topPadding = self.padding.top;
    CGFloat leftPadding = self.padding.left;
    CGFloat rightPadding = self.padding.right;
    CGFloat itemSpacing = self.interitemSpacing;
    CGFloat lineSpacing = self.lineSpacing;
    CGFloat currentX = leftPadding;

    if (!self.singleLine && self.preferredMaxLayoutWidth > 0) {
        for (UIView *view in subviews) {
            CGSize size = view.intrinsicContentSize;
            CGFloat width1 = self.isIntrinsicWidth?self.regularWidth:size.width;
            CGFloat height1 = self.isIntrinsicHeight?self.regularHeight:size.height;
            if (previousView) {
//                CGFloat width = size.width;
                currentX += itemSpacing;
                if (currentX + width1 + rightPadding <= self.preferredMaxLayoutWidth) {
                    view.frame = CGRectMake(currentX, CGRectGetMinY(previousView.frame), width1, height1);
                    currentX += width1;
                } else {
                    CGFloat width = MIN(width1, self.preferredMaxLayoutWidth - leftPadding - rightPadding);
                    view.frame = CGRectMake(leftPadding, CGRectGetMaxY(previousView.frame) + lineSpacing, width, height1);
                    currentX = leftPadding + width;
                }
            } else {
                CGFloat width = MIN(width1, self.preferredMaxLayoutWidth - leftPadding - rightPadding);
                view.frame = CGRectMake(leftPadding, topPadding, width, height1);
                currentX += width;
            }

            previousView = view;
        }
    } else {
        for (UIView *view in subviews) {
            CGSize size = view.intrinsicContentSize;
            view.frame = CGRectMake(currentX, topPadding, self.isIntrinsicWidth?self.regularWidth:size.width, self.isIntrinsicHeight?self.regularHeight:size.height);
            currentX += self.isIntrinsicWidth?self.regularWidth:size.width;

            previousView = view;
        }
    }

    self.didSetup = YES;
}

介绍完啦,各位还需要细看的请点击传送门跑起来看看,不早啦,各位晚安~~~~~~

OVER~~~~~~

时间: 2024-10-22 00:15:34

iOS 主流搜索界面下的Tag标签布局框架,各种样式任君挑选,包您满意(SKTagView)的相关文章

iOS快速集成搜索界面下拉菜单框架

前言 这次推出的控件,比较常用,搜索界面下拉菜单,如果喜欢我的文章,可以关注我微博:吖了个峥,也可以来小码哥,了解下我们的iOS培训课程.后续还会更新更多内容,有任何问题,欢迎简书留言峥吖... Demo效果: 效果图.gif Demo演示: 1.创建下拉菜单 YZPullDownMenu *menu = [[YZPullDownMenu alloc] init]; menu.frame = CGRectMake(0, 20, YZScreenW, 44); [self.view addSubv

iOS之iPhone手机通讯录和短信搜索界面的实现以及UISearchController和UISearchDisplayController的浅析

本来觉得这个模块也就是一个SearchBar就搞定了,但是现在的产品经理也是够了,一会儿一个想法,之前的搜索 都已经写完了,类似主流的电商,好像也没那么麻烦,但是改版了总得弄点什么吧.嘿,哥们,我现在要iphone手机 通讯录里面搜索的样式,你搞定哦......,要一毛一样哦.作为一个文化人,我只能在内心深处生 出表达出,苦逼的我们顶多发发牢骚,要改就改喽. 请看图先 这是他要的效果demo 下面是我写的demo 看到这效果,应该都能想到用UISearchController,但是这货是iOS8

IOS嵌套界面下 -UIWebView加载网页显示不全(尺寸适应问题)

最近有个朋友碰到一个关于在嵌套界面下UIWebView加载网页显示不全的问题 咋一看这种问题太easy了.但是不要忽视其背后的真正黑手,现在拿百度首页做个实验(百度就是这点好)先贴上一小段核心代码: 显示效果: 看到没 显示不全.现在你会说快用大招: 解决它.可惜这招也不行. 原因分析:为什么会显示不全呢? 主要问题就出在前面说的关于在嵌套界面下. 可为什么在嵌套界面下就不行呢? 显示不全是个问题. 是的 是个问题而且是个显示界面尺寸不匹配的问题.可在主界面就这可以, 而且frame我都是用的s

转////iOS 8 Auto Layout界面自动布局系列1-自动布局的基本原理

iOS 8 Auto Layout界面自动布局系列1-自动布局的基本原理 http://blog.csdn.net/pucker/article/details/41832939 标签: iosinterface苹果布局界面 2014-12-10 00:25 11286人阅读 评论(2) 收藏 举报  分类: iOS开发(19)  版权声明:本文为博主原创文章,未经博主允许不得转载. 苹果今年如约放出了新的iPhone 6与iOS 8系统,SDK针对新的设备和系统的界面适配也进行了若干改进,因此

git tag — 标签相关操作

git tag — 标签相关操作 发表于 2011年06月29日 由 机器猫 标签可以针对某一时间点的版本做标记,常用于版本发布. 列出标签 $ Git tag # 在控制台打印出当前仓库的所有标签$ git tag -l ‘v0.1.*’ # 搜索符合模式的标签 打标签 git标签分为两种类型:轻量标签和附注标签.轻量标签是指向提交对象的引用,附注标签则是仓库中的一个独立对象.建议使用附注标签.# 创建轻量标签$ git tag v0.1.2-light # 创建附注标签$ git tag -

[转载]git tag — 标签相关操作

git tag — 标签相关操作 发表于 2011年06月29日 由 机器猫 标签可以针对某一时间点的版本做标记,常用于版本发布. 列出标签 $ Git tag # 在控制台打印出当前仓库的所有标签 $ git tag -l ‘v0.1.*’ # 搜索符合模式的标签 打标签 git标签分为两种类型:轻量标签和附注标签.轻量标签是指向提交对象的引用,附注标签则是仓库中的一个独立对象.建议使用附注标签. # 创建轻量标签 $ git tag v0.1.2-light # 创建附注标签 $ git t

Discuz tag 标签重复显示的解决方法

最近论坛遇到个问题,Discuz tag标签出了问题,编辑一次就添加一个标签,如下图:<ignore_js_op> 删都删不掉,看着真TM不爽,于是,想到了解决办法,如下:Discuz帖子下方的tag标签重复显示,表现为相同的tag标签多次显示,帖子编辑次数越多,tag重复的次数越多.Discuz!官方直到Discuz X3.2也没有解决tag重复的问题.要解决Discuz标签重复,可以通过修改source\module\forum\forum_viewthread.php来实现.用notep

iOS interface guidelines (界面设计指南)&lt;一&gt;

一.      为iOS而设计 1.iOS体现的主题: (1)Deference(顺从):UI的存在就是为了让顾客更加容易理解和进行交互,而不是要和顾客玩智力游戏 (2)Clarity(清晰):在每个尺寸中都能清晰的显示文字,表达精确和图像清晰的图标,装饰物要合适且搭配自然,设计的功能要击中一点,表达明确          (3)Depth(深度):生动的视觉和真实的感情能够让界面充满生气,也可以提高用户的兴趣和使用户更加容易理解 无论你是想要重新设计旧app的界面还是创造一个,你都需要考虑下面

dedecms发布文章时添加的tag标签消失了,无法添加!

今天依旧织梦刚把网站上传上来,调试完成后,想先更新几篇文章的.结果,在发文章的时候出现了一个问题:那就是我的tag标签一个都没有显示出来.刚编辑好的tag标签,文章一保存就消失了,而且tag标签管理里面也是空的.由于是头一次遇到,所以就在网上找相关的织梦教程来解决.发现很有多的朋友都遇到了这个问题,比如"我用织梦CMS做网站,但是修改文章的时候改TAG标签,修改并保存之后TAG标签就消失了,怎么都无法添加!","dede我添加了TAG,怎么在Tag标签管理里找不到呢?&quo