美文网首页ios开发进阶iOS学习程序员
UILabel 实现竖排展示的几种方法

UILabel 实现竖排展示的几种方法

作者: JasonLee宸 | 来源:发表于2017-10-23 14:11 被阅读173次

    前言

    平时使用UILabel 的时候,默认都是横排排列。
    现在需要竖排排列,暂时想到以下三种方法,大家可以留言补充。
    实现效果:

    image.png

    1.\n 添加换行符号

    遍历字符串,在每一个字符后面添加\n
    此处,就直接在字符后写\n,上述代码自行脑补,嘿嘿。

    [lab setNumberOfLines:0];
    [lab setText:@"不\n忘\n初\n心\n,\n方\n得\n始\n终\n。"];
    

    2.设置label 合适的宽度和长度,自动换行

     UILabel *lab = [[UILabel alloc]initWithFrame:CGRectMake(12, 100, 16, 200)];
     [lab setNumberOfLines:0];
     [lab setText:@"不忘初心,方得始终。"];
     [lab setTextColor:[UIColor redColor]];
     [lab setTextAlignment:NSTextAlignmentCenter];
     [lab setFont:[UIFont systemFontOfSize:15.0f]];
     [self.view addSubview:lab];
    

    这种方法比较取巧,姑且算一种方法吧。

    3.NSVerticalGlyphFormAttributeName

    你一定会在网上看到kCTVerticalFormsAttributeName,现在使用NSAttributedStringKey 对应到是上述方法。但是,不看注释的后果是,这个方法试了好久,不管用!!!

    image.png

    Currently on iOS, it's always horizontal 在iOS上,总是水平的。

        NSMutableAttributedString *aa = [[NSMutableAttributedString alloc]initWithString:@"不忘初心,方得始终。"];
        [aa addAttribute:(id)NSShadowAttributeName value:shadow range:NSMakeRange(0, [aa length])];
        NSNumber *num = [NSNumber numberWithInteger:1];
        [aa addAttribute:(id)NSVerticalGlyphFormAttributeName value:num range:NSMakeRange(0, [aa length])];
        [lab setAttributedText:aa];
    

    所以,即使设置了这个属性,也不起作用。pass!

    3.draw

    此处我们可以使用CoreText绘制富文本,CoreText的主要作用是用于文字的排版和渲染,如果我们需要将文本内容直接渲染到图形上下文(Graphics context)时,从性能和易用性来考虑,最佳方案就是使用CoreText。
    对于CoreText 不了解的,可以先阅读下面文章:
    CoreText实现图文混排

    汉字的竖排排列

    #import "VerticalGlyphLabel.h"
    #import <CoreText/CoreText.h>
    
    @implementation VerticalGlyphLabel
    
    - (void)drawRect:(CGRect)rect{
        [super drawRect:rect];
        CGContextRef context = UIGraphicsGetCurrentContext();//获取当前绘制上下文
        CGContextSetTextMatrix(context, CGAffineTransformIdentity);//设置字形的变换矩阵为不做图形变换
        CGContextTranslateCTM(context, 0, self.bounds.size.height);//平移方法,将画布向上平移一个屏幕高
        CGContextScaleCTM(context, 1.0, -1.0);//缩放方法,x轴缩放系数为1,则不变,y轴缩放系数为-1,则相当于以x轴为轴旋转180度
    
        NSMutableAttributedString * attributeStr = [[NSMutableAttributedString alloc] initWithString:@"我是一个富文本"];
        [attributeStr setAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:15.0f]} range:NSMakeRange(0, [attributeStr length])];
    
        CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attributeStr);//一个frame的工厂,负责生成frame
        CGMutablePathRef path = CGPathCreateMutable();//创建绘制区域
        CGPathAddRect(path, NULL, CGRectMake(0, 0, 20, self.bounds.size.height ));//添加绘制尺寸
        NSInteger length = attributeStr.length;
        CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0,length), path, NULL);//工厂根据绘制区域及富文本(可选范围,多次设置)设置frame
        CTFrameDraw(frame, context);//根据frame绘制文字
    
        CFRelease(frame);
        CFRelease(path);
        CFRelease(frameSetter);    
    }
    

    上述方法其实和方法2类似,CGPathAddRect(path, NULL, CGRectMake(0, 0, 20, self.bounds.size.height ));添加绘制的尺寸,此处设置文字宽度和整体高度,就可以实现竖排的效果。

    还有一种方法是在stackoverflow 的评论中看到的
    using CoreText (to get glyphs) and CoreGraphics (to draw CGGlyphs)

        NSMutableAttributedString * attributeStr = [[NSMutableAttributedString alloc] initWithString:@"this is a text" attributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:11.0f]}];
        CGPoint location =  CGPointMake(20, 20);
        UIFont *font = [[attributeStr attributesAtIndex:0 effectiveRange:NULL] objectForKey:NSFontAttributeName];
        NSUInteger myLength = [attributeStr length];
        
        CTFontRef ctfont = CTFontCreateWithName((CFStringRef)[font fontName], [font pointSize], NULL);
        
        CGGlyph *glyphs = malloc(sizeof(CGGlyph) * myLength);
        UniChar *characters = malloc(sizeof(UniChar) * myLength);
        CGSize *advances = malloc(sizeof(CGSize) * myLength);
        
        [[attributeStr string] getCharacters:characters range:NSMakeRange(0,myLength)];
        
        CTFontGetGlyphsForCharacters(ctfont, characters, glyphs, myLength);
        CTFontGetAdvancesForGlyphs(ctfont, kCTFontOrientationHorizontal, glyphs, advances, myLength);
        
        free(characters);
        
        CGContextRef ctx = UIGraphicsGetCurrentContext();
        
        CGFontRef cgfont = CTFontCopyGraphicsFont(ctfont, NULL);
        
        CGContextSetFont(ctx, cgfont);
        CGContextSetFontSize(ctx, CTFontGetSize(ctfont));
        
        CGAffineTransform textMatrix = CGAffineTransformMakeTranslation(location.x, location.y);
        textMatrix = CGAffineTransformScale(textMatrix, 1, -1);
        
        CGContextSetTextMatrix(ctx, textMatrix);
        
        CGFloat lineHeight = CTFontGetAscent(ctfont) + CTFontGetDescent(ctfont) + CTFontGetLeading(ctfont);
        location.y = -CTFontGetAscent(ctfont);
        
        CGFloat maxAdvance = 0.;
        
        NSUInteger i;
        for (i = 0; i < myLength; i++)
            maxAdvance = MAX(maxAdvance, advances[i].width);
        
        for (i = 0; i < myLength; i++)
        {
            location.x = (maxAdvance - advances[i].width) * 0.5;
            
            CGContextShowGlyphsAtPositions(ctx, &glyphs[i], &location, 1);
            location.y -= lineHeight;
        }
        
        free(glyphs);
        free(advances);
        CGFontRelease(cgfont);
        CFRelease(ctfont);
    

    其中需要CGGlyph数组。意思是你需要自己把unichar字符自已映射成字体文件中的Glyph。
    如果需要使用汉字,此种方法是不行的,需要定制字体,关于字体定制请看
    iOS 定制应用程序字体
    后面两种方法都比较复杂,在此处有些小题大作了。

    以上方法如有不正之处,请指出,谢谢。

    相关文章

      网友评论

        本文标题:UILabel 实现竖排展示的几种方法

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