重庆分公司,新征程启航

为企业提供网站建设、域名注册、服务器等服务

ios开发图文混排,ios图文混排第三方

iOS中不同形式的图文混排技术的实现总结

在我们iOS项目开发中,我们经常会遇到图文混排的情况,那么什么是图文混排呢?

创新互联自2013年创立以来,先为伊金霍洛等服务建站,伊金霍洛等地企业,进行企业商务咨询服务。为伊金霍洛企业网站制作PC+手机+微官网三网同步一站式服务解决您的所有建站问题。

那么什么是图文混排呢?

在这里我给大家举个例子大家就明白了,例如我们在微博类,社交聊天应用中常常会遇到各种表情,各种链接的解析。问题来了,图文混排的形式有哪些呢?

图文混排的形式:

1.富文本(attributeString)

我们可以采用attributeString来进行图文混排.例如一个文字上插入一个图片

什么是coreText?

iOS/OSX中用于描述富文本的类是NSAttributedString,顾名思义,它比NSString多了Attribute的概念。它可以包含很多属性,粗体,斜体,下划线,颜色,背景色等等,每个属性都有其对应的字符区域。在OSX上我们只需解析完毕相应的数据,准备好NSAttributedString即可,底层的绘制完全可以交给相应的控件完成。但是在iOS上就没有这么方便,想要绘制Attributed String就需要用到CoreText了。(当然iOS6之后已经有AttributedLabel了。)

使用CoreText进行NSAttributedString的绘制,最重要的两个概念就是CTFrameSetter和CTFrame。

其中CTFramesetter是由CFAttributedString(NSAttributedString)初始化而来,可以认为它是CTFrame的一个Factory,通过传入CGPath生成相应的CTFrame并使用它进行渲染:直接以CTFrame为参数使用CTFrameDraw绘制或者从CTFrame中获取CTLine进行微调后使用CTLineDraw进行绘制。

一个CTFrame是由一行一行的CLine组成,每个CTLine又会包含若干个CTRun(既字形绘制的最小单元),通过相应的方法可以获取到不同位置的CTRun和CTLine,以实现对不同位置touch事件的响应。

ios7 开始,功能强大,简单易用,也可以进行图文混排. TextKit并没有新增的类,他是在原有的文本显示控件上的封装,可以使用平时我们最喜欢使用的UILabel,UITextField,UITextView里面就可以使用了。现在来详细介绍一下.

1).NSAtrributedString

这是所有TextKit的载体,所有的信息都会输入到NSAttributedString里面,然后将这个String输入到Text控件里面就可以显示了。

2).NSTextAttachment

iOS7新增的类,作为文本的附件,可以放文件,可以放数据,以 NSAttachmentAttributeName这个key放入NSAttributedString里面,在表情混排这里,我们将放入image。

3).重载NSTextAttachment

本来是可以直接使用NSTextAttachment,但是我们需要根据文字大小来改变表情图片的大小,于是我们需要重载NSTextAttachment,NSTextAttachment实现了NSTextAttachmentContainer,可以给我们改变返回的图像,图像的大小。

利用UIWebView加载HTML实现图文混排

但是注意:UIWebView本身有内存问题,占用内存相比较而较大不推荐,但是使用比较灵活,

知乎的ios app里面的图文混排是怎么实现的,是加载的html吗

iOS实现图文混排的两个方法

如果你想自定义文本的布局,例如像QQ、微信这样的应用中使用表情,那你多半会用到CoreText,CoreText是iOS、OSX平台的文本处理低层的框架, 可以实现任意的文字编排,更多详细信息请戳官方文档,一般来说, 我们们用下面的代码来实现图文混排:

text = [[NSMutableAttributedString alloc] initWithString:@""];

NSAttributedString *txt1 = [[NSAttributedString alloc] initWithString:@"测试"];

[text appendAttributedString:txt1];

[txt1 release];

CTRunDelegateCallbacks callback;

callback.version = kCTRunDelegateVersion1; //必须指定,否则不会生效,没有回调产生。

callback.dealloc = deallocCallback;

callback.getAscent = getAscent;

callback.getDescent = getDescent;

callback.getWidth = getWidth;

NSDictionary *imgAttr = [[NSDictionary dictionaryWithObjectsAndKeys:@100, @"width", nil] retain];

CTRunDelegateRef delegate = CTRunDelegateCreate(callback, imgAttr);

NSDictionary *txtDelegate = [NSDictionary dictionaryWithObjectsAndKeys:(id)delegate, (NSString*)kCTRunDelegateAttributeName, @100, @"width", nil];

NSAttributedString *imgField = [[[NSAttributedString alloc] initWithString:@" " attributes:txtDelegate] autorelease];

[text appendAttributedString:imgField];

[text appendAttributedString:[[[NSAttributedString alloc] initWithString: @"结束"] autorelease]];

CGMutablePathRef pathRef = CGPathCreateMutable();

CGPathAddRect(pathRef, NULL, CGRectMake(0, 0, self.frame.size.width, self.frame.size.height));

framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)text);

ctFrame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), pathRef, NULL);

CFArrayRef lines = CTFrameGetLines(ctFrame);

CGPoint origins[CFArrayGetCount(lines)];

CTFrameGetLineOrigins(ctFrame, CFRangeMake(0, 0), origins);

for (int i = 0; i CFArrayGetCount(lines); i++) {

CTLineRef line = CFArrayGetValueAtIndex(lines, i);

CFArrayRef runs = CTLineGetGlyphRuns(line);

for (int j = 0; j CFArrayGetCount(runs); j++) {

CTRunRef run = CFArrayGetValueAtIndex(runs, j);

CGPoint lineOrigin = origins[i];

NSDictionary *meta = (NSDictionary*)CTRunGetAttributes(run);

if (meta ([meta valueForKey:@"width"] != nil)) {

imageLocation.y = lineOrigin.y;

CGFloat offset = CTLineGetOffsetForStringIndex(line, CTRunGetStringRange(run).location, NULL);

imageLocation.x = lineOrigin.x + offset + self.frame.origin.x;

}

}

}

CFRelease(pathRef);

[self setNeedsDisplay];

一直以来,我认为只有这种方法实现。好吧,其实我没有想过有没有其它实现方法的问题。直到有一天看类似效果的代码时惊奇的发现:怎么 没有CTRunDelegate? 于是就仔细想了一下这个问题,创建CTFrame的时候会指定一个path,通常这个path我会使用一个CGRect完事,然后在 有图片的地方使用CTRunDelegate处理一下,但其实完全可以使用CGMutablePath来画出一块不规则的文本路径,比如:这样,就可以在预定的位置画图片了,而不用会CTRunDelegate来特殊处理,这种方式比较适合图片位置固定的应用。

转自madongsheng

iOS如何实现图文混排?

可以使用CoreText, 但学习的话,也要花不短的时间。

或者你可以换一种思路, 例如上面的内容,在接口端解析内容返回一个内容数组。文字是一组,一张图是一组。这样在ios端显示时,只需要解析这个数组就可以了。如果是文本用UILabel展示,如果是图片链接,用UIImageView展示。

ios开发,关于图文混排

图文混排

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原点的值

仅供参考

iOS开发之富文本(图文混排)(全)

NSMutableAttributedString*abs = [[NSMutableAttributedString alloc] initWithString:text];

富文本:

字符间距正值间距加宽,负值间距变窄

typedefNS_ENUM(NSInteger, NSUnderlineStyle) {

NSUnderlineStyleNone                                    =0x00,

NSUnderlineStyleSingle                                  =0x01,

NSUnderlineStyleThickNS_ENUM_AVAILABLE(10_0,7_0)      =0x02,

NSUnderlineStyleDoubleNS_ENUM_AVAILABLE(10_0,7_0)    =0x09,

NSUnderlinePatternSolidNS_ENUM_AVAILABLE(10_0,7_0)      =0x0000,

NSUnderlinePatternDotNS_ENUM_AVAILABLE(10_0,7_0)        =0x0100,

NSUnderlinePatternDashNS_ENUM_AVAILABLE(10_0,7_0)      =0x0200,

NSUnderlinePatternDashDotNS_ENUM_AVAILABLE(10_0,7_0)    =0x0300,

NSUnderlinePatternDashDotDotNS_ENUM_AVAILABLE(10_0,7_0) =0x0400,

NSUnderlineByWordNS_ENUM_AVAILABLE(10_0,7_0)            =0x8000

} NS_ENUM_AVAILABLE(10_0, 6_0);

和这三个任一个都好使,NSVerticalGlyphFormAttributeName,NSObliquenessAttributeName,NSExpansionAttributeName)

目前只有一个可用效果NSTextEffectLetterpressStyle (凸版印刷效果)

不能在UILabel和UITextField使用,只能用UITextView来进行,实现他的代理,在代理方法里面进行URL跳转

- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange     // 该方法返回YES就能打开URL,NO不做任何事情

上面的方法已经弃用了,取而代之的是下面的方法:

- (BOOL)textView:(UITextView*)textView shouldInteractWithURL:(NSURL*)URL inRange:(NSRange)characterRange interaction:(UITextItemInteraction)interaction

注:

1.一定要实现UITextView的代理才能进行URL跳转

2.textView的editable属性修改为NO,在编辑时不可点击

//LRE: NSWritingDirectionLeftToRight|NSWritingDirectionEmbedding, 

RLE: NSWritingDirectionRightToLeft|NSWritingDirectionEmbedding,

LRO: NSWritingDirectionLeftToRight|NSWritingDirectionOverride, 

RLO: NSWritingDirectionRightToLeft|NSWritingDirectionOverride,

0为水平排版的字,1为垂直排版的字。注意,在iOS中, 总是以横向排版


名称栏目:ios开发图文混排,ios图文混排第三方
文章路径:http://cqcxhl.cn/article/dsgcshi.html

其他资讯

在线咨询
服务热线
服务热线:028-86922220
TOP