无限互联iOS开发(脱产班)的教程分为四个阶段,历时四个月,从基础的Objective-C开始,由浅入深、循序渐进,让实习生在接受iPhone培训的同时,结合名企的iOS项目开发,成为一名技术过硬、受企业欢迎的iPhone软件开发工程师。
上课时间:周一到周五 总: 664课时 Demo: 80个左右 项目:三个
第一阶段:objective c语言基础和高级
第二阶段:iPhone UI基础和项目一
第三阶段: iPhone UI高级和项目二
第四阶段:App策划设计与大型项目三
第二篇:【无限互联】iOS开发之图文混排研究
【无限互联】ios开发之图文混排研究
本节要点:
1.理解图文混排的概念。
2.研究FTCoreText框架的实现原理。
3.演示使用FTCoreText框架实现图文混排的demo,以及效果图。
图文混排的概念
● 在view上显示的数据既包括文本数据,也包括图片数据。
● 图片的大小可以不同,图片和文字的排列顺序不固定。
● 文本数据的字体、颜色、背景等其他属性可以不同。
● 文本数据中还可以包含超链接。可以点击超链接进入其他页面。
研究FTCoreText框架的实现原理
1>.此框架的功能 和 缺陷
1.1> 功能:此框架能够实现不同风格的文本数据、图片数据的混合显示,还可以设置超链接。
1.2> 缺陷:此框架里面的文本的处理只针对与XML或者HTML格式的数据。(比如这种标签类型的数据:<title>Giraffe</title>)对于JSON格式的数据,可能需要自己修改内部一些方法的实现。
2>.此框架的基本构成
2.1> 此框架有两个类组成,分别是FTCoreTextStyle类、FTCoreTextView类。
2.2> FTCoreTextStyle类主要是用于设置格式的,定义了一些属性和方法。通过这个类就可以定义一种格式。
2.3> FTCoreTextView这个类是此框架的核心类。这个类里面定义了一个私有的类
FTCoreTextNode。需要处理的数据中,每一个标签(<title>Giraffe</title>)对应一个节点。节点类里面就封装了一些节点的属性和方法,供FTCoreTextView这个类使用。
2.4> FTCoreTextView这个类主要封装了对数据的处理、绘制图片和文本,其中包含了很多处理细节的方法。
3>.FTCoreText框架内部具体的实现原理
3.1>FTCoreTextStyle类的主要实现 FTCoreTextStyle类封装的一些重要的属性: [objc] view plaincopyprint?
1. <span style="color:#993399;">@property (nonatomic) NSString *name; //格式的
名称
2. @property (nonatomic) NSString *appendedCharacter; //追加的字符串
3. @property (nonatomic) UIFont *font; //字体
4. @property (nonatomic) UIColor *color; //颜色
5. @property (nonatomic, getter=isUnderLined) BOOL underlined; //下划线 6. @property (nonatomic) FTCoreTextAlignement textAlignment; //文字显示位置 7. @property (nonatomic) UIEdgeInsets paragraphInset; //段落之间的间隔 8. @property (nonatomic) CGFloat leading;
9. @property (nonatomic) CGFloat maxLineHeight; //最大行高
10. @property (nonatomic) CGFloat minLineHeight; //最小行高
11. // bullet 格式
12. @property (nonatomic) NSString *bulletCharacter; //设置bullet字符
13. @property (nonatomic) UIFont *bulletFont; // 设置bullet字体
14. @property (nonatomic) UIColor *bulletColor; //设置bullet颜色
15. //当格式被解析时,回调的block
16. @property (nonatomic, copy) FTCoreTextCallbackBlock block;
17. @property (nonatomic, assign) BOOL applyParagraphStyling; //段落格式
</span>
FTCoreTextStyle类封装的一些重要的方法: [objc] view plaincopyprint?
1. <span style="color:#006600;">//初始化方法
2. - (id)init
3. {
4. self = [super init];
5. if (self) {
6. self.name = @"_default";
7. self.bulletCharacter = @"?";
8. self.appendedCharacter = @"";
9. self.font = [UIFont systemFontOfSize:12];
10. self.color = [UIColor blackColor];
11. self.underlined = NO;
12. self.textAlignment = FTCoreTextAlignementLeft;
13. self.maxLineHeight = 0;
14. self.minLineHeight = 0;
15. self.paragraphInset = UIEdgeInsetsZero;
16. self.applyParagraphStyling = YES;
17. self.leading = 0;
18. self.block=nil;
19. }
20. return self;
21. }</span>
[objc] view plaincopyprint?
1. <span style="color:#006600;">//类方法,通过name来定义一种格式 2. + (id)styleWithName:(NSString *)name
3. {
4. FTCoreTextStyle *style = [[FTCoreTextStyle alloc] init]; 5. [style setName:name];
6. return style;
7. }</span>
3.2>FTCoreTextNode的主要实现 FTCoreTextNode封装的一些主要的属性:
[objc] view plaincopyprint?
1. <span style="color:#993399;">@property (nonatomic, assign) FTCoreTextNode *supernode; //父节点
2. @property (nonatomic) NSArray *subnodes; //所有子类节点
3. @property (nonatomic, copy) FTCoreTextStyle *style; //定义一种格式 4. @property (nonatomic) NSRange styleRange; //定义格式应用的范围 5. @property (nonatomic) BOOL isClosed; //是否是关闭
6. @property (nonatomic) NSInteger startLocation; //开始的位置
7. @property (nonatomic) BOOL isLink; //是否是链接
8. @property (nonatomic) BOOL isImage; //是否是图片
9. @property (nonatomic) BOOL isBullet; //是否是Bullet
10. @property (nonatomic) NSString *imageName; //图片的名称</span> FTCoreTextNode封装的一些主要的方法: [objc] view plaincopyprint?
1. <span style="color:#006600;">//在所有子节点的最后插入一个子节点 2. - (void)addSubnode:(FTCoreTextNode *)node 3. {
4. [self insertSubnode:node atIndex:[_subnodes count]];
5. }
6.
7. //在指定的位置插入子节点
8. - (void)insertSubnode:(FTCoreTextNode *)subnode atIndex:(NSUInteger)index 9. {
10. //设置父节点
11. subnode.supernode = self;
12. NSMutableArray *subnodes = (NSMutableArray *)self.subnodes; 13. //判断index是否超出数组_subnodes的长度
14. if (index <= [_subnodes count]) { 15. [subnodes insertObject:subnode atIndex:index]; 16. }
17. else { 18. [subnodes addObject:subnode]; 19. }
20. }</span>
[objc] view plaincopyprint?
1. <span style="color:#006600;">//获取节点的索引
2. - (NSUInteger)nodeIndex
3. {
4. return [_supernode.subnodes indexOfObject:self];
5. }
6.
7. //获取指定位置的子节点
8. - (FTCoreTextNode *)subnodeAtIndex:(NSUInteger)index
9. {
10. if (index < [_subnodes count]) {
11. return [_subnodes objectAtIndex:index];
12. }
13. return nil;
14. }
15. </span>
3.3>FTCoreTextView类的主要实现 FTCoreTextView封装的一些主要的属性: [objc] view plaincopyprint?
1. <span style="color:#993399;">@property (nonatomic) NSString *text; //文本内容 2. @property (nonatomic) NSString *processedString; //处理之后的文本 3. @property (nonatomic, readonly) NSAttributedString *attributedString; //属性文
本
4. @property (nonatomic, assign) CGPathRef path; //路径
5. @property (nonatomic) NSMutableDictionary *URLs; //存储所有的URL 6. @property (nonatomic) NSMutableArray *images; //存储所有图片 7. @property (nonatomic, assign) id <FTCoreTextViewDelegate> delegate; //设置
代理对象
8. @property (nonatomic) UIColor *shadowColor; //阴影颜色
9. @property (nonatomic) CGSize shadowOffset; //阴影大小
10. @property (nonatomic) BOOL verbose;
11. @property (nonatomic) BOOL highlightTouch; //触摸时高亮状态</span>
[objc] view plaincopyprint?
1. <pre name="code" class="objc"><span style="color:#993399;">@property
(nonatomic) CTFramesetterRef framesetter;
2. @property (nonatomic) FTCoreTextNode *rootNode; //节点
3. @property (nonatomic, readwrite) NSAttributedString *attributedString; //属性文
本
4. @property (nonatomic) NSDictionary *touchedData; //点击的文本数据的属性的
key和value的映射
5. @property (nonatomic) NSArray *selectionsViews; //选中的视图</span>
[objc] view plaincopyprint?
1. <span style="font-size:14px;color:#993399;">//以下常量是一些默认的标记(标签)
名称
2. extern NSString * const FTCoreTextTagDefault; //默认标记
3. extern NSString * const FTCoreTextTagImage; //图片标记
4. extern NSString * const FTCoreTextTagBullet; //Bullet标记
5. extern NSString * const FTCoreTextTagPage; //< _page / >分页标记 6. extern NSString * const FTCoreTextTagLink; //超链接标记
7. extern NSString * const FTCoreTextTagParagraph; //段落标记</span>
[objc] view plaincopyprint?
1. <span style="font-size:14px;color:#993399;">//以下这些常量被使用在字典中的属
性,这个字典是作为代理对象的协议方法的参数
2. extern NSString * const FTCoreTextDataURL; //定义URL
3. extern NSString * const FTCoreTextDataName; //定义Name
4. extern NSString * const FTCoreTextDataFrame; //定义Frame
5. extern NSString * const FTCoreTextDataAttributes; //定义Attributes 6. @protocol FTCoreTextViewDelegate; //定义协议</span> FTCoreTextView封装的一些主要的方法(主要方法的调用流程及实现的功能):
[objc] view plaincopyprint?
1. /*
2. 调整视图的高度:
3. 1、创建一个CGSize宽度就为视图当前的宽度,高度无穷大
4. 2、调用将此suggestedSizeConstrainedToSize方法,CGSize作为参数。在这个方法中通过_framesetter和CGSize计算出一个合适的size,并返回size。由此确定当前视图的frame.
5. */
6. - (void)fitToSuggestedHeight
7. {
8. CGSize suggestedSize = [self <span style="background-color: rgb(255, 153, 102);">suggestedSizeConstrainedToSize:CGSizeMake(CGRectGetWidth(self.frame), MAXFLOAT)</span>];
9. CGRect viewFrame = self.frame;
10. viewFrame.size.height = suggestedSize.height;
11. self.frame = viewFrame;
12. }
[objc] view plaincopyprint?
1. //计算文本的CGSize
2. - (CGSize)suggestedSizeConstrainedToSize:(CGSize)size
3. {
4. CGSize suggestedSize;
5. [self <span style="background-color: rgb(255, 153,
0);">updateFramesetterIfNeeded</span>];
6. if (_framesetter == NULL) {
7. return CGSizeZero;
8. }
9. suggestedSize = CTFramesetterSuggestFrameSizeWithConstraints(_framesetter, CFRangeMake(0, 0), NULL, size, NULL);
10. suggestedSize = CGSizeMake(ceilf(suggestedSize.width),
ceilf(suggestedSize.height));
11. return suggestedSize;
12. }
[objc] view plaincopyprint?
1. //更新Framesetter
2. - (void)updateFramesetterIfNeeded
3. {
4. if (!_coreTextViewFlags.updatedAttrString) {
5. if (_framesetter != NULL) CFRelease(_framesetter);
6. _framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)<span style="background-color: rgb(255, 153, 0);">self.attributedString);</span>
7. _coreTextViewFlags.updatedAttrString = YES;
8. _coreTextViewFlags.updatedFramesetter = YES;
9. }
10. }
[objc] view plaincopyprint?
1. <span style="color:#008400;">//取得处理之后的属性文本
2. - (NSAttributedString *)attributedString
3. {
4. if (!_coreTextViewFlags.updatedAttrString) {
5. _coreTextViewFlags.updatedAttrString = YES;
6.
7. if (_processedString == nil || _coreTextViewFlags.textChangesMade || !_coreTextViewFlags.updatedFramesetter) {
8. _coreTextViewFlags.textChangesMade = NO;
9. [</span><span style="color: rgb(0, 132, 0); background-color: rgb(255, 153, 0);">self processText</span><span style="color:#008400;">];
10. }
11.
12. if (_processedString) {
13.
14. NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:_processedString];
15.
16. for (FTCoreTextNode *node in [_rootNode allSubnodes]) { 17. [self </span><span style="color:#009900;background-color: rgb(255, 153, 0);">applyStyle:node.style inRange:node.styleRange
onString:&string</span><span style="color:#008400;">];
18. }
19.
20. _attributedString = string;
21. }
22. }
23. return _attributedString;
24. }</span>
[objc] view plaincopyprint?
1. <span style="color:#006600;">/*
2. </span><span style="color:#ff0000;">处理文本的方法的实现(比较核心的方法):</span><span style="color:#006600;">
3. 1、定义正则表达式,在要处理的字符串中查找出符合要求的字符串。 4. NSString *regEx = @"<(/){0,1}.*?( /){0,1}>"; 此正则表达式,可以查找出三类标签,例如:<a 属性=@“123”> </a> <a/>
5. 2、以上三类标签分别对应代码中的3中类型:
6. 1>. <a 属性=@“123”> 对应这种类型 tagType = FTCoreTextTagTypeOpen; 7. 2>. </a> 对应这种类型 tagType = FTCoreTextTagTypeClose;
8. 3>. <a/> 对应这种类型 tagType = FTCoreTextTagTypeSelfClose; 9. 3、获取到标签后,取得标签的名称。在对应的标签类型下进行判断和处理。 10. 4、每个这样的标签(<a>123</a>)对应一个节点。每次取得一个标签的头部(标签类型:FTCoreTextTagTypeOpen),就创建一个节点。通过标签的名称判断是否是超链接、图片等等。
11. 判断完之后,就设置当前节点的属性(节点有很多属性:isLink,isImage等等)。如果是图片,则设置 newNode.isImage = YES; 进行下次循环时,取得标签尾部(标签类型:FTCoreTextTagTypeClose),就直接通过当前节点的属性判断是否是图片标签,或者其他类型。根据判断结果,使用封装好的FTCoreTextStyle类,为不同的标签内容设置不同的格式Style为标签的内容设置不同的格式。
12. */
13. - (void)processText
14. {
15. if (!_text || [_text length] == 0) return;
16. [_URLs removeAllObjects];
17. [_images removeAllObjects];
18. FTCoreTextNode *rootNode = [FTCoreTextNode new];
19. rootNode.style = [_styles objectForKey:[self
defaultTagNameForKey:FTCoreTextTagDefault]];
20. FTCoreTextNode *currentSupernode = rootNode;
21. NSMutableString *processedString = [NSMutableString stringWithString:_text]; 22. BOOL finished = NO;
23. NSRange remainingRange = NSMakeRange(0, [processedString length]); 24. //定义了正则表达式,查找标签,例如:<a 属性=@“123”> </a> <a/> 25. <span style="background-color: rgb(204, 204, 255);">NSString *regEx = @"<(/){0,1}.*?( /){0,1}>";</span>
26.
27. while (!finished) {
28.
29. NSRange tagRange = [processedString rangeOfString:regEx
options:NSRegularExpressionSearch range:remainingRange];
30.
31. if (tagRange.location == NSNotFound) {
32. if (currentSupernode != rootNode && !currentSupernode.isClosed) { 33. if (_verbose) NSLog(@"FTCoreTextView :%@ - Couldn't parse text because tag '%@' at position %d is not closed - aborting rendering", self,
currentSupernode.style.name, currentSupernode.startLocation);
34. return;
35. }
36. finished = YES;
37. continue;
38. }
39. NSString *fullTag = [processedString substringWithRange:tagRange]; 40. FTCoreTextTagType tagType;
41.
42. if ([fullTag rangeOfString:@"</"].location == 0) {
43. //标签</b>
44. tagType = FTCoreTextTagTypeClose;
45. }
46. else if ([fullTag rangeOfString:@"/>"].location == NSNotFound && [fullTag rangeOfString:@" />"].location == NSNotFound) {
47. //标签<b>或者<b 属性=@"123">
48. tagType = FTCoreTextTagTypeOpen;
49. }
50. else {
51. //标签<b/>
52. tagType = FTCoreTextTagTypeSelfClose;
53. }
54. //获取整个标签所有组成部分
55. NSArray *tagsComponents = [fullTag componentsSeparatedByString:@" "]; 56.
57. //获取标签名称(里面可能包括"<")
58. NSString *tagName = (tagsComponents.count > 0) ? [tagsComponents objectAtIndex:0] : fullTag;
59.
60. //这里获得的tagName的值例如:_image
61. tagName = [tagName stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"< />"]];
62.
63. FTCoreTextStyle *style = [_styles objectForKey:tagName];
64.
65. if (style == nil) {
66. style = [_styles objectForKey:[self
defaultTagNameForKey:FTCoreTextTagDefault]];
67. if (_verbose) NSLog(@"FTCoreTextView :%@ - Couldn't find style for tag '%@'", self, tagName);
68. }
69. //判断标签的类型
70. switch (tagType) {
71. case FTCoreTextTagTypeOpen:
72. {
73. if (currentSupernode.isLink || currentSupernode.isImage) {
74. NSString *predefinedTag = nil;
75. if (currentSupernode.isLink) predefinedTag = [self
defaultTagNameForKey:FTCoreTextTagLink];
76. else if (currentSupernode.isImage) predefinedTag = [self
defaultTagNameForKey:FTCoreTextTagImage];
77. if (_verbose) NSLog(@"FTCoreTextView :%@ - You can't open a new tag inside a '%@' tag - aborting rendering", self, predefinedTag);
78. return;
79. }
80. FTCoreTextNode *newNode = [FTCoreTextNode new];
81. newNode.style = style;
82. newNode.startLocation = tagRange.location;
83. //判断是否是链接
84. if ([tagName isEqualToString:[self defaultTagNameForKey:FTCoreTextTagLink]]) { 85. newNode.isLink = YES;
86. }
87. //判断是否是Bullet
88. else if ([tagName isEqualToString:[self
defaultTagNameForKey:FTCoreTextTagBullet]]) {
89. newNode.isBullet = YES;
90. NSString *appendedString = [NSString stringWithFormat:@"%@\t", newNode.style.bulletCharacter];
91. [processedString insertString:appendedString atIndex:tagRange.location + tagRange.length];
92.
93. //bullet styling
94. //设置子标签的样式
95. FTCoreTextStyle *bulletStyle = [FTCoreTextStyle new];
96. bulletStyle.name = @"_FTBulletStyle";
97. bulletStyle.font = newNode.style.bulletFont;
98. bulletStyle.color = newNode.style.bulletColor;
99. bulletStyle.applyParagraphStyling = NO;
100. bulletStyle.paragraphInset = UIEdgeInsetsMake(0, 0, 0,
newNode.style.paragraphInset.left);
101.
102. FTCoreTextNode *bulletNode = [FTCoreTextNode new];
103. bulletNode.style = bulletStyle;
104. bulletNode.styleRange = NSMakeRange(tagRange.location, [appendedString length]);
105.
106. [newNode addSubnode:bulletNode];
107. }
108. //判断是否是图片
109. else if ([tagName isEqualToString:[self
defaultTagNameForKey:FTCoreTextTagImage]]) {
110. newNode.isImage = YES;
111. }
112. [processedString replaceCharactersInRange:tagRange withString:@""]; 113. [currentSupernode addSubnode:newNode];
114. currentSupernode = newNode;
115. remainingRange.location = tagRange.location;
116. remainingRange.length = [processedString length] - tagRange.location; 117. }
118. break;
119. case FTCoreTextTagTypeClose:
120. {
121. if ((![currentSupernode.style.name isEqualToString:[self defaultTagNameForKey:FTCoreTextTagDefault]]
&& ![currentSupernode.style.name isEqualToString:tagName]) ) {
122. if (_verbose) NSLog(@"FTCoreTextView :%@ - Closing tag '%@' at range %@ doesn't match open tag '%@' - aborting rendering", self, fullTag,
NSStringFromRange(tagRange), currentSupernode.style.name);
123. return;
124. }
125.
126. currentSupernode.isClosed = YES;
127. if (currentSupernode.isLink) {
128. NSRange elementContentRange = NSMakeRange(currentSupernode.startLocation, tagRange.location - currentSupernode.startLocation);
129. NSString *elementContent = [processedString
substringWithRange:elementContentRange];
130. NSRange pipeRange = [elementContent rangeOfString:@"|"]; 131. NSString *urlString = nil;
132. NSString *urlDescription = nil;
133. if (pipeRange.location != NSNotFound) {
134. urlString = [elementContent substringToIndex:pipeRange.location] ; 135. urlDescription = [elementContent substringFromIndex:pipeRange.location + 1]; 136. }
137. [processedString replaceCharactersInRange:NSMakeRange(elementContentRange.location, elementContentRange.length + tagRange.length) withString:urlDescription]; 138. if (!([[urlString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] hasPrefix:@"http://"] || [[urlString stringByTrimmingCharactersInSet:[NSCharacterSet
whitespaceAndNewlineCharacterSet]] hasPrefix:@"https://"]))
139. {
140. urlString = [NSString stringWithFormat:@"http://%@", urlString]; 141. }
142. NSURL *url = [NSURL URLWithString:[urlString stringByTrimmingCharactersInSet:[NSCharacterSet
whitespaceAndNewlineCharacterSet]]];
143. NSRange urlDescriptionRange =
NSMakeRange(elementContentRange.location, [urlDescription length]); 144. [_URLs setObject:url forKey:NSStringFromRange(urlDescriptionRange)]; 145.
146. currentSupernode.styleRange = urlDescriptionRange;
147. }
148. else if (currentSupernode.isImage) {
149. NSRange elementContentRange = NSMakeRange(currentSupernode.startLocation, tagRange.location - currentSupernode.startLocation);
150. NSString *elementContent = [processedString
substringWithRange:elementContentRange];
151. UIImage *img = [UIImage imageNamed:elementContent];
152.
153. if (img) {
154. NSString *lines = @"\n";
155. float leading = img.size.height;
156. currentSupernode.style.leading = leading;
157. currentSupernode.imageName = elementContent;
158. [processedString replaceCharactersInRange:NSMakeRange(elementContentRange.location, elementContentRange.length + tagRange.length) withString:lines];
159.
160. [_images addObject:currentSupernode];
161. currentSupernode.styleRange = NSMakeRange(elementContentRange.location,
[lines length]);
162. }
163. else {
164. if (_verbose) NSLog(@"FTCoreTextView :%@ - Couldn't find image '%@' in main bundle", self, [NSValue valueWithRange:elementContentRange]); 165. [processedString replaceCharactersInRange:tagRange withString:@""]; 166. }
167. }
168. else {
169. currentSupernode.styleRange = NSMakeRange(currentSupernode.startLocation, tagRange.location - currentSupernode.startLocation);
170. [processedString replaceCharactersInRange:tagRange withString:@""]; 171. }
172. if ([currentSupernode.style.appendedCharacter length] > 0) {
173. [processedString insertString:currentSupernode.style.appendedCharacter atIndex:currentSupernode.styleRange.location +
currentSupernode.styleRange.length];
174. NSRange newStyleRange = currentSupernode.styleRange;
175. newStyleRange.length += [currentSupernode.style.appendedCharacter length]; 176. currentSupernode.styleRange = newStyleRange;
177. }
178. if (style.paragraphInset.top > 0) {
179. if (![style.name isEqualToString:[self defaultTagNameForKey:FTCoreTextTagBullet]] || [[currentSupernode previousNode].style.name isEqualToString:[self
defaultTagNameForKey:FTCoreTextTagBullet]]) {
180. [processedString insertString:@"\n" atIndex:currentSupernode.startLocation];
181. NSRange topSpacingStyleRange =
NSMakeRange(currentSupernode.startLocation, [@"\n" length]);
182. FTCoreTextStyle *topSpacingStyle = [[FTCoreTextStyle alloc] init]; 183. topSpacingStyle.name = [NSString
stringWithFormat:@"_FTTopSpacingStyle_%@", currentSupernode.style.name]; 184. topSpacingStyle.minLineHeight = currentSupernode.style.paragraphInset.top; 185. topSpacingStyle.maxLineHeight = currentSupernode.style.paragraphInset.top; 186. FTCoreTextNode *topSpacingNode = [[FTCoreTextNode alloc] init]; 187. topSpacingNode.style = topSpacingStyle;
188.
189. topSpacingNode.styleRange = topSpacingStyleRange;
190.
191. [currentSupernode.supernode insertSubnode:topSpacingNode
beforeNode:currentSupernode];
192.
193. [currentSupernode
adjustStylesAndSubstylesRangesByRange:topSpacingStyleRange]; 194. }
195. }
196. remainingRange.location = currentSupernode.styleRange.location + currentSupernode.styleRange.length;
197. remainingRange.length = [processedString length] - remainingRange.location; 198. currentSupernode = currentSupernode.supernode;
199. }
200. break;
201. case FTCoreTextTagTypeSelfClose:
202. {
203. FTCoreTextNode *newNode = [FTCoreTextNode new];
204. newNode.style = style;
205. [processedString replaceCharactersInRange:tagRange
withString:newNode.style.appendedCharacter];
206. newNode.styleRange = NSMakeRange(tagRange.location,
[newNode.style.appendedCharacter length]);
207. newNode.startLocation = tagRange.location;
208. [currentSupernode addSubnode:newNode];
209.
210. if (style.block)
211. {
212. NSDictionary* blockDict = [NSDictionary dictionaryWithObjectsAndKeys:tagsComponents,@"components", [NSValue valueWithRange:NSMakeRange(tagRange.location,
newNode.style.appendedCharacter.length)],@"range", nil nil];
213. style.block(blockDict);
214. }
215. remainingRange.location = tagRange.location;
216. remainingRange.length = [processedString length] - tagRange.location; 217. }
218. break;
219. }
220. }
221.
222. rootNode.styleRange = NSMakeRange(0, [processedString length]); 223. self.rootNode = rootNode;
224. self.processedString = processedString;
225. }</span>
[objc] view plaincopyprint?
1. <span style="color:#006600;">//在指定的范围内,应用指定的格式 2. - (void)applyStyle:(FTCoreTextStyle *)style inRange:(NSRange)styleRange onString:(NSMutableAttributedString **)attributedString
3. {
4. [*attributedString addAttribute:(id)FTCoreTextDataName
5. value:(id)style.name
6. range:styleRange];
7.
8. [*attributedString addAttribute:(id)kCTForegroundColorAttributeName 9. value:(id)style.color.CGColor
10. range:styleRange];
11.
12. if (style.isUnderLined) {
13. NSNumber *underline = [NSNumber numberWithInt:kCTUnderlineStyleSingle]; 14. [*attributedString addAttribute:(id)kCTUnderlineStyleAttributeName 15. value:(id)underline
16. range:styleRange];
17. }
18.
19. CTFontRef ctFont = CTFontCreateFromUIFont(style.font);
20.
21. [*attributedString addAttribute:(id)kCTFontAttributeName
22. value:(__bridge id)ctFont
23. range:styleRange];
24. CFRelease(ctFont);
25.
26. CTTextAlignment alignment = style.textAlignment;
27. CGFloat maxLineHeight = style.maxLineHeight;
28. CGFloat minLineHeight = style.minLineHeight;
29. CGFloat paragraphLeading = style.leading;
30.
31. CGFloat paragraphSpacingBefore = style.paragraphInset.top;
32. CGFloat paragraphSpacingAfter = style.paragraphInset.bottom; 33. CGFloat paragraphFirstLineHeadIntent = style.paragraphInset.left; 34. CGFloat paragraphHeadIntent = style.paragraphInset.left;
35. CGFloat paragraphTailIntent = style.paragraphInset.right;
36.
37. //if (SYSTEM_VERSION_LESS_THAN(@"5.0")) {
38. paragraphSpacingBefore = 0;
39. //}
40.
41. CFIndex numberOfSettings = 9;
42. CGFloat tabSpacing = 28.f;
43.
44. BOOL applyParagraphStyling = style.applyParagraphStyling;
45.
46. if ([style.name isEqualToString:[self
defaultTagNameForKey:FTCoreTextTagBullet]]) {
47. applyParagraphStyling = YES;
48. }
49. else if ([style.name isEqualToString:@"_FTBulletStyle"]) {
50. applyParagraphStyling = YES;
51. numberOfSettings++;
52. tabSpacing = style.paragraphInset.right;
53. paragraphSpacingBefore = 0;
54. paragraphSpacingAfter = 0;
55. paragraphFirstLineHeadIntent = 0;
56. paragraphTailIntent = 0;
57. }
58. else if ([style.name hasPrefix:@"_FTTopSpacingStyle"]) {
59. [*attributedString removeAttribute:(id)kCTParagraphStyleAttributeName range:styleRange];
60. }
61.
62. if (applyParagraphStyling) {
63.
64. CTTextTabRef tabArray[] = { CTTextTabCreate(0, tabSpacing, NULL) }; 65.
66. CFArrayRef tabStops = CFArrayCreate( kCFAllocatorDefault, (const void**) tabArray, 1, &kCFTypeArrayCallBacks );
67. CFRelease(tabArray[0]);
68.
69. CTParagraphStyleSetting settings[] = {
70. {kCTParagraphStyleSpecifierAlignment, sizeof(alignment), &alignment}, 71. {kCTParagraphStyleSpecifierMaximumLineHeight, sizeof(CGFloat), &maxLineHeight},
72. {kCTParagraphStyleSpecifierMinimumLineHeight, sizeof(CGFloat), &minLineHeight},
73. {kCTParagraphStyleSpecifierParagraphSpacingBefore, sizeof(CGFloat), ?graphSpacingBefore},
74. {kCTParagraphStyleSpecifierParagraphSpacing, sizeof(CGFloat), ?graphSpacingAfter},
75. {kCTParagraphStyleSpecifierFirstLineHeadIndent, sizeof(CGFloat), ?graphFirstLineHeadIntent},
76. {kCTParagraphStyleSpecifierHeadIndent, sizeof(CGFloat), ?graphHeadIntent}, 77. {kCTParagraphStyleSpecifierTailIndent, sizeof(CGFloat), ?graphTailIntent}, 78. {kCTParagraphStyleSpecifierLineSpacing, sizeof(CGFloat), ?graphLeading}, 79. {kCTParagraphStyleSpecifierTabStops, sizeof(CFArrayRef), &tabStops}//always at the end
80. };
81.
82. CTParagraphStyleRef paragraphStyle = CTParagraphStyleCreate(settings, numberOfSettings);
83. [*attributedString addAttribute:(id)kCTParagraphStyleAttributeName 84. value:(__bridge id)paragraphStyle
85. range:styleRange];
86. CFRelease(tabStops);
87. CFRelease(paragraphStyle);
88. }
89. }</span>
//绘制的方法
[objc] view plaincopyprint?
1. <span style="color:#006600;">/*
2. drawRect方法调用流程:
3. 程序运行先调用drawRect方法,然后再调用drawImages方法,将整个页面绘制出来。
4. drawRect方法的实现:
5. 1、创建CGPath
6. 2、由CGPath和framesetter创建CTFrameRef
7. 3、绘制:CTFrameDraw(drawFrame, context);
8. 4、如果有图片就调用drawImages,进行图片绘制
9.
10. drawImages方法的实现:
11. 1、创建CGPath
12. 2、由CGPath和framesetter创建CTFrameRef
13. 3、通过这个方法CTFrameGetLines(ctframe);获取lines
14. 4、最后构造出frame,绘制图片[img drawInRect:CGRectIntegral(frame)]; 15. */
16.
17. - (void)drawRect:(CGRect)rect
18. {
19. CGContextRef context = UIGraphicsGetCurrentContext();
20.
21. [self.backgroundColor setFill];
22. CGContextFillRect(context, rect);
23.
24. //更新Framesetter
25. [self updateFramesetterIfNeeded];
26.
27. CGMutablePathRef mainPath = CGPathCreateMutable();
28.
29. if (!_path) {
30. CGPathAddRect(mainPath, NULL, CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height));
31. }
32. else {
33. CGPathAddPath(mainPath, NULL, _path);
34. }
35.
36. CTFrameRef drawFrame = CTFramesetterCreateFrame(_framesetter, CFRangeMake(0, 0), mainPath, NULL);
37.
38. if (drawFrame == NULL) {
39. if (_verbose) NSLog(@"f: %@", self.processedString);
40. }
41. else {
42. //draw images 绘制图片
43. if ([_images count] > 0) [self<span style="background-color: rgb(255, 153, 0);"> drawImages</span>];
44.
45. //设置阴影颜色
46. if (_shadowColor) {
47. CGContextSetShadowWithColor(context, _shadowOffset, 0.f,
_shadowColor.CGColor);
48. }
49.
50. //转换坐标系统
51. CGContextSetTextMatrix(context, CGAffineTransformIdentity);
52. CGContextTranslateCTM(context, 0, self.bounds.size.height);
53. CGContextScaleCTM(context, 1.0, -1.0);
54.
55. // draw text
56. CTFrameDraw(drawFrame, context);
57. }
58. // cleanup
59. if (drawFrame) CFRelease(drawFrame);
60. CGPathRelease(mainPath);
61.
62. if ([_delegate respondsToSelector:@selector(coreTextViewfinishedRendering:)]) {
63. [_delegate coreTextViewfinishedRendering:self];
64. }
65. }</span><span style="color:#009900;">
66. </span>
[objc] view plaincopyprint?
1. <span style="color:#006600;">//绘制图片
2. - (void)drawImages
3. {
4. CGMutablePathRef mainPath = CGPathCreateMutable();
5. if (!_path) {
6. CGPathAddRect(mainPath, NULL, CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height));
7. }
8. else {
9. CGPathAddPath(mainPath, NULL, _path);
10. }
11.
12. CTFrameRef ctframe = CTFramesetterCreateFrame(_framesetter, CFRangeMake(0, 0), mainPath, NULL);
13. CGPathRelease(mainPath);
14.
15. NSArray *lines = (__bridge NSArray *)CTFrameGetLines(ctframe); 16. NSInteger lineCount = [lines count];
17. CGPoint origins[lineCount];
18.
19. CTFrameGetLineOrigins(ctframe, CFRangeMake(0, 0), origins); 20.
21. FTCoreTextNode *imageNode = [_images objectAtIndex:0];
22.
23. for (int i = 0; i < lineCount; i++) {
24. CGPoint baselineOrigin = origins[i];
25. //the view is inverted, the y origin of the baseline is upside down 26. baselineOrigin.y = CGRectGetHeight(self.frame) - baselineOrigin.y; 27.
28. CTLineRef line = (__bridge CTLineRef)[lines objectAtIndex:i]; 29. CFRange cfrange = CTLineGetStringRange(line);
30.
31. if (cfrange.location > imageNode.styleRange.location) {
32. CGFloat ascent, descent;
33. CGFloat lineWidth = CTLineGetTypographicBounds(line, &ascent, &descent, NULL);
34.
35. CGRect lineFrame = CGRectMake(baselineOrigin.x, baselineOrigin.y - ascent, lineWidth, ascent + descent);
36.
37. CTTextAlignment alignment = imageNode.style.textAlignment; 38. UIImage *img = [UIImage imageNamed:imageNode.imageName]; 39.
40. if (img) {
41. int x = 0;
42. if (alignment == kCTRightTextAlignment) x = (self.frame.size.width - img.size.width);
43. if (alignment == kCTCenterTextAlignment) x = ((self.frame.size.width - img.size.width) / 2);
44.
45. CGRect frame = CGRectMake(x, (lineFrame.origin.y - img.size.height), img.size.width, img.size.height);
46.
47. // adjusting frame
48.
49. UIEdgeInsets insets = imageNode.style.paragraphInset;
50. if (alignment != kCTCenterTextAlignment) frame.origin.x = (alignment == kCTLeftTextAlignment)? insets.left : (self.frame.size.width - img.size.width - insets.right);
51. frame.origin.y += insets.top;
52. frame.size.width = ((insets.left + insets.right + img.size.width ) > self.frame.size.width)? self.frame.size.width : img.size.width;
53.
54. [img drawInRect:CGRectIntegral(frame)];
55. }
56.
57. NSInteger imageNodeIndex = [_images indexOfObject:imageNode]; 58. if (imageNodeIndex < [_images count] - 1) {
59. imageNode = [_images objectAtIndex:imageNodeIndex + 1]; 60. }
61. else {
62. break;
63. }
64. }
65. }
66. CFRelease(ctframe);
67. }
68. </span>
//触摸事件触发的方法
[objc] view plaincopyprint?
1. <span style="color:#006600;">/*
2. 当用户点击超链接时,方法调用流程:
3. 首先调用touchesBegan方法。在touchesBegan方法中又会调用
dataForPoint:activeRects:这个方法,返回被点击的超链接页面绘制需要的参数字典。最后在touchesEnded的方法中调用协议方法,并将参数字典传过去。在协议方法中取得被点击的超链接对应的URL,显示出URL对应的页面。 4.
5. */
6.
7. - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 8. {
9. [super touchesEnded:touches withEvent:event];
10.
11. if (self.delegate && [self.delegate
respondsToSelector:@selector(coreTextView:receivedTouchOnData:)]) { 12. CGPoint point = [(UITouch *)[touches anyObject] locationInView:self]; 13. NSMutableArray *activeRects;
14. NSDictionary *data = [self <span style="background-color: rgb(255, 153, 0);">dataForPoint:point activeRects:&activeRects</span>];
15. if (data.count > 0) {
16. NSMutableArray *selectedViews = [NSMutableArray new];
17. for (NSString *rectString in activeRects) {
18. CGRect rect = CGRectFromString(rectString);
19. UIView *view = [[UIView alloc] initWithFrame:rect];
20. view.layer.cornerRadius = 3;
21. view.clipsToBounds = YES;
22. view.backgroundColor = [UIColor colorWithWhite:0 alpha:0.25]; 23. [self addSubview:view];
24. [selectedViews addObject:view];
25. }
26. self.touchedData = data;
27. self.selectionsViews = selectedViews;
28. }
29. }
30. }</span>
[objc] view plaincopyprint?
1. <span style="color:#006600;">/* 在touchBegan方法中调用此方法 2. 此方法的实现:
3. 1、构造CGPathRef
4. 2、通过CTFramesetterRef和CGPath 构造出一个CTFrameRef 5. 3、在从CTFrameRef获取lines: NSArray *lines = (__bridge NSArray *)CTFrameGetLines(ctframe);
6. 4.从lines里面获取runs: CFArrayRef runs = CTLineGetGlyphRuns(line); 7. 5.遍历所有的run,获取到attributes,并且设置了runBounds; 8. 然后将attributes和runBounds存到一个字典中:
9. [returnedDict setObject:attributes forKey:FTCoreTextDataAttributes]; 10. [returnedDict setObject:NSStringFromCGRect(runBounds) forKey:FTCoreTextDataFrame];
11. 返回字典returnedDict。
12.
13. */
14.
15. - (NSDictionary *)dataForPoint:(CGPoint)point activeRects:(NSArray **)activeRects
16. {
17. NSMutableDictionary *returnedDict = [NSMutableDictionary dictionary]; 18.
19. CGMutablePathRef mainPath = CGPathCreateMutable();
20. if (!_path) {
21. CGPathAddRect(mainPath, NULL, CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height));
22. }
23. else {
24. CGPathAddPath(mainPath, NULL, _path);
25. }
26.
27. CTFrameRef ctframe = CTFramesetterCreateFrame(_framesetter, CFRangeMake(0, 0), mainPath, NULL);
28. CGPathRelease(mainPath);
29.
30. NSArray *lines = (__bridge NSArray *)CTFrameGetLines(ctframe); 31. NSInteger lineCount = [lines count];
32.
33. //数组存放点
34. CGPoint origins[lineCount];
35.
36. if (lineCount != 0) {
37.
38. CTFrameGetLineOrigins(ctframe, CFRangeMake(0, 0), origins); 39.
40. for (int i = 0; i < lineCount; i++) {
41. CGPoint baselineOrigin = origins[i];
42. //the view is inverted, the y origin of the baseline is upside down 43. //y 的起点是反向的,视图是颠倒的
44. baselineOrigin.y = CGRectGetHeight(self.frame) - baselineOrigin.y; 45.
46. CTLineRef line = (__bridge CTLineRef)[lines objectAtIndex:i]; 47. CGFloat ascent, descent;
48. CGFloat lineWidth = CTLineGetTypographicBounds(line, &ascent, &descent, NULL);
49.
50. CGRect lineFrame = CGRectMake(baselineOrigin.x, baselineOrigin.y - ascent, lineWidth, ascent + descent);
51.
52. //判断点是否在lineFrame的范围内
53. if (CGRectContainsPoint(lineFrame, point)) {
54. //we look if the position of the touch is correct on the line
55.
56. CFIndex index = CTLineGetStringIndexForPosition(line, point);
57.
58. NSArray *urlsKeys = [_URLs allKeys];
59.
60. for (NSString *key in urlsKeys) {
61. NSRange range = NSRangeFromString(key);
62. if (index >= range.location && index < range.location + range.length) { 63. NSURL *url = [_URLs objectForKey:key];
64. if (url) [returnedDict setObject:url forKey:FTCoreTextDataURL];
65.
66. if (activeRects && _highlightTouch) {
67. //we looks for the rects enclosing the entire active section
68. NSInteger startIndex = range.location;
69. NSInteger endIndex = range.location + range.length;
70.
71. //we look for the line that contains the start index
72. //寻找线的起点的索引
73. NSInteger startLineIndex = i;
74. for (int iLine = i; iLine >= 0; iLine--) {
75. CTLineRef line = (__bridge CTLineRef)[lines objectAtIndex:iLine]; 76. CFRange range = CTLineGetStringRange(line);
77. if (range.location <= startIndex && range.location + range.length >= startIndex) { 78. startLineIndex = iLine;
79. break;
80. }
81. }
82. //we look for the line that contains the end index
83. //寻找线的终点索引
84. NSInteger endLineIndex = startLineIndex;
85. for (int iLine = i; iLine < lineCount; iLine++) {
86. CTLineRef line = (__bridge CTLineRef)[lines objectAtIndex:iLine]; 87. CFRange range = CTLineGetStringRange(line);
88. if (range.location <= endIndex && range.location + range.length >= endIndex) { 89. endLineIndex = iLine;
90. break;
91. }
92. }
93. //we get enclosing rects
94. //获取到封闭的矩形
95. NSMutableArray *rectsStrings = [NSMutableArray new];
96. for (int iLine = startLineIndex; iLine <= endLineIndex; iLine++) { 97. CTLineRef line = (__bridge CTLineRef)[lines objectAtIndex:iLine]; 98. CGFloat ascent, descent;
99. CGFloat lineWidth = CTLineGetTypographicBounds(line, &ascent, &descent, NULL);
100.
101. CGPoint baselineOrigin = origins[iLine];
102. //the view is inverted, the y origin of the baseline is upside down 103. //y 的起点是反向的,视图是颠倒的
104. baselineOrigin.y = CGRectGetHeight(self.frame) - baselineOrigin.y; 105.
106. CGRect lineFrame = CGRectMake(baselineOrigin.x, baselineOrigin.y - ascent, lineWidth, ascent + descent);
107. CGRect actualRect;
108. actualRect.size.height = lineFrame.size.height;
109. actualRect.origin.y = lineFrame.origin.y;
110.
111. CFRange range = CTLineGetStringRange(line);
112. if (range.location >= startIndex) {
113. //the beginning of the line is included
114. actualRect.origin.x = lineFrame.origin.x;
115. } else {
116. actualRect.origin.x = CTLineGetOffsetForStringIndex(line, startIndex, NULL); 117. }
118. NSInteger lineRangEnd = range.length + range.location;
119. if (lineRangEnd <= endIndex) {
120. //the end of the line is included
121. actualRect.size.width = CGRectGetMaxX(lineFrame) -
CGRectGetMinX(actualRect);
122. } else {
123. CGFloat position = CTLineGetOffsetForStringIndex(line, endIndex, NULL); 124. actualRect.size.width = position - CGRectGetMinX(actualRect); 125. }
126. actualRect = CGRectInset(actualRect, -1, 0);
127. [rectsStrings addObject:NSStringFromCGRect(actualRect)];
128. }
129.
130. *activeRects = rectsStrings;
131. }
132. break;
133. }
134. }
135.
136. //frame
137. CFArrayRef runs = CTLineGetGlyphRuns(line);
138. for(CFIndex j = 0; j < CFArrayGetCount(runs); j++) {
139. CTRunRef run = CFArrayGetValueAtIndex(runs, j);
140. NSDictionary* attributes = (__bridge NSDictionary*)CTRunGetAttributes(run); 141.
142. NSString *name = [attributes objectForKey:FTCoreTextDataName]; 143. if (![name isEqualToString:@"_link"]) continue;
144.
145. //设置FTCoreTextDataAttributes
146. [returnedDict setObject:attributes forKey:FTCoreTextDataAttributes]; 147.
148. CGRect runBounds;
149. runBounds.size.width = CTRunGetTypographicBounds(run, CFRangeMake(0, 0), &ascent, &descent, NULL); //8
150. runBounds.size.height = ascent + descent;
151.
152. CGFloat xOffset = CTLineGetOffsetForStringIndex(line,
CTRunGetStringRange(run).location, NULL); //9
153. runBounds.origin.x = baselineOrigin.x + self.frame.origin.x + xOffset + 0; 154. runBounds.origin.y = baselineOrigin.y + lineFrame.size.height - ascent; 155.
156. //设置FTCoreTextDataFrame
157. [returnedDict setObject:NSStringFromCGRect(runBounds) forKey:FTCoreTextDataFrame];
158. }
159. }
160. if (returnedDict.count > 0) break;
161. }
162. }
163.
164. CFRelease(ctframe);
165. return returnedDict;
166. }
167. </span>
[objc] view plaincopyprint?
1. <span style="color:#006600;">//触摸结束后,调用的方法 2. - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 3. {
4. [super touchesEnded:touches withEvent:event];
5.
6. if (_touchedData) {
7. if (self.delegate && [self.delegate
respondsToSelector:@selector(coreTextView:receivedTouchOnData:)]) { 8. if ([self.delegate
respondsToSelector:@selector(coreTextView:receivedTouchOnData:)]) { 9.
10. //触摸结束时,调用协议方法
11. [self.delegate <span style="background-color: rgb(255, 153,
0);">coreTextView:self receivedTouchOnData:_touchedData</span>];
12. }
13. }
14. _touchedData = nil;
15. [_selectionsViews
makeObjectsPerformSelector:@selector(removeFromSuperview)]; 16. _selectionsViews = nil;
17. }
18. }</span>
演示使用FTCoreText框架实现图文混排的demo,以及效果图
demo的.h文件:
[objc] view plaincopyprint?
1. <span style="color:#006600;">@interface articleViewController : UIViewController <FTCoreTextViewDelegate>
2. @property (nonatomic) UIScrollView *scrollView;
3. @property (nonatomic) FTCoreTextView *coreTextView;</span> demo的.m文件:
[objc] view plaincopyprint?
1. <span style="color:#006600;">#pragma mark - View Controller Methods 2. 3. // Implement viewDidLoad to do additional setup after loading the view, typically from a nib. 4. - (void)viewDidLoad
5. {
6. [super viewDidLoad];
7.
8. //add coretextview 9. scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds]; 10. scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
11. coreTextView = [[FTCoreTextView alloc] initWithFrame:CGRectMake(20, 20, 280, 0)];
12. coreTextView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
13. // set text
14. [coreTextView setText:[self textForView]];
15. // set styles
16. [coreTextView addStyles:[self coreTextStyle]];
17. // set delegate
18. [coreTextView setDelegate:self];
19.
20. //设置coreTextView的高度
21. [coreTextView fitToSuggestedHeight];
22.
23. [scrollView addSubview:coreTextView];
24. [scrollView setContentSize:CGSizeMake(CGRectGetWidth(scrollView.bounds), CGRectGetHeight(coreTextView.frame) + 40)];
25.
26. [self.view addSubview:scrollView];
27.
28.
29. }<span style="font-size:14px;">
30. </span></span>
[objc] view plaincopyprint?
1. //取得要处理的文本数据
2. - (NSString *)textForView
3. {
4. NSString *text = [NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"text" ofType:@"txt"] encoding:NSUTF8StringEncoding error:nil];
5.
6. return text;
7. }
8.
9. //定义一组格式
10. - (NSArray *)coreTextStyle
11. {
12. NSMutableArray *result = [NSMutableArray array];
13.
14. FTCoreTextStyle *defaultStyle = [FTCoreTextStyle new];
15. defaultStyle.name = FTCoreTextTagDefault; //thought the default name is already set to FTCoreTextTagDefault
16. defaultStyle.font = [UIFont fontWithName:@"TimesNewRomanPSMT" size:16.f]; 17. defaultStyle.textAlignment = FTCoreTextAlignementJustified;
18. [result addObject:defaultStyle];
19.
20.
21. FTCoreTextStyle *titleStyle = [FTCoreTextStyle styleWithName:@"title"]; // using fast method
22. titleStyle.font = [UIFont fontWithName:@"TimesNewRomanPSMT" size:40.f]; 23. titleStyle.paragraphInset = UIEdgeInsetsMake(0, 0, 25, 0);
24. titleStyle.textAlignment = FTCoreTextAlignementCenter;
25. [result addObject:titleStyle];
26.
27. FTCoreTextStyle *imageStyle = [FTCoreTextStyle new];
28. imageStyle.paragraphInset = UIEdgeInsetsMake(0,0,0,0);
29. imageStyle.name = FTCoreTextTagImage;
30. imageStyle.textAlignment = FTCoreTextAlignementCenter;
31. [result addObject:imageStyle];
32.
33. FTCoreTextStyle *firstLetterStyle = [FTCoreTextStyle new];
34. firstLetterStyle.name = @"firstLetter";
35. firstLetterStyle.font = [UIFont fontWithName:@"TimesNewRomanPS-BoldMT" size:30.f];
36. [result addObject:firstLetterStyle];
37.
38. FTCoreTextStyle *linkStyle = [defaultStyle copy];
39. linkStyle.name = FTCoreTextTagLink;
40. linkStyle.color = [UIColor orangeColor];
41. [result addObject:linkStyle];
42.
43. FTCoreTextStyle *subtitleStyle = [FTCoreTextStyle styleWithName:@"subtitle"]; 44. subtitleStyle.font = [UIFont fontWithName:@"TimesNewRomanPS-BoldMT" size:25.f];
45. subtitleStyle.color = [UIColor brownColor];
46. subtitleStyle.paragraphInset = UIEdgeInsetsMake(10, 0, 10, 0);
47. [result addObject:subtitleStyle];
48.
49. FTCoreTextStyle *bulletStyle = [defaultStyle copy];
50. bulletStyle.name = FTCoreTextTagBullet;
51. bulletStyle.bulletFont = [UIFont fontWithName:@"TimesNewRomanPSMT" size:16.f];
52. bulletStyle.bulletColor = [UIColor orangeColor];
53. bulletStyle.bulletCharacter = @"?";
54. [result addObject:bulletStyle];
55.
56. FTCoreTextStyle *italicStyle = [defaultStyle copy];
57. italicStyle.name = @"italic";
58. italicStyle.underlined = YES;
59. italicStyle.font = [UIFont fontWithName:@"TimesNewRomanPS-ItalicMT" size:16.f];
60. [result addObject:italicStyle];
61.
62. FTCoreTextStyle *boldStyle = [defaultStyle copy];
63. boldStyle.name = @"bold";
64. boldStyle.font = [UIFont fontWithName:@"TimesNewRomanPS-BoldMT" size:16.f];
65. [result addObject:boldStyle];
66.
67. FTCoreTextStyle *coloredStyle = [defaultStyle copy];
68. [coloredStyle setName:@"colored"];
69. [coloredStyle setColor:[UIColor redColor]];
70. [result addObject:coloredStyle];
71.
72. return result;
73. }
74.
75. #pragma mark - FTCoreTextView 协议方法 点击超链接时,会调用此方法 76. - (void)coreTextView:(FTCoreTextView *)acoreTextView
receivedTouchOnData:(NSDictionary *)data
77. {
78. NSURL *url = [data objectForKey:FTCoreTextDataURL];
79. if (!url) return;
80. [[UIApplication sharedApplication] openURL:url];
81. }<span style="font-size: 18px;">
82. </span>
效果图:
效果 图1 效果 图2
效果图3 注:效果图1、效果图2是文本数据绘制之后显示的界面。接,弹出的新的界面。
CoreText的框架图(有助于理解其中的一些方法的实现): 效果图3是点击文本中的超链