close
当前位置: 物联网在线 > 技术文库 > ios >

iOS实现多个可变cell复杂界面的制作

在日常的开发中,有时会遇到内容块比较多,且又可变的界面:

iOS实现多个可变cell复杂界面的制作

这个界面中有些内容块是固定出现的,比如最上面的商品详情图片、商品名称、价格等。而有些内容块则是不一定出现的,比如促销(显然不是每个商品都有促销)、已选规格(有的商品没有规格)、店铺信息(有的商品属于自营,就没有店铺)等。还有些内容要根据情况进行变化,比如评论,这里最多列出4条评论,如果没有评论,则显示“暂无评论”且不显示“查看所有评论”按钮。

对于这样的界面,相信很多人第一感觉会用TableView来做,因为中间要列出评论内容,这个用TableView的cell来填充比较合适。但如何处理评论内容之外的其他内容呢?我之前的做法是,评论内容之上的用HeaderView做,下面的用FooterView做,虽然最终实现了功能,但做起来十分麻烦。布局我是用Auto Layout来做的,由于Auto Layout本身的特点,代码中就涉及很多判断处理。比如“已选规格”块,最开始的是有一个和“促销”内容块的顶部间距约束,但“促销”内容块不一定会有,就得根据情况,调整“已选规格”块本身的约束(例如让其顶部间距约束指向“价格”内容块)。同样,“促销”内容块本身也需要类似的处理,如果没有“促销”时,要隐藏自己,而隐藏自己最简单的办法,就是将自己的高度约束设置为0(因为它还有底部到“已选规格”的间距约束,不能随意将自身移除,否则“已选规格”相关的约束得再进行调整)。

此外,还有一个麻烦的问题。界面刚进来的时候,是需要请求网络数据,这时界面就要显示成一个初始状态,而显然初始状态有些内容块是不应该显示的,比如促销,只有完成了数据请求,才能知道是否有促销,有的话才显示促销内容;比如评论,初始时应该显示成“暂无评论”,数据请求完成后,才显示相应的内容。这样,我们需要处理初始进入和数据请求完成两种状态下各个内容块的显示,十分复杂繁琐。

总结来说,用TableView的 HeaderView + 评论内容cell + FooterView + Auto Layout 的方式会带来如下问题:

约束本身需要依赖其他View的,而所依赖的View又是可变的内容块,会导致约束需要繁琐的判断修改增删

需要处理初始进入和数据请求完成两种状态的界面展示,使代码更加复杂繁琐

需要额外计算相应内容的高度,以更新HeaderView、FooterView的高度

可见,这种方式并不是理想的解决方案。可能有人会说,那不要用Auto Layout,直接操作frame来布局就好,这样或许能减少一些麻烦,但总体上并没有减少复杂度。也有人说,直接用ScrollView来做,这样的话,所有的内容包括评论内容的cell,都得自己手动拼接,可以想象这种做法也是比较麻烦的。所以,我们得另辟蹊径,使用其他方法来达到目的。下面就为大家介绍一种比较简便的做法,这种做法也是一个前同事分享给我的,我就借花献佛,分享给大家。

我们还是用TableView来做这个界面,和之前不同的是,我们把每一个可变内容块做成一个独立的cell,cell的粒度可以自行控制,比如可以用一个cell囊括商品图片、标题、副标题、价格,也可以拆得更细,图片、标题、副标题、价格都各自对应一个cell。这里我们选择后者,因为图片内容块,我们需要按屏幕宽度等比例拉伸;标题、副标题的文字内容可能是一行,也可能是两行,高度可变,用单独的cell来控制会更简单明了。

下面先定义好各种类型的cell:

//基础cell,这里为了演示简便,定义这个cell,其他cell继承自这个cell    @interface MultipleVariantBasicTableViewCell : UITableViewCell    @property (nonatomic, weak) UILabel *titleTextLabel;    @end         //滚动图片    @interface CycleImagesTableViewCell : MultipleVariantBasicTableViewCell    @end         //正标题    @interface MainTitleTableViewCell : MultipleVariantBasicTableViewCell    @end         //副标题    @interface SubTitleTableViewCell : MultipleVariantBasicTableViewCell    @end         //价格    @interface PriceTableViewCell : MultipleVariantBasicTableViewCell    @end         // ...其他内容块的cell声明              // 各种内容块cell的实现,这里为了演示简便,cell中就只放了一个Label    @implementation MultipleVariantBasicTableViewCell         - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {        self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];        if (self) {            UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];            label.numberOfLines = 0;            [self.contentView addSubview:label];            self.titleTextLabel = label;        }        return self;    }         @end         @implementation CycleImagesTableViewCell    @end         @implementation MainTitleTableViewCell    @end         // ...其他内容块的cell实现         // 评论内容cell使用Auto Layout,配合iOS 8 TableView的自动算高,实现内容自适应    @implementation CommentContentTableViewCell         - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {        self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];        if (self) {            self.titleTextLabel.translatesAutoresizingMaskIntoConstraints = NO;            self.titleTextLabel.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 8;            NSLayoutConstraint *leftConstraint = [NSLayoutConstraint constraintWithItem:self.titleTextLabel attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeLeading multiplier:1.0f constant:4.0f];            NSLayoutConstraint *rightConstraint = [NSLayoutConstraint constraintWithItem:self.titleTextLabel attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTrailing multiplier:1.0f constant:-4.0f];            NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:self.titleTextLabel attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTop multiplier:1.0f constant:4.0f];            NSLayoutConstraint *bottomConstraint = [NSLayoutConstraint constraintWithItem:self.titleTextLabel attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeBottom multiplier:1.0f constant:-4.0f];            [self.contentView addConstraints:@[leftConstraint, rightConstraint, topConstraint, bottomConstraint]];        }        return self;    }         @end 
(责任编辑:ioter)

用户喜欢...

在智能手机上实现 1 Gbps RF 前端的简单方法

有人可能会问,我们为什么需要 1 Gbps 的下载速度?当前的下载速度还不够快吗?让我们面对现实吧:我们都讨厌看到手机上旋转的缓冲符号,而且我们总是想要更多数据。运营商也希望用户有...


实现5G新型无线电大规模MIMO系统

大规模MIMO依赖于使用大量天线,是实现必要改进的关键技术,以证明从4G到5G无线网络的演进是合理的。 正在定义第五代(5G)无线接入网络,以满足2020年及以后的容量需求的持续增长,并解决...


应用最新的CAN总线增强功能,实现安全可靠的高速汽车通信

设计人员多年来一直依赖控制器局域网(CAN)来实现汽车各子系统和电子控制单元(ECU)之间的可靠通信。然而,随着机载网络节点的数量增加,所需的数据吞吐量以及对更低延迟和更高级安...


射频收发器在数字波束合成相控阵中实现强制杂散去相关性

在大型数字波束合成天线中,人们非常希望通过组合来自分布式波形发生器和接收器的信号这一波束合成过程改善动态范围。如果关联误差项不相关,则可以在噪声和杂散性能方面使动态范围提...


生成多个5G NR同步信号块(SSB)以形成同步信号突发(SS突发)

该示例示出了如何生成同步信号块(SSB)并生成多个SSB以形成同步信号突发(SS突发)。形成同步信号块(主要和辅助同步信号,物理广播信道)的信道和信号被创建并映射到表示该块的矩阵中...


为什么以及如何使用串行外设接口来简化多个设备之间的连接

嵌入式系统可使用一个或多个处理器或微控制器,在更复杂的系统中执行专用操作。这些嵌入式控制器需要与其他系统元件、传感器甚至其他控制器进行通信。虽然复杂的串行接口和协议很常见...


在不需要大量使用资源的情况下为HMI实现带来新的维度

十多年前,iPhone的推出预示着我们日常生活中几个关键要素的大变革。这些改变游戏规则的手机将在我们如何立即与技术互动方面发挥关键作用 - 即通过使用触摸。虽然触摸屏在此之前已经存在...


使用微控制器的功能,在紧凑设计中快速实现模拟信号链

许多针对物联网 (IoT) 的设计都依靠模拟电路,以便满足应用对传感器和致动器的信号调节、电流控制和其他功能的独特要求。虽然专用的信号链 IC 可以满足这种需求,但是成本和空间严格受限...


合成可变电路内Rs,Ls和Cs

电压放大器的输入和输出之间连接的阻抗反映在放大器输入阻抗中,与放大器增益成比例地缩放。 虽然第一次看作仅限于不希望的寄生电容倍增器限制带宽和稳定性,但米勒效应也已被纳入有...


模拟器件继续实现高效电机控制的无传感器矢量控制技术

基于使用磁显着性的空间显着性跟踪的技术适用于零速操作并且使得可以在没有参数影响的情况下估计初始转子位置。对于初始转子位置,主要有两种基于脉冲信号注入或正弦载波信号注入的基...