我曾经遇到过一个问题:需要实现一个自定义的label(类似于UILabel),同时需要兼顾UILabel的大小自适应的特性。这个label通常宽度是固定的,通过autolayout指定其宽度约束,但不指定高度,让其根据内容自适应。

我们知道UIView的方法intrinsicContentSize可以帮助我们确定视图在autolayout下的大小,从而避免我们去设置其宽高的约束。于是我采用了这样的解决方案:将label的宽度作为其属性,使用前我必须指定label的宽度,然后label本身通过其宽度属性确定高度。然而这个方法不太方便,因为宽度有时需要我们去计算,比如说它是屏幕宽度减去某个值。然而我是一个足够懒的程序员,不想每次去手动设置宽度。

后来思路终于有了,虽然不知道这是否是最佳方法,但至少解决了问题。在autolayout布局完成后,我们就可以知道视图的最终宽度了。这时我们可以通过

invalidateIntrinsicContentSize方法重新计算视图的大小。

代码如下:

 @interface MyLabel : UIView

 @property (nonatomic, strong) UIFont *font;
@property (nonatomic, strong) NSString *text; @end
 @interface MyLabel ()

 @property (nonatomic, strong) UIFont *defaultFont;

 @end

 @implementation MyLabel

 - (instancetype)init
{
self = [super init];
if (self) {
self.defaultFont = [UIFont systemFontOfSize:];
}
return self;
} - (void)setText:(NSString *)text
{
_text = text;
[self setNeedsLayout];
[self setNeedsDisplay];
} - (void)layoutSubviews
{
[self invalidateIntrinsicContentSize]; // 在布局的时候强制重新计算大小
[super layoutSubviews];
} - (CGSize)sizeThatFits:(CGSize)size
{
UIFont *font = self.font ? self.font : self.defaultFont;
size.width = ceil(size.width); // 避免单行文本二次计算时被错误地计算为两行高度
if (size.width > ) {
return [self.text boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:font} context:nil].size;
} else { // 此处是为了兼容不设宽度的情况(单行文本)
return [self.text sizeWithAttributes:@{NSFontAttributeName:font}];
}
} - (CGSize)intrinsicContentSize
{
return [self sizeThatFits:CGSizeMake(CGRectGetWidth(self.bounds), CGFLOAT_MAX)];
} - (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize
{
return [self sizeThatFits:targetSize];
} - (void)drawRect:(CGRect)rect
{
UIFont *font = self.font ? self.font : self.defaultFont;
[self.text drawInRect:rect withAttributes:@{NSFontAttributeName:font}];
} @end

让我们来测试一下:

     MyLabel *label = [MyLabel new];
label.backgroundColor = [UIColor yellowColor];
[self.view addSubview:label];
[label mas_makeConstraints:^(MASConstraintMaker *make) { // 这里并没设高度约束
make.left.mas_equalTo();
make.top.mas_equalTo();
make.width.mas_lessThanOrEqualTo();
}]; label.text = @"this is a long text. this is a long text.";

实现一个在autolayout下有宽度约束后,自动确定高度的view的更多相关文章

  1. 【纯css】左图右文列表,左图外框宽度占一定百分比的正方形,右上下固定,右中自动响应高度。支持不规则图片。

    查看演示 <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF- ...

  2. Linux下svn提交文件后自动同步更新到网站目录

    有时,对于多文件需要上传到服务器的时候将会很麻烦,但是如果使用svn的钩子脚本就容易实现本地提交svn后,自动同步代码文件到远程服务器的网站目录下,而不必手动上传了. 首先,在网站目录下checkou ...

  3. 怎样使用AutoLayOut为UIScrollView添加约束

    1.在ViewController中拖入1个UIScrollView,并为其添加约束 约束为上下左右四边与superview对齐 2.在scrollview中,拖入1个UIView,为了便于区分将其设 ...

  4. js获取上一个月、下一个月格式为yyyy-mm-dd的日期

    /** * 获取上一个月 * * @date 格式为yyyy-mm-dd的日期,如:2014-01-25 */ function getPreMonth(date) { var arr = date. ...

  5. 第三章 用SDK编译出第一个在Linux下的软件界面

    第三章 用SDK编译出第一个在Linux下的软件界面 先创建一个工程目录“mkdir project1”,进入目录,创建main.cpp文件,编写代码如下: 代码内容暂时可以先不理解,先让程序跑起来再 ...

  6. tcl/tk实例详解——返回一个文件夹下所有文件的绝对路径

    http://blog.csdn.net/dulixin/article/details/2133840 #所有代码如下,使用注释的方式讲解脚本#修改好文件夹和保存结果路径,可以把本文件直接拷贝进tc ...

  7. js input框输入1位数字后自动跳到下一个input框聚焦

    // input框输入1位数字后自动跳到下一个input聚焦 function goNextInput(el){ var txts = document.querySelectorAll(el); f ...

  8. JavaScript一个页面中有多个audio标签,其中一个播放结束后自动播放下一个,audio连续播放

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. Python遍历一个文件夹下有几个Excel文件及每个Excel文件有几个Sheet

    一. 解决问题: 工作中常会遇到合并Excel文件的需求,Excel文件数量不确定,里面的Sheet 数量是可变的,Sheet Name是可变的,所以,需要用到遍历一个文件夹下有几个Excel文件,判 ...

随机推荐

  1. ssh login nova vm

    $ sudo cat >> /usr/bin/nova-ssh  << END FIRST=$1 IDX=`expr index $1 "@"`if [[ ...

  2. android 屏幕适配问题【转】

      如何将一个应用程序适配在不同的手机上,虽然这不算是一个技术问题,但是对于刚刚做屏幕的开发人员来说,还真不是一件多么简单的事情. 首先:你需要在AndroidManifest.xml文件的<m ...

  3. 初识Maven

    今天开始学习怎样使用maven,听起来挺神奇的东西,我们来一步一步的加以剖析. Maven的一些具体的论文的东西,网上很多博客介绍,这里我就不逐一介绍,下面我们从安装maven开始讲解: (1)Mav ...

  4. (转)130道ASP.NET面试题

    130道ASP.NET面试题 转自http://blog.csdn.net/kingmax54212008/article/details/2021204 1. 简述 private. protect ...

  5. liunx操作数据库

    liunx操作数据库 1.连接数据库 #mysql -uroot -p mysql -uroot -p 然后输入密码 2.关闭防火墙 #iptables -stop 开启#iptables -star ...

  6. c++ primer plus 习题答案(1)

    c++ primer plus 习题答案用的是第五版,IDE仍然是vs2013.我只标注了题号,具体的题目找下书上对应内容吧. p110.8 #include<iostream> #inc ...

  7. cocostudio导出plist文件

    今天在用Armature类时用到cocostudio导出文件,由于美术的原因他使用的是中文命名法(这你敢相信),后面在导入程序中跟了下代码发现是解析plist文件有误,我就来比较正常功能文件和有错文件 ...

  8. Spring学习之常用注解(转)

    使用注解来构造IoC容器 用注解来向Spring容器注册Bean.需要在applicationContext.xml中注册<context:component-scan base-package ...

  9. C++学习之使用new的注意事项

    C++学习之使用new的注意事项       在构造函数中使用new来初始化对象的指针成员成员时必须特别小心,具体的说,应该如下这样做: 一.如果在构造函数中使用new来初始化指针成员,则应该在析构函 ...

  10. jquery中的uploadfile关于图片上上传的插件的应用

    ajaxFileUpload是一个异步上传文件的jQuery插件. 传一个不知道什么版本的上来,以后不用到处找了. 语法:$.ajaxFileUpload([options]) options参数说明 ...