无限互联iOS开发课程安排(脱产班)

时间:2024.4.30

无限互联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>

无限互联iOS开发之图文混排研究

效果图:

无限互联iOS开发之图文混排研究

效果 图1 效果 图2

无限互联iOS开发之图文混排研究

效果图3 注:效果图1、效果图2是文本数据绘制之后显示的界面。接,弹出的新的界面。

CoreText的框架图(有助于理解其中的一些方法的实现): 效果图3是点击文本中的超链

无限互联iOS开发之图文混排研究

更多相关推荐:
《古典诗词》校本课程开发计划

《古典诗词欣赏》校本课程开发计划开发教师:主讲人:教学材料:《中学生必背古诗词》、《唐诗三百首》等课程类型:人文素养授课对象:七年级,八年级学生授课时间:每周一课时所需教学用具:《诗词中国》、《青少年最该读的古…

校本课程开发计划

20xx-20xx学年度石河完小上学期校本课程开发计划一、指导思想以《基础教育课程改革纲要》和课程标准为指导,结合“着眼素质、扎实基础、全面发展、办出特色”的学校办学宗旨和育人理念,坚持以学生发展为本,通过尊重…

课程开发计划

年级09级教育学2班姓名黄儒军学号20xx0512442我的美丽家乡垫江课程开发计划一开发背景一国家和地方层面国家提出的西部大开发战略是一项长远的规划而垫江正处于西部地区开发本课程让个多的人了解垫江有助于垫江的...

校本课程开发计划

校本课程开发计划一校本课程开发的原则1以学生为本的原则课程结构决定着学生的素质结构学校课程必须以促进学生全面发展为目的以培养学生的创新精神和实践能力为重点辩证处理好社会需要课程体系和学生发展的关系校本课程的研究...

学校校本课程开发计划

高里中心学校校本课程开发计划校本课程是以学校为基础开发出来的课程实施校本课程是实现学校的办学宗旨体现办学特色的有效途径学校在完成国家课程计划的前提下可以对国家课程进行部分改造可以自行开发和实施校本课程实施校本课...

小学校本课程开发计划及实施方案

小学校本课程开发计划及实施方案一校本课程开发的原则1以学生为本的原则课程结构决定着学生的素质结构学校课程必须以促进学生全面发展为目的以培养学生的创新精神和实践能力为重点辩证处理好社会需要课程体系和学生发展的关系...

课程管理系统项目开发计划书

项目开发计划书项目开发计划书11引言211编写目的212背景213定义214参考资料22项目概述221工作内容222主要参加人员323产品4231程序4232文件4233服务错误未定义书签234非移交的产品42...

校本课程开发实施计划

校本课程培训计划东尖山中学校本课程培训计划一校本课程开发的目标课程改革是整个基础教育改革的核心内容是适应时代发展和全面推进素质教育的重要举措更是增强国力积蓄未来国际竞争实力的战略措施校本课程开发实施则是基础教育...

足球校本课程开发计划

20xx20xx学年学校课程开发计划

数学校本课程开发与实施计划

数学校本课程开发与实施计划一指导思想以基础教育课程改革纲要和课程标准为指导结合着眼素质扎实基础全面发展办出特色的学校办学宗旨和育人理念坚持以学生发展为本通过尊重学生信任学生指导学生等手段和途径让每一位学生的个性...

泰光中学校本课程开发计划

泰光中学校本课程开发计划校本课程是以学校为基础开发出来的课程实施校本课程是实现学校的办学宗旨体现办学特色的有效途径学校在完成国家课程计划的前提下可以对国家课程进行部分改造可以自行开发和实施校本课程实施校本课程能...

校本课程开发实施方案

校本课程开发实施方案20xx20xx三年总体开发方案养马庄乡中学养马庄乡中学校本课程开发实施方案20xx20xx三年总体开发方案一指导思想校本课程是基础教育课程改革的重要组成部分做好校本课程的开发是落实新课程的...

课程开发计划(44篇)