ios实践之Label 字间距、行间距、两端对齐、分行显示

UILabel算是iOS里使用最多的控件了吧,下面来说说它特殊的应用需求吧

一、设置字间距、行间距

这是一个比较常见的需求了

写一个UILabel的分类

@interface UILabel (extension)
/**
 *  设置字间距
 */

-(void)setColumnSpace:(CGFloat)columnSpace;
 /**
 *  设置行距
 */

- (void)setRowSpace:(CGFloat)rowSpace;

@end
#import "UILabel+extension.h"
#import <CoreText/CoreText.h>

@implementation UILabel (extension)

- (void)setColumnSpace:(CGFloat)columnSpace
{
    NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithAttributedString:self.attributedText];
    //调整间距
    [attributedString addAttribute:(__bridge NSString *)kCTKernAttributeName value:@(columnSpace) range:NSMakeRange(0, [attributedString length])];
    self.attributedText = attributedString;
}

- (void)setRowSpace:(CGFloat)rowSpace
{
    self.numberOfLines = 0;
    NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithAttributedString:self.attributedText];
    //调整行距
    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
    paragraphStyle.lineSpacing = rowSpace;
    paragraphStyle.baseWritingDirection = NSWritingDirectionLeftToRight;
    [attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [self.text length])];
    self.attributedText = attributedString;
}

@end

然后再重写UILabel

@interface RDNewLabel : UILabel
@property (nonatomic, assign) float charactSpace; //字间距
@property (nonatomic, assign) float lineSpace; //行间距

+ (CGFloat)textHeight:(NSString *)text width:(CGFloat)labelWidth font:(UIFont *)font charactSpace:(CGFloat)charactSpace LineSpace:(CGFloat)lineSpace numberLines:(NSInteger)numberLines;
(CGFloat)textWidth:(NSString *)text height:(CGFloat)labelHeight font:(UIFont *)font charactSpace:(CGFloat)charactSpace LineSpace:(CGFloat)lineSpace;

#define CharactSpacing  0.4 //字间距
#define LinesSpacing     4.0 //行间距

@implementation RDNewLabel

- (void)setText:(NSString *)text{
    [super setText:text];
   //默认字间距为0.4
    if (_charactSpace==0) {
         [self setColumnSpace:CharactSpacing];
    }else{
        [self setColumnSpace:_charactSpace];
    }
    //默认行间距为4.0,当设置0.01时则不设置行间距
    if (_lineSpace == 0) {
        [self setRowSpace:LinesSpacing];
    }else{
        if (_lineSpace <= 0.01) {
            
        }else{
             [self setRowSpace:_lineSpace];
        }
       
   }
}
+ (CGFloat)textHeight:(NSString *)text width:(CGFloat)labelWidth font:(UIFont *)font charactSpace:(CGFloat)charactSpace LineSpace:(CGFloat)lineSpace numberLines:(NSInteger)numberLines{
    CGFloat textHeight = 0;
    RDNewLabel *label = [RDNewLabel new];
    label.font = font;
    if (charactSpace == 0) {
        charactSpace = CharactSpacing;
    }
    label.charactSpace = charactSpace;
    if (lineSpace == 0) {
        lineSpace = LinesSpacing;
    }
    label.lineSpace = lineSpace;
    label.text = text;
    label.numberOfLines = numberLines;
    textHeight = [label sizeThatFits:CGSizeMake(labelWidth, MAXFLOAT)].height;
    return textHeight;
}

+ (CGFloat)textWidth:(NSString *)text height:(CGFloat)labelHeight font:(UIFont *)font charactSpace:(CGFloat)charactSpace LineSpace:(CGFloat)lineSpace{
    CGFloat textWidth = 0;
    RDNewLabel *label = [RDNewLabel new];
    label.font = font;
    if (charactSpace == 0) {
        charactSpace = CharactSpacing;
    }
    label.charactSpace = charactSpace;
    if (lineSpace == 0) {
        lineSpace = LinesSpacing;
    }
    label.lineSpace = lineSpace;
    label.text = text;
    label.numberOfLines = 0;
    textWidth = [label sizeThatFits:CGSizeMake(MAXFLOAT, labelHeight)].width;
    return textWidth;
}

二、Label 两端对齐

很多情况我们会遇到这样的需求,要求Label文字两端对齐。
使用UILabel的NSTextAlignment设置两端对齐并不是达到效果,而使用UILabel的attributedText确实可以实现两端对齐。
重写UILabel的setText方法

@implementation ALLabel

- (void)setText:(NSString *)text{

    NSMutableAttributedString *attributedStr = [[NSMutableAttributedString alloc]initWithString:text];
    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc]init];
    paragraphStyle.alignment = NSTextAlignmentJustified;//设置两端对齐
    [attributedStr setAttributes:@{NSParagraphStyleAttributeName:paragraphStyle,NSFontAttributeName:self.font,NSUnderlineStyleAttributeName:[NSNumber numberWithInteger:NSUnderlineStyleNone]} range:NSMakeRange(0, attributedStr.length)];
   
    [self setAttributedText:attributedStr];
}

初始化一个ALLabel 
@property (weak, nonatomic) IBOutlet ALLabel *label;

NSString* msg = @"壬戌之秋,七月既望,苏子与客泛舟游于赤壁之下。清风《赤壁赋》文徵明书徐来,水波不兴。举酒属(zhǔ)客,诵明月之诗,歌窈窕之章。少(shǎo) 焉,月出于东山之上,徘徊于斗(dǒu)牛之间。白露横江,水光接天。纵一苇之所如,凌万顷之茫然。浩浩乎如冯 (píng) 虚御风,而不知其所止;飘飘乎如遗世独立,羽化而登仙。”

 _label.text = msg;

计算label自适应高度还是一样

CGSize   resultSize = [msg boundingRectWithSize:size options:NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesFontLeading | NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: [UIFont systemFontOfSize:fontSize]} context:nil].size

三、分行显示

也许我们会遇到类似需求:本来多行的文字,却首先只显示两行,最二行末尾处放置一个“查看更多”的按钮,点击查看更多按钮则全部显示。

思路:
1、设置一个lines为0的allTextLabel;
2、放置一个lines为1的firstLineLabel,top、left、right和allTextLabel对齐;
3、放置一个lines也为1的secondLineLabel,left与firstLineLabel对齐,top与firstLineLabel的bottom间距为0,right与“查看更多按钮”的间距为0;
4、放置一个“查看更多”的按钮moreTextButton,right与firstLineLabel对齐,top与firstLineLabel的bottom间距为0,宽度固定

@property (weak, nonatomic) IBOutlet UILabel *allTextLabel;
@property (weak, nonatomic) IBOutlet UILabel *firstLineLabel;
@property (weak, nonatomic) IBOutlet UILabel *secondLineLabel;
@property (weak, nonatomic) IBOutlet UIButton *moreTextButton;

根据文字内容和宽度返回一个以行数line为索引的数组

#import <CoreText/CoreText.h>
- (NSArray *)getSeparatedLinesFromLabelText:(NSString  *)text font:(UIFont *)font width:(CGFloat)width
{
    
    CTFontRef myFont = CTFontCreateWithName((__bridge CFStringRef)([font fontName]), [font pointSize], NULL);
    NSMutableAttributedString *attStr = [[NSMutableAttributedString alloc] initWithString:text];
    [attStr addAttribute:(NSString *)kCTFontAttributeName value:(__bridge id)myFont range:NSMakeRange(0, attStr.length)];
    
    CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attStr);
    
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathAddRect(path, NULL, CGRectMake(0,0,width,MAXFLOAT));
    
    CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), path, NULL);
    
    NSArray *lines = (__bridge NSArray *)CTFrameGetLines(frame);
    NSMutableArray *linesArray = [[NSMutableArray alloc]init];
    
    for (id line in lines)
    {
        CTLineRef lineRef = (__bridge CTLineRef )line;
        CFRange lineRange = CTLineGetStringRange(lineRef);
        NSRange range = NSMakeRange(lineRange.location, lineRange.length);
        
        NSString *lineString = [text substringWithRange:range];
        [linesArray addObject:lineString];
    }
    return linesArray;
    
}

接下来就是赋值了

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
NSString * msg = @"土地是以它的肥沃和收获而被估价的;才能也是土地,不过它生产的不是粮食,而是真理。如果只能滋生瞑想和幻想的话,即使再大的才能也只是砂地或盐池,那上面连小草也长不出来的
    _allTextLabel.hidden = TRUE;
    CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;
    _textLines = [self getSeparatedLinesFromLabelText:msg font:[UIFont systemFontOfSize:15] width:screenWidth-90];
    _firstLineLabel.text = _textLines[0];
    _secondLineLabel.text = _textLines[1];
}

点击查看更多按钮,其实就是赋值后隐藏firstLineLabel和secondLineLabel

- (IBAction)onClickShowMoreText:(id)sender {
    
    _allTextLabel.text = msg ;
    _allTextLabel.hidden = FALSE;
    _firstLineLabel.hidden = TRUE;
    _secondLineLabel.hidden = TRUE;
    _moreTextButton.hidden = TRUE;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容