(1) NSAttributedString
NSAttributedString 可以将一段文字中的部分文字设置单独的字体和颜色。
与UITouch结合可以实现点击不同文字触发不同事件的交互功能。
主要方法:
- (void)addAttribute:(NSString *)name value:(id)value range:(NSRange)range;
可以设置某段文字的字体名称,颜色,下滑线等信息。
- (void)removeAttribute:(NSString *)name range:(NSRange)range;
移除之前设置的字体属性值。
- (void)addAttributes:(NSDictionary *)attrs range:(NSRange)range;
存储某段文字包含的信息(包括字体属性或其它,也可以存储一些自定义的信息)
- (NSDictionary *)attributesAtIndex:(NSUInteger)location effectiveRange:(NSRangePointer)range;
通过location来获取某段文字中之前存储的信息NSDictionary
//设置字体
CTFontRef aFont =
CTFontCreateWithName((CFStringRef)textFont.fontName, textFont.pointSize,
NULL);
if (!aFont) return;
CTFontRef
newFont = CTFontCreateCopyWithSymbolicTraits(aFont, 0.0, NULL,
kCTFontItalicTrait, kCTFontBoldTrait); //将默认黑体字设置为其它字体
[self removeAttribute:(NSString*)kCTFontAttributeName
range:textRange];
[self
addAttribute:(NSString*)kCTFontAttributeName value:(id)newFont
range:textRange];
CFRelease(aFont);
CFRelease(newFont);
//设置字体颜色
[self
removeAttribute:(NSString*)kCTForegroundColorAttributeName
range:textRange];
[self
addAttribute:(NSString*)kCTForegroundColorAttributeName
value:(id)textColor.CGColor
range:textRange];
//设置对齐
换行
CTTextAlignment coreTextAlign =
kCTLeftTextAlignment;
CTLineBreakMode coreTextLBMode =
kCTLineBreakByCharWrapping;
CTParagraphStyleSetting
paraStyles[2]
=
{
{.spec =
kCTParagraphStyleSpecifierAlignment, .valueSize = sizeof(CTTextAlignment),
.value = (const
void*)&coreTextAlign},
{.spec =
kCTParagraphStyleSpecifierLineBreakMode, .valueSize = sizeof(CTLineBreakMode),
.value = (const
void*)&coreTextLBMode},
};
CTParagraphStyleRef
aStyle = CTParagraphStyleCreate(paraStyles, 2);
[self
removeAttribute:(NSString*)kCTParagraphStyleAttributeName
range:textRange];
[self
addAttribute:(NSString*)kCTParagraphStyleAttributeName value:(id)aStyle
range:textRange];
CFRelease(aStyle);
(2)Draw NSAttributedString
CGContextRef
cgc =
UIGraphicsGetCurrentContext();
CGContextSaveGState(cgc);
//图像方向转换
CGContextConcatCTM(cgc,
CGAffineTransformScale(CGAffineTransformMakeTranslation(0,
self.bounds.size.height), 1.f,
-1.f));
CTFramesetterRef framesetter
=
CTFramesetterCreateWithAttributedString((CFAttributedStringRef)weiBoText);
drawingRect
= self.bounds;
CGMutablePathRef path =
CGPathCreateMutable();
CGPathAddRect(path, NULL,
drawingRect);
textFrame =
CTFramesetterCreateFrame(framesetter,CFRangeMake(0,0), path,
NULL);
CGPathRelease(path);
CFRelease(framesetter);
CTFrameDraw(textFrame,
cgc);
CGContextRestoreGState(cgc);
(3)图文混排
CTFrameRef textFrame // coreText 的 frame
CTLineRef line // coreText 的 line
CTRunRef run // line 中的部分文字
相关方法:
CFArrayRef CTFrameGetLines
(CTFrameRef frame )
//获取包含CTLineRef的数组
void CTFrameGetLineOrigins(
CTFrameRef
frame,
CFRange range,
CGPoint
origins[] ) //获取所有CTLineRef的原点
CFRange CTLineGetStringRange (CTLineRef line ) //获取line中文字在整段文字中的Range
CFArrayRef CTLineGetGlyphRuns (CTLineRef line ) //获取line中包含所有run的数组
CFRange CTRunGetStringRange (CTRunRef run ) //获取run在整段文字中的Range
CFIndex CTLineGetStringIndexForPosition(
CTLineRef
line,
CGPoint position )
//获取点击处position文字在整段文字中的index
CGFloat
CTLineGetOffsetForStringIndex(
CTLineRef
line,
CFIndex charIndex,
CGFloat*
secondaryOffset ) //获取整段文字中charIndex位置的字符相对line的原点的x值
主要步骤:
1)计算并存储文字中保含的所有表情文字及其Range
2)替换表情文字为指定宽度的NSAttributedString
CTRunDelegateCallbacks
callbacks;
callbacks.version =
kCTRunDelegateVersion1;
callbacks.getAscent =
ascentCallback;
callbacks.getDescent =
descentCallback;
callbacks.getWidth =
widthCallback;
callbacks.dealloc =
deallocCallback;
CTRunDelegateRef
runDelegate = CTRunDelegateCreate(&callbacks,
NULL);
NSDictionary *attrDictionaryDelegate = [NSDictionary
dictionaryWithObjectsAndKeys:
(id)runDelegate,
(NSString*)kCTRunDelegateAttributeName,
[UIColor
clearColor].CGColor,(NSString*)kCTForegroundColorAttributeName,
nil];
NSAttributedString
*faceAttributedString = [[NSAttributedString alloc] initWithString:@"*"
attributes:attrDictionaryDelegate];
[weiBoText
replaceCharactersInRange:faceRange
withAttributedString:faceAttributedString];
[faceAttributedString
release];
3) 根据保存的表情文字的Range计算表情图片的Frame
textFrame 通过CTFrameGetLines 获取所有line的数组 lineArray
遍历lineArray中的line通过CTLineGetGlyphRuns获取line中包含run的数组 runArray
遍历runArray中的run 通过CTRunGetStringRange获取run的Range
判断表情文字的location是否在run的Range
如果在 通过CTLineGetOffsetForStringIndex获取x的值 y的值为line原点的值
4)Draw表情图片到计算获取到的Frame
(3)点击文字触发事件
主要步骤:
1) 根据touch事件获取点point
2) textFrame 通过CTFrameGetLineOrigins获取所有line的原点
3) 比较point和line原点的y值获取点击处于哪个line
4) line、point 通过CTLineGetStringIndexForPosition获取到点击字符在整段文字中的 index
5) NSAttributedString 通过index 用方法-(NSDictionary *)attributesAtIndex:(NSUInteger)location effectiveRange:(NSRangePointer)range 可以获取到点击到的NSAttributedString中存储的NSDictionary
6) 通过NSDictionary中存储的信息判断点击的哪种文字类型分别处理
转自http://ios-iphone.diandian.com/post/2012-03-06/15104770
确实是一个比较详细的总结了。以前开发中没用这个,用其他的虽然用其他的办法也能实现,但是麻烦了许多,浪费了许多时间
关于图文混排的的框架coreText,布布扣,bubuko.com
原文:http://www.cnblogs.com/lingzhiguiji/p/3578589.html