UILabel 的 preferredMaxLayoutWidth 属性研究

来源:互联网 发布:动漫周边淘宝 编辑:程序博客网 时间:2024/06/13 00:44

下面这张图对于有强迫症的 iOS 开发应该并不陌生,只要 xib 中将 UILabel 的 numberOfLines 设置为非 1(0或2,3…)并且没有在 xib 中设置 preferredMaxLayoutWidth 就会出现该警告。

这里写图片描述

消除该警告,有两种比较常见的方法

  1. 在 xib 中把相应 Label 的 numberOfLines 先设置为 1,再到代码中初始化的地方设置 numberOfLines 为自己想要的非 1 值。
  2. 在 xib 中把相应 Label 的 preferredMaxLayoutWidth 设置为 0,如下图所示:
    这里写图片描述

那么问题来了,上面第二中方法把 preferredMaxLayoutWidth 设置为 0 会不会有什么影响呢?

  • 首先看下苹果文档中对 UILabel 的 preferredMaxLayoutWidth 属性的说明

这里写图片描述

  • 于是自己创建了测试工程看下这个属性具体会影响到哪些地方
    • 1.对于 numberOfLines 为 1 的 UILabel,根据上面的文档说明这个属性没有什么作用。
    • 2.对于 numberOfLines 为非 1(0或2,3…)的 UILabel,下面再细分两种情况:
      • (1).如果 xib 中没有足够的约束确定 UILabel 的宽度,则会用 preferredMaxLayoutWidth 决定其最大的隐式宽度,文字内容不足 preferredMaxLayoutWidth 宽度,则隐式宽度约束为文字所需的宽度;如果超过 preferredMaxLayoutWidth 宽度则会换行(注意一下,如果 preferredMaxLayoutWidth 为 0 则永远不会换行)。调用其父视图(或者父视图的父视图)的 [superView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize] 方法计算其父视图最小宽高时,就会用 preferredMaxLayoutWidth 作为换行宽度计算其中的 numberOfLines 非 1 的 UILabel 需要的高度(正常的换行符也会马上换行)(注意一下,如果 preferredMaxLayoutWidth 为 0 则永远不会换行,需要的高度就是一行需要的高度),然后一层层根据相对约束确定 superView 需要的最小宽高。对 UILabel 的 sizeThatFits: 方法没有任何影响。
      • (2).如果 xib 中已经有足够的约束确定 UILabel 的宽度,则不会再用 preferredMaxLayoutWidth preferredMaxLayoutWidth 决定换行,而是用约束确定的宽度去决定换行(如果 preferredMaxLayoutWidth 为 0 则更不会影响)。调用其父视图(或者父视图的父视图)的 [superView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize] 方法计算其父视图最小宽高时,依然会使用 preferredMaxLayoutWidth 作为换行宽度计算其中的 numberOfLines 非 1 的 UILabel 需要的高度(正常的换行符也会马上换行)(注意一下,如果 preferredMaxLayoutWidth 为 0 则继续用约束确定的宽度作为换行换行宽度计算所需高度),然后一层层根据相对约束确定 superView 需要的最小宽高。对 UILabel 的 sizeThatFits: 方法没有任何影响。

经过研究,暂时没有发现上面的第二种修改方法(xib 把 preferredMaxLayoutWidth 设置为 0)会产生什么不好的影响。

但是把 preferredMaxLayoutWidth 设置为非 0 对于上面的2-(2)里面的情况就有非常大的影响了,我们常用的 UITableView+FDTemplateLayoutCell 动态计算 Cell 高度中就用了 systemLayoutSizeFittingSize: 方法。

最后贴一段 UITableView+FDTemplateLayoutCell 中先用 systemLayoutSizeFittingSize: 方法计算高度的代码。

    if (!cell.fd_enforceFrameLayout && contentViewWidth > 0) {        // Add a hard width constraint to make dynamic content views (like labels) expand vertically instead        // of growing horizontally, in a flow-layout manner.        NSLayoutConstraint *widthFenceConstraint = [NSLayoutConstraint constraintWithItem:cell.contentView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:contentViewWidth];        // [bug fix] after iOS 10.3, Auto Layout engine will add an additional 0 width constraint onto cell's content view, to avoid that, we add constraints to content view's left, right, top and bottom.        static BOOL isSystemVersionEqualOrGreaterThen10_2 = NO;        static dispatch_once_t onceToken;        dispatch_once(&onceToken, ^{            isSystemVersionEqualOrGreaterThen10_2 = [UIDevice.currentDevice.systemVersion compare:@"10.2" options:NSNumericSearch] != NSOrderedAscending;        });        NSArray<NSLayoutConstraint *> *edgeConstraints;        if (isSystemVersionEqualOrGreaterThen10_2) {            // To avoid confilicts, make width constraint softer than required (1000)            widthFenceConstraint.priority = UILayoutPriorityRequired - 1;            // Build edge constraints            NSLayoutConstraint *leftConstraint = [NSLayoutConstraint constraintWithItem:cell.contentView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:cell attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0];            NSLayoutConstraint *rightConstraint = [NSLayoutConstraint constraintWithItem:cell.contentView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:cell attribute:NSLayoutAttributeRight multiplier:1.0 constant:accessroyWidth];            NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:cell.contentView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:cell attribute:NSLayoutAttributeTop multiplier:1.0 constant:0];            NSLayoutConstraint *bottomConstraint = [NSLayoutConstraint constraintWithItem:cell.contentView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:cell attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0];            edgeConstraints = @[leftConstraint, rightConstraint, topConstraint, bottomConstraint];            [cell addConstraints:edgeConstraints];        }        [cell.contentView addConstraint:widthFenceConstraint];        // Auto layout engine does its math        fittingHeight = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;        // Clean-ups        [cell.contentView removeConstraint:widthFenceConstraint];        if (isSystemVersionEqualOrGreaterThen10_2) {            [cell removeConstraints:edgeConstraints];        }        [self fd_debugLog:[NSString stringWithFormat:@"calculate using system fitting size (AutoLayout) - %@", @(fittingHeight)]];    }
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 文件变成快捷方式打不开怎么办 ai文件打不开了怎么办 电脑下载了病毒软件怎么办 打嗝停不下来怎么办 咳嗽停不下来怎么办 电动机停不下来怎么办 电脑所有程序都打不开怎么办 机顶盒画面卡顿怎么办 电脑画面卡顿怎么办 鞋舌头跑偏怎么办 球球大作战老卡怎么办 孩子被打却不敢还手怎么办? 自卫砍伤了人怎么办 系统还原节点黑屏了怎么办 我惹事了要被打怎么办 诛仙宠物太多怎么办 笔记本玩lolfps低怎么办 lol延迟有42怎么办 软件安装后黑屏怎么办 汽车脚垫翘边怎么办 晴季寿司会员怎么办 理财产品跑路了怎么办 宝宝足跟血异常怎么办 孩子足跟血异常怎么办 打印机显示用户干预怎么办 打印机脱机状态怎么办win10 电脑打印机显示脱机怎么办 佳能打印机显示脱机怎么办 汽车说明书丢了怎么办 oppo手机刷机后内存不足怎么办 电脑运行太慢怎么办 台式电脑卡慢怎么办 touch炫舞不记得区怎么办 产能过剩是带怎么办 裸辞找不到工作怎么办 30岁找不到工作怎么办 20岁找不到工作怎么办 年轻人一直找不到工作怎么办 经济不好的时候怎么办 dnf86没任务了怎么办 dnf打团队友开挂怎么办