iOS文本佈局探討之三——使用TextKit框架進行富文本佈局

iOS文本佈局探討之三——使用TextKit框架進行富文本佈局

1、引言

        關於圖文混排,其實之前的博客已經討論不少,在實際開發中,常常使用第三方的框架來完成排版的需求,其中RCLabel和RTLabel是兩個比較好用的第三方庫,他們的實現都是基於UIView的,經過更底層的CoreText相關API來進行圖文處理。相關介紹博客地址以下:數組

iOS中支持HTML標籤渲染的MDHTMLLaebl:http://my.oschina.net/u/2340880/blog/703254網絡

擴展於RCLabel的支持異步加載網絡圖片的富文本引擎的設計:http://my.oschina.net/u/2340880/blog/499311app

iOS開發封裝一個能夠響應超連接的label——基於RCLabel的交互擴展:http://my.oschina.net/u/2340880/blog/550194框架

2、原生UILabel真的只能渲染文字麼?

        CoreText是一個比較底層且十分強大的文本渲染框架,可是其使用起來並非十分方便。在較低版本的iOS系統中,要進行富文本排版十分困難。在iOS6中,系統爲UILabel,UITextView等這類文本渲染控件引入了NSAttributedString屬性,有了NSAttributedString這個類,建立靈活多彩的文本控件變得十分輕鬆,開發者只須要配置NSAttributedString屬性字符串便可。可是要進行圖文混排,依然比較困難。iOS7以後引入TextKit框架,就完美的解決了圖文混排這樣的問題。異步

        首先,iOS7中新添加了一類NSTextAttachment,從類名理解它是一個文本附件,其實也正是如此,NSTextAttachment類能夠向文本中添加一些附件,這有些向郵件系統,寄信者能夠向郵件中添加附件一同發送出去。NSTextAttachment類並不直接參與富文本的渲染與佈局,渲染和佈局依然由NSAttributedString類來完成,NSAttributedString類中提供了方法將NSTextAttachment所描述的內容轉換爲NSAttributedString示例。以一個簡單的圖文混排爲例:佈局

- (void)viewDidLoad {
    [super viewDidLoad];
    //進行NSTextAttachment的建立
    NSTextAttachment * attach = [[NSTextAttachment  alloc]init];
    //設置顯示的圖片
    attach.image =[UIImage imageNamed:@"image"];
    //設置尺寸
    attach.bounds = CGRectMake(0, 0, 120, 60);
    NSTextAttachment * attach2 = [[NSTextAttachment  alloc]init];
    attach2.image =[UIImage imageNamed:@"image2"];
    attach2.bounds = CGRectMake(0, 0, 100, 90);
    //建立文本NSAttributedString對象
    NSMutableAttributedString * attri = [[NSMutableAttributedString alloc]initWithString:@"Describes a dictionary that fully specifies a font.... UIFontDescriptorInherits From NSObject UIFontDescriptor NSObject UIFontDescriptor Conforms To CVarArgT... 這裏是中文"];
    //將NSTextAttachment映射爲NSAttributedString對象
    NSMutableAttributedString * att = [[NSMutableAttributedString alloc]initWithAttributedString:[NSAttributedString attributedStringWithAttachment:attach]];
    //將圖片插入NSAttributedString中
    [attri insertAttributedString:att atIndex:15];
    [attri insertAttributedString:[NSAttributedString attributedStringWithAttachment:attach2] atIndex:130];
    UILabel * label = [[UILabel alloc]initWithFrame:CGRectMake(20, 20, 280, 540)];
    label.backgroundColor = [UIColor grayColor];
    label.numberOfLines = 0;
    label.attributedText = attri;
    [self.view addSubview:label];
}

運行工程後,效果以下圖所示,其實只使用UILabel也能夠實現複雜的富文本和圖文混排:url

3、爲富文本附件添加用戶交互能力

        TextKit框架強大到只使用UILabel就能夠完成複雜的富文本佈局,可是UILabel有一個致命的缺陷,其沒法進行用戶交互。試想,若是能夠向一段文本中添加任意數據類型的文件,當用戶點擊這個文件時,能夠獲取到文件數據並進行業務邏輯處理,這將十分酷。這樣富文本佈局其實就不僅侷限於圖文混排了,咱們能夠插入音頻,插入視頻,甚至插入任意自定義格式的數據。結合使用NSTextAttachment與UITextView,這些都能實現。先看NSTextAttachment類中的一些經常使用屬性與方法:spa

//這個初始化方法用於建立攜帶任意數據的文本附件
- (instancetype)initWithData:(nullable NSData *)contentData ofType:(nullable NSString *)uti NS_DESIGNATED_INITIALIZER NS_AVAILABLE(10_11, 7_0);
//攜帶的數據內容
@property(nullable, copy, NS_NONATOMIC_IOSONLY) NSData *contents NS_AVAILABLE(10_11, 7_0);
//數據類型
@property(nullable, copy, NS_NONATOMIC_IOSONLY) NSString *fileType NS_AVAILABLE(10_11, 7_0);

//設置渲染的圖片 須要注意 若是設置的這個 附件攜帶的數據 fileWrapper目錄內容將無效
@property(nullable, strong, NS_NONATOMIC_IOSONLY) UIImage *image NS_AVAILABLE(10_11, 7_0);
//設置圖片渲染的尺寸
@property(NS_NONATOMIC_IOSONLY) CGRect bounds NS_AVAILABLE(10_11, 7_0);

//設置附件攜帶的文件目錄 須要注意 若是設置了這個屬性 image和data將無效
@property(nullable, strong, NS_NONATOMIC_IOSONLY) NSFileWrapper *fileWrapper;

結合UITextView能夠爲NSAttributedString屬性字符串添加超連接,在代碼回調中監聽此超連接的回調能夠獲取NSTextAttachment攜帶的附件內容,如此就能夠自由的進行業務處理了,示例代碼以下:.net

- (void)viewDidLoad {
    [super viewDidLoad];
    //保留一個數組存放附件
    _attArray = [NSMutableArray array];
    //建立附件數據
    NSData * stringData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"image3" ofType:@"gif"]];
    NSTextAttachment * attach = [[NSTextAttachment  alloc]initWithData:stringData ofType:@"gif"];
    [_attArray addObject:attach];
    attach.bounds = CGRectMake(0, 0, 30, 40);
    NSMutableAttributedString * attri = [[NSMutableAttributedString alloc]initWithString:@"Describes a dictionary that fully specifies a font.... UIFontDescriptorInherits From NSObject UIFontDescriptor NSObject UIFontDescriptor Conforms To CVarArgT... 這裏是中文"];
    NSMutableAttributedString * att = [[NSMutableAttributedString alloc]initWithAttributedString:[NSAttributedString attributedStringWithAttachment:attach]];
    //爲NSTextAttachment轉換爲的NSAttributedString添加超連接
    [att addAttributes:@{NSLinkAttributeName:@"url..."} range:NSMakeRange(0, att.string.length)];
    [attri insertAttributedString:att atIndex:15];
    UITextView * textView = [[UITextView alloc]initWithFrame:CGRectMake(20, 20, 280, 540)];
    textView.backgroundColor = [UIColor grayColor];
    textView.dataDetectorTypes = UIDataDetectorTypeLink;
    textView.delegate =self;
    textView.attributedText = attri;
    textView.editable =    NO;
    [self.view addSubview:textView];
}

實現以下的TextView代理方法:設計

-(BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange{
    //能夠獲取到url 進行匹配
    NSLog(@"%@",URL);
    //取出NSTextAttachment附件
    NSTextAttachment * attach =_attArray.firstObject;
    NSLog(@"%@--",attach.contents);
    return YES;
}

向文本中添加任意數據的NSTextAttachment會展示一個文件的圖標,以下圖所示:

當用戶點擊文件圖標時,會將攜帶的gif文件數據進行打印。

 

專一技術,熱愛生活,交流技術,也作朋友。

——琿少 QQ羣:203317592

相關文章
相關標籤/搜索