封装了一个iOS水平方向动态宽度layout

news2024/11/28 4:42:43

我们有时候会遇到这样的情形,就是需要展示一些动态的标签,宽度是动态的,
水平方向是一行,其实这种情况还是比较容易处理的,只是一下子想不起来,
这里做了一个相关的需求,将思路和代码记录下来,方便后续的查找
效果图
请添加图片描述

思路:就是重写自定义layout的prepare layout 方法, 在里面计算每一个item 的frame
。通过[UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:[NSIndexPath indexPathForItem:i inSection:0]] 方法创建 UICollectionViewLayoutAttributes 对象,然后个UICollectionViewLayoutAttributes 对象的frame赋值,这里要记录上一个UICollectionViewLayoutAttributes对象的x.及总的宽度。通过这句代码赋值frame
layoutAttributes.frame = CGRectMake(currentX, currentY, cellWidth, cellHeight);
然后将布局属性添加到一个数组中
在layoutAttributesForElementsInRect:方法中返回数组。
在 collectionViewContentSize 方法中返回宽度
还有一点,我们需要通过代理方式获取到单个item的宽度

  • (CGFloat)cellWidthForItemAtIndex:(NSInteger)index;

  • (CGFloat)footerWidthForFooterAtSection:(NSInteger)section;

代码

@protocol LIUNumberCenterAssociationLayoutDelegate <NSObject>

- (CGFloat)cellWidthForItemAtIndex:(NSInteger)index;

- (CGFloat)footerWidthForFooterAtSection:(NSInteger)section;

@end

@interface LIUNumberCenterAssociationLayout : UICollectionViewFlowLayout

@property (nonatomic, weak) id <LIUNumberCenterAssociationLayoutDelegate> delegate;

@end
//
//  LIUNumberCenterAssociationLayout.m
//

#import "LIUNumberCenterAssociationLayout.h"

@interface LIUNumberCenterAssociationLayout ()

@property (nonatomic, strong) NSMutableArray<UICollectionViewLayoutAttributes *> *layoutAttributesArray;

@property (nonatomic, assign) CGSize contentSize;

@end

@implementation LIUNumberCenterAssociationLayout


- (instancetype)init {
    if (self = [super init]) {
        self.layoutAttributesArray = [NSMutableArray new];
        self.contentSize = CGSizeMake(16, 22); // 16是左边距
    }
    return self;
}

- (void)prepareLayout {
    [super prepareLayout];
    [self updateLayout];
}

- (CGSize)collectionViewContentSize {
    return self.contentSize;
}

- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
    return self.layoutAttributesArray;
}

#pragma mark - ---------- update ----------

- (void)updateLayout {
    // 移除旧的布局
    [self.layoutAttributesArray removeAllObjects];
    self.contentSize = CGSizeMake(8, 28); // 16是左边距
    // 计算新的布局
    NSInteger count = 0;
    if ([self.collectionView.dataSource respondsToSelector:@selector(collectionView:numberOfItemsInSection:)]) {
        count = [self.collectionView.dataSource collectionView:self.collectionView numberOfItemsInSection:0];
    }
    CGFloat x = 0; 

    if (count > 0) {
        for (int i = 0; i < count; i++) {
            CGFloat currentX = x;
            CGFloat currentY = 0;
            CGFloat cellWidth = [self cellWidthForItemAtIndex:i];
            CGFloat cellHeight = 28;
            // 创建布局属性
            UICollectionViewLayoutAttributes *layoutAttributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:[NSIndexPath indexPathForItem:i inSection:0]];
            layoutAttributes.frame = CGRectMake(currentX, currentY, cellWidth, cellHeight);
            [self.layoutAttributesArray addObject:layoutAttributes];
            // 计算下一个item的x,以及布局更新结束检测
            if (i < count - 1) {
                x = currentX + cellWidth + 8; // 8是间距
            } else {
                x = currentX + cellWidth + 8; // 8是右边距
                self.contentSize = CGSizeMake(x, 0);
            }
        }
    }
    if ([self.delegate respondsToSelector:@selector(footerWidthForFooterAtSection:)]) {
        CGFloat footerWidth = [self.delegate footerWidthForFooterAtSection:0];
        UICollectionViewLayoutAttributes *layoutattribute = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionFooter withIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]];
        layoutattribute.frame = CGRectMake(x, 0, footerWidth, 28);
        x += footerWidth ;
        self.contentSize = CGSizeMake(x, 28);
        [self.layoutAttributesArray addObject:layoutattribute];
    }
}

- (CGFloat)cellWidthForItemAtIndex:(NSInteger)index {
    CGFloat width = 0;
    if ([self.delegate respondsToSelector:@selector(cellWidthForItemAtIndex:)]) {
        width = [self.delegate cellWidthForItemAtIndex:index];
    }
    return width;
}

@end

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2186851.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第5章 总线与微命令实验

第5章 总线与微命令实验 5.1实验目的 &#xff08;1&#xff09;理解总线的概念和作用。 &#xff08;2&#xff09;连接运算器与存储器&#xff0c;熟悉计算机的数据通路。 &#xff08;3&#xff09;理解微命令与微操作的概念。 5.2实验要求 &#xff08;1&#xff09;做…

69 BERT预训练_by《李沐:动手学深度学习v2》pytorch版

系列文章目录 文章目录 系列文章目录NLP里的迁移学习Bert的动机Bert架构对输入的修改五、预训练任务1、2、3、 六、1、2、3、 七、1、2、3、 八、1、2、3、 NLP里的迁移学习 之前是使用预训练好的模型来抽取词、句子的特征&#xff0c;例如 word2vec 或语言模型这种非深度学习…

香酥胡麻饼 一口沦陷的传统美食

&#x1f96f;美食发现 | 胡麻饼&#xff0c;一口咬出的千年韵味&#x1f96f;&#x1f60b;宝子们&#xff0c;今天我要给大家分享一款超级有历史底蕴的美食 —— 食家巷胡麻饼。 ✨食家巷胡麻饼&#xff0c;那可是有着悠久历史的传统美食。在古代&#xff0c;它就备受人们喜…

【算法】链表:160.相交链表(easy)+双指针

系列专栏 《分治》 《模拟》 《Linux》 目录 1、题目链接 2、题目介绍 3、解法&#xff08;双指针&#xff09; 返回结果 算法正确性 时间复杂度 4、代码 1、题目链接 160. 相交链表 - 力扣&#xff08;LeetCode&#xff09; 2、题目介绍 ​ 3、解法&#xff08;…

MISC -第十天(音符加解密、敲击码、NtfsStreamsEditor工具)

前言 各位师傅大家好&#xff0c;我是qmx_07&#xff0c;今天继续讲解MISC的相关知识 [MRCTF2020]你能看懂音符吗 附件信息: rar文件无法打开&#xff0c;显示损坏&#xff0c;先放到hxd查看 头标识错误&#xff0c;尝试修复 rar标识头(52 61 72 21) 压缩包里有一个d…

4个顶级的大模型推理引擎

LLM 在文本生成应用中表现出色&#xff0c;例如具有高理解度和流畅度的聊天和代码完成模型。然而&#xff0c;它们的庞大规模也给推理带来了挑战。基本推理速度很慢&#xff0c;因为 LLM 会逐个生成文本标记&#xff0c;需要对每个下一个标记进行重复调用。随着输入序列的增长&…

【游戏模组】星际争霸1代模组燃烧之地,泰伦帝国对决UED。特效华丽兵种巨多特别好玩

各位星际争霸1代的粉丝大家好&#xff0c;今天小编给大家带来一个星际争霸1代的模组&#xff0c;这个模组的名字叫燃烧之地&#xff0c;主要是2个阵营。玩家可以扮演UED或者泰伦帝国中的一个来进行比赛。 这个模组设定的世界线背景是在异虫入侵并随后被星灵消灭后&#xff0c;…

昇思MindSpore进阶教程--梯度累加

大家好&#xff0c;我是刘明&#xff0c;明志科技创始人&#xff0c;华为昇思MindSpore布道师。 技术上主攻前端开发、鸿蒙开发和AI算法研究。 努力为大家带来持续的技术分享&#xff0c;如果你也喜欢我的文章&#xff0c;就点个关注吧 正文开始 本教程介绍梯度累加的训练算法…

C(十一)scanf、getchar(第三弹)

问题引入&#xff1a;如何实现输入一串密码&#xff0c;如&#xff1a;“123 xxxx” &#xff0c;然后读取并确认&#xff0c;是 -- Y&#xff1b;否 -- N。 自然的&#xff0c;我们想到用scanf&#xff0c;但是在使用过程中你是否遇到跟我一样的困惑呢&#xff1f;如下&…

【Linux】进程管理:状态与优先级调度的深度分析

✨ 山海自有归期&#xff0c;风雨自有相逢 &#x1f30f; &#x1f4c3;个人主页&#xff1a;island1314 &#x1f525;个人专栏&#xff1a;Linux—登神长阶 ⛺️ 欢迎关注&#xff1a;&#x1f44d;点赞 &#x1…

华为技术经理总结Java技术栈思维导图

最近帮在读大四的学生做了一个java项目&#xff0c;使用Spring bootVue3做了一个机器学习在线训练和服务的平台&#xff0c;发现他的Java技术栈并不全面&#xff0c;希望在下面分享一下Java技术栈&#xff0c;能够帮助到正在参加秋招或者是准备找工作的朋友们&#xff1a; 完整…

Vue.js 组件开发知识详解

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

为什么我可以做系统架构师?

人人都可以做产品经理&#xff0c;但是却没有人随随便便成为系统架构师&#xff0c;系统架构师为什么这么稀缺&#xff0c;因为系统架构师要求的能力是十分全面的&#xff0c;首先技术基本功要非常扎实&#xff0c;其次是你的统筹能力&#xff0c;一个项目交到你手上&#xff0…

软件管理【1.10】

软件管理【1.10】 13、软件管理13.1.包管理工具rpm13.2.yum和dnf13.2.1.配置yum源13.2.2.只下载安装包,不安装13.2.3.配置本地光盘ISO文件安装13.2.4.配置阿里云epel源13.2.5.base-for-centos7.repo13.2.6.base-for-rocky8.repo13.3.搭建私有yum仓库13.3.1.Apache实现网战功能…

力扣题解 1928

题目描述&#xff08;困难&#xff09; 规定时间内到达终点的最小费用 一个国家有 n 个城市&#xff0c;城市编号为 0 到 n - 1 &#xff0c;题目保证 所有城市 都由双向道路 连接在一起 。道路由二维整数数组 edges 表示&#xff0c;其中 edges[i] [xi, yi, timei] 表示城市…

提示词工程实践

本讲义主要以text2SQL为场景进行讲解&#xff0c;包括提示词的编写和闭源模型调用、本地开源模型部署调用以及基于开源模型的微调。 回顾下大模型学习思路&#xff1a; 1. 开发环境准备 1.1 代码 代码位于【算法管理】->【公共算法】->【prompts_engineering_04】&…

leetcode每日一题day17(24.9.27)——每种字符最少取k个

思路&#xff1a;看到题目就想到了搜索&#xff0c; 广搜&#xff1a;满足要求就往后搜&#xff0c;最后返回搜索队列达到过的最大深度&#xff0c; 深搜&#xff1a;一直往一边取&#xff0c;搜索完所有可能&#xff0c;并在此基础上进行剪枝&#xff0c;剪枝方案有如果某一分…

大师级GC调优:剖析高并发系统的垃圾回收优化实战

前期准备 大家开始前一定要对VisualVM、Jmeter这两款工具有所了解&#xff01; 1. 下载安装VisualVM&#xff0c;以便后续调优分析。JDK1.8及之前所在目录的bin目录下有自带的VisualVM&#xff0c;JDK1.8以后需要自行手动安装下载。 下载地址&#xff1a;https://visualvm.git…

模型的深度优化

文章目录 一、测试模型是否正确二、图形打印直观观察三、保存训练模型四、正确率&#xff08;仅使用于分类问题&#xff09; 一、测试模型是否正确 本文承接我的上一篇文章完整网络模型训练&#xff08;一&#xff09; 运用测试数据集&#xff08;test_dataloader&#xff09;…

第二十一章 (动态内存管理)

1. 为什么要有动态内存分配 2. malloc和free 3. calloc和realloc 4. 常⻅的动态内存的错误 5. 动态内存经典笔试题分析 6. 总结C/C中程序内存区域划分 1.为什么要有动态内存管理 我们目前已经掌握的内存开辟方式有 int main() {int num 0; //开辟4个字节int arr[10] …