iOS开发笔记 | 自定义具有内边距的label

作者: 无夜之星辰 | 来源:发表于2017-12-07 17:19 被阅读811次
iu

前言

UIScrollViewcontentInset这个属性,但是UILabel没有;Android有,iOS没有。

最近需要用到带内边距的label,所以就结合网上前辈的代码封装了一个,本来我是想弄一个category的,但最终失败了。

代码如下,继承自UILabel

.h文件:

#import <UIKit/UIKit.h>

@interface EdgeInsetsLabel : UILabel

@property (nonatomic) UIEdgeInsets contentInset;

@end

.m文件:

#import "EdgeInsetsLabel.h"

@implementation EdgeInsetsLabel

- (void)setContentInset:(UIEdgeInsets)contentInset {
    _contentInset = contentInset;
    NSString *tempString = self.text;
    self.text = @"";
    self.text = tempString;
}

-(void)drawTextInRect:(CGRect)rect {
    [super drawTextInRect:UIEdgeInsetsInsetRect(rect, self.contentInset)];
}

@end

使用

self.label.contentInset = UIEdgeInsetsMake(0, 20, 0, 20);

代码说明

改变label的inset是在这个方法里面进行的:

-(void)drawTextInRect:(CGRect)rect {
    [super drawTextInRect:UIEdgeInsetsInsetRect(rect, self.contentInset)];
}

这是系统提供的方法:


这个方法不能主动调用,但我们又需要在这个方法中做处理,怎么办?

我实验了一下,改变label的text的时候会回调这个方法

也就是说,我们可以通过改变label的text的方式来间接调用这个方法

所以就有了这段奇葩的赋值contentInset的代码:

- (void)setContentInset:(UIEdgeInsets)contentInset {
    _contentInset = contentInset;
    NSString *tempString = self.text;
    self.text = @"";
    self.text = tempString;
}

先将label文本清空,再重新赋值text,从而达到改变label的text的效果,最终回调drawTextInRect:方法。

社会社会

这样我们给label赋值contentInset的时候就能立即看到效果了。

效果GIF:

效果.gif

对应的代码:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    self.label = [[EdgeInsetsLabel alloc] initWithFrame:CGRectMake(90, 90, 200, 100)];
    [self.view addSubview:self.label];
    self.label.text = @"人之初,性本善,我最喜欢吃鸡蛋。人之初,性本善,我最喜欢吃鸡蛋。人之初,性本善,我最喜欢吃鸡蛋。人之初,性本善,我最喜欢吃鸡蛋。";
    self.label.numberOfLines = 0;
    self.label.backgroundColor = [UIColor orangeColor];
    self.label.contentInset = UIEdgeInsetsMake(0, 20, 0, 20);
    
    // 3秒后改变contentInset
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        self.label.contentInset = UIEdgeInsetsMake(20, 50, 10, 20);
    });
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    self.label.contentInset = UIEdgeInsetsMake(0, 80, 0, 20);
    self.label.text = @"因缺思厅";
}

demo

点击获取DEMO

最后

如果你有更好的方法不要吝惜分享啊。


2017年12月28日更新

根据评论区neghao同学的建议,要调用drawTextInRect这个方法可以通过调用UILabelsetNeedsDisplay方法来实现。

所以赋值contentInset就可以改成这样了:

- (void)setContentInset:(UIEdgeInsets)contentInset {
    _contentInset = contentInset;
    
    [self setNeedsDisplay];
}

代码已更新到GitHub。

感谢大家的建议。

相关文章

网友评论

  • Alan龙马:无法换行
  • Hynsen:用该方法使用xib创建label 自动换行无效呢
  • nenhall:你不用重设text,调用setNeedsDisplay会自动调用drawRect
    无夜之星辰:@neghao 你这招可以,学习了:sunglasses:
  • ForKid:个人感觉用一个ScrollView用来做一个label有点浪费了,可以用一个textLayer作为子layer来处理
  • Haha_kd:drawTextInRect setneedlayout 相关的方法可以立即刷新,不用重新赋值
    无夜之星辰:不行,这两个方法都不能立即触发drawTextInRect
  • CepheusSun:kuaishifu is kuaishifu
  • 37e4dd6ddc60:kuaishifu is kuaishifu
  • moonCoder:kuaishifu is kuaishifu

本文标题:iOS开发笔记 | 自定义具有内边距的label

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