美文网首页
UITableView+FDTemplateLayoutCell

UITableView+FDTemplateLayoutCell

作者: KyleLou | 来源:发表于2018-04-10 10:23 被阅读38次

    <article>

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

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

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

    定的的模式,那么如果需求有固定宽高模式的[图片上传失败...(image-21f1d6-1523326930882)]

    ,老规矩,只能改源码了.

    请看图:

    [图片上传失败...(image-2cb030-1523326930882)]

    [图片上传失败...(image-fb582c-1523326930882)]

    [图片上传失败...(image-b6d96f-1523326930882)]

    传统模式:

    [图片上传失败...(image-af9122-1523326930882)]

    TableView cell模式的不规则模式和固定宽高模式:[图片上传失败...(image-1147c4-1523326930882)]

    [图片上传失败...(image-9b1050-1523326930882)]

    [图片上传失败...(image-af421a-1523326930882)]

    [图片上传失败...(image-926856-1523326930882)]

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

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

    **[图片上传失败...(image-110276-1523326930876)]

    [图片上传失败...(image-c0cfc6-1523326930876)]**

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

    SKTagView来进行布局,非常简单

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

    Demo1

    首先:

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

    [objc] view plain copy

    <embed id="ZeroClipboardMovie_1" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" name="ZeroClipboardMovie_1" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=1&width=16&height=16" wmode="transparent" width="16" height="16" align="middle">

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

    来看看效果哈

    [图片上传失败...(image-c7d32b-1523326930881)]

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

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

    [图片上传失败...(image-510a7d-1523326930885)]

    [图片上传失败...(image-31416c-1523326930885)]

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

    [图片上传失败...(image-dcdd34-1523326930875)]

    咦???这个数组里面只有个UIView么,不科学啊,要不再拨开一层看看[图片上传失败...(image-408763-1523326930872)]

    [图片上传失败...(image-6f424-1523326930875)]

    **[图片上传失败...(image-8279f8-1523326930872)]

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

    [objc] view plain copy

    <embed id="ZeroClipboardMovie_2" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" name="ZeroClipboardMovie_2" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=2&width=16&height=16" wmode="transparent" width="16" height="16" align="middle">

      • (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar{
    1. // (lldb) po self.searchBar.subviews[0].subviews

    2. // <__NSArrayM 0x7ffba1e08330>(

    3. // <UISearchBarBackground: 0x7ffba1c670e0; frame = (0 0; 360 44); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x7ffba1c201a0>>,

    4. // <UISearchBarTextField: 0x7ffba1c905b0; frame = (0 0; 0 0); text = ''; clipsToBounds = YES; opaque = NO; layer = <CALayer: 0x7ffba1c90360>>,

    5. // <UINavigationButton: 0x7ffba1c982c0; frame = (0 0; 53 30); opaque = NO; layer = <CALayer: 0x7ffba1c98800>>

    6. // )

    7. //

    8. // (lldb) po self.searchBar.subviews

    9. // <__NSArrayM 0x7ffba1e77280>(

    10. // <UIView: 0x7ffba1c8a470; frame = (0 0; 360 44); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x7ffba1c7ddc0>>

    11. // )

    12. searchBar.showsCancelButton = YES;

    13. for(UIView *view in [[[searchBar subviews] objectAtIndex:0] subviews]) {

    14. if([view isKindOfClass:[NSClassFromString(@"UINavigationButton") class]]) {

    15. UIButton * cancel =(UIButton *)view;

    16. [cancel setTitle:@"搜索" forState:UIControlStateNormal];

    17. cancel.titleLabel.font = [UIFont systemFontOfSize:14];

    18. cancel.tintColor = [UIColor redColor];

    19. }

    20. }}

    **修改完后的效果(Mac这截图效果也是醉了[图片上传失败...(image-638db2-1523326930871)]

    )**

    [图片上传失败...(image-9d3fd1-1523326930884)]

    然后

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

    [objc] view plain copy

    <embed id="ZeroClipboardMovie_3" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" name="ZeroClipboardMovie_3" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=3&width=16&height=16" wmode="transparent" width="16" height="16" align="middle">

    1. // 配置

      • (void)configTagView
    2. {

    3. self.label = [[UILabel alloc] initWithFrame:CGRectMake(10, 90, 100, 30)];

    4. self.label.textColor = [UIColor blackColor];

    5. self.label.font = [UIFont systemFontOfSize:13];

    6. self.label.text = @"历史搜索";

    7. [self.view addSubview:self.label];

    8. // 先移除掉所有

    9. [self.tagView removeAllTags];

    10. // 初始化

    11. self.tagView = [[SKTagView alloc] init];

    12. // 整个tagView对应其SuperView的上左下右距离

    13. self.tagView.padding = UIEdgeInsetsMake(10, 10, 10, 10);

    14. // 上下行之间的距离

    15. self.tagView.lineSpacing = 10;

    16. // item之间的距离

    17. self.tagView.interitemSpacing = 20;

    18. // 最大宽度

    19. self.tagView.preferredMaxLayoutWidth = 375;

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

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

    22. // 原作者没有能加固定宽度的,自己修改源码加上了固定宽度和高度,默认是0,就是标签式布局,如果实现了,那么就是固定宽度高度

    23. // self.tagView.regularWidth = 100;

    24. // self.tagView.regularHeight = 30;

    25. // 开始加载

    26. [self.dataSource enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOLBOOL * _Nonnull stop) {

    27. // 初始化标签

    28. SKTag *tag = [[SKTag alloc] initWithText:self.dataSource[idx]];

    29. // 标签相对于自己容器的上左下右的距离

    30. tag.padding = UIEdgeInsetsMake(3, 15, 3, 15);

    31. // 弧度

    32. tag.cornerRadius = 3.0f;

    33. // 字体

    34. tag.font = [UIFont boldSystemFontOfSize:12];

    35. // 边框宽度

    36. tag.borderWidth = 0;

    37. // 背景

    38. tag.bgColor = [UIColor colorWithRed:244/255.0 green:244/255.0 blue:244/255.0 alpha:1];

    39. // 边框颜色

    40. tag.borderColor = [UIColor colorWithRed:191/255.0 green:191/255.0 blue:191/255.0 alpha:1];

    41. // 字体颜色

    42. tag.textColor = [UIColor colorWithRed:53/255.0 green:53/255.0 blue:53/255.0 alpha:1];

    43. // 是否可点击

    44. tag.enable = YES;

    45. // 加入到tagView

    46. [self.tagView addTag:tag];

    47. }];

    48. // 点击事件回调

    49. self.tagView.didTapTagAtIndex = ^(NSUInteger idx){

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

    51. };

    52. // 获取刚才加入所有tag之后的内在高度

    53. CGFloat tagHeight = self.tagView.intrinsicContentSize.height;

    54. NSLog(@"高度%lf",tagHeight);

    55. // 根据已经得到的内在高度给SKTagView创建frame

    56. self.tagView.frame = CGRectMake(0, 120, 375, tagHeight);

    57. [self.tagView layoutSubviews];

    58. [self.view addSubview:self.tagView];

    59. }

    最后

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

    [objc] view plain copy

    <embed id="ZeroClipboardMovie_4" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" name="ZeroClipboardMovie_4" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=4&width=16&height=16" wmode="transparent" width="16" height="16" align="middle">

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

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

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

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

    Demo2

    首先

    用Xib做一个SKTagView的Cell

    [图片上传失败...(image-36df22-1523326930874)]

    然后

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

    [objc] view plain copy

    <embed id="ZeroClipboardMovie_5" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" name="ZeroClipboardMovie_5" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=5&width=16&height=16" wmode="transparent" width="16" height="16" align="middle">

      • (void)configCell:(MKJTagViewTableViewCell *)cell indexpath:(NSIndexPath *)indexpath
    1. {

    2. [cell.tagView removeAllTags];

    3. cell.tagView.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width;

    4. cell.tagView.padding = UIEdgeInsetsMake(20, 20, 20, 20);

    5. cell.tagView.lineSpacing = 20;

    6. cell.tagView.interitemSpacing = 30;

    7. cell.tagView.singleLine = NO;

    8. // 给出两个字段,如果给的是0,那么就是变化的,如果给的不是0,那么就是固定的

    9. cell.tagView.regularWidth = 80;

    10. cell.tagView.regularHeight = 30;

    11. NSArray *arr = [self.dataSource[indexpath.row] valueForKey:@"first"];

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

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

    14. tag.font = [UIFont systemFontOfSize:12];

    15. tag.textColor = [UIColor colorWithRed:arc4random() % 256 / 255.0 green:arc4random() % 256 / 255.0 blue:arc4random() % 256 / 255.0 alpha:1];

    16. tag.bgColor =[UIColor colorWithRed:arc4random() % 256 / 255.0 green:arc4random() % 256 / 255.0 blue:arc4random() % 256 / 255.0 alpha:1];

    17. tag.cornerRadius = 5;

    18. tag.enable = YES;

    19. tag.padding = UIEdgeInsetsMake(5, 10, 5, 10);

    20. [cell.tagView addTag:tag];

    21. }];

    22. cell.tagView.didTapTagAtIndex = ^(NSUInteger index)

    23. {

    24. NSLog(@"点击了%ld",index);

    25. };

    26. }

      • (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    27. {

    28. return [tableView fd_heightForCellWithIdentifier:identyfy configuration:^(id cell) {

    29. [self configCell:cell indexpath:indexPath];

    30. }];

    31. }

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

    [objc] view plain copy

    <embed id="ZeroClipboardMovie_6" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" name="ZeroClipboardMovie_6" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=6&width=16&height=16" wmode="transparent" width="16" height="16" align="middle">

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

    给BOOL属性进行复赋值

    [objc] view plain copy

    <embed id="ZeroClipboardMovie_7" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" name="ZeroClipboardMovie_7" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=7&width=16&height=16" wmode="transparent" width="16" height="16" align="middle">

    1. @interface SKTagView ()

    2. @property (strong, nonatomic, nullable) NSMutableArray *tags;

    3. @property (assign, nonatomic) BOOL didSetup;

    4. @property (nonatomic,assign) BOOL isIntrinsicWidth; //!<是否宽度固定

    5. @property (nonatomic,assign) BOOL isIntrinsicHeight; //!<是否高度固定

    6. @end

    7. @implementation SKTagView

    8. // 重写setter给bool赋值

      • (void)setRegularWidth:(CGFloat)intrinsicWidth
    9. {

    10. if (_regularWidth != intrinsicWidth) {

    11. _regularWidth = intrinsicWidth;

    12. if (intrinsicWidth == 0) {

    13. self.isIntrinsicWidth = NO;

    14. }

    15. else

    16. {

    17. self.isIntrinsicWidth = YES;

    18. }

    19. }

    20. }

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

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

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

    [objc] view plain copy

    <embed id="ZeroClipboardMovie_8" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" name="ZeroClipboardMovie_8" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=8&width=16&height=16" wmode="transparent" width="16" height="16" align="middle">

    1. pragma mark - Private

      • (void)layoutTags {
    2. if (self.didSetup || !self.tags.count) {

    3. return;

    4. }

    5. NSArray *subviews = self.subviews;

    6. UIView *previousView = nil;

    7. CGFloat topPadding = self.padding.top;

    8. CGFloat leftPadding = self.padding.left;

    9. CGFloat rightPadding = self.padding.right;

    10. CGFloat itemSpacing = self.interitemSpacing;

    11. CGFloat lineSpacing = self.lineSpacing;

    12. CGFloat currentX = leftPadding;

    13. if (!self.singleLine && self.preferredMaxLayoutWidth > 0) {

    14. for (UIView *view in subviews) {

    15. CGSize size = view.intrinsicContentSize;

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

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

    18. if (previousView) {

    19. // CGFloat width = size.width;

    20. currentX += itemSpacing;

    21. if (currentX + width1 + rightPadding <= self.preferredMaxLayoutWidth) {

    22. view.frame = CGRectMake(currentX, CGRectGetMinY(previousView.frame), width1, height1);

    23. currentX += width1;

    24. } else {

    25. CGFloat width = MIN(width1, self.preferredMaxLayoutWidth - leftPadding - rightPadding);

    26. view.frame = CGRectMake(leftPadding, CGRectGetMaxY(previousView.frame) + lineSpacing, width, height1);

    27. currentX = leftPadding + width;

    28. }

    29. } else {

    30. CGFloat width = MIN(width1, self.preferredMaxLayoutWidth - leftPadding - rightPadding);

    31. view.frame = CGRectMake(leftPadding, topPadding, width, height1);

    32. currentX += width;

    33. }

    34. previousView = view;

    35. }

    36. } else {

    37. for (UIView *view in subviews) {

    38. CGSize size = view.intrinsicContentSize;

    39. view.frame = CGRectMake(currentX, topPadding, self.isIntrinsicWidth?self.regularWidth:size.width, self.isIntrinsicHeight?self.regularHeight:size.height);

    40. currentX += self.isIntrinsicWidth?self.regularWidth:size.width;

    41. previousView = view;

    42. }

    43. }

    44. self.didSetup = YES;

    45. }

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

    OVER~~~~~~ 安静 安静 安静 安静 安静 安静

    [图片上传失败...(image-a1d648-1523326930876)]

    </article>

    版权声明:本文为博主原创文章,未经博主允许不得转载。转载请Email我....... https://blog.csdn.net/Deft_MKJing/article/details/51722157

    相关文章

      网友评论

          本文标题:UITableView+FDTemplateLayoutCell

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