iOS實現(xiàn)圖文混排的兩個方法
創(chuàng)新互聯(lián)建站是一家專注于成都網(wǎng)站設(shè)計、網(wǎng)站制作與策劃設(shè)計,寧洱網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)建站做網(wǎng)站,專注于網(wǎng)站建設(shè)10多年,網(wǎng)設(shè)計領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:寧洱等地區(qū)。寧洱做網(wǎng)站價格咨詢:18980820575
如果你想自定義文本的布局,例如像QQ、微信這樣的應(yīng)用中使用表情,那你多半會用到CoreText,CoreText是iOS、OSX平臺的文本處理低層的框架, 可以實現(xiàn)任意的文字編排,更多詳細(xì)信息請戳官方文檔,一般來說, 我們們用下面的代碼來實現(xiàn)圖文混排:
text = [[NSMutableAttributedString alloc] initWithString:@""];
NSAttributedString *txt1 = [[NSAttributedString alloc] initWithString:@"測試"];
[text appendAttributedString:txt1];
[txt1 release];
CTRunDelegateCallbacks callback;
callback.version = kCTRunDelegateVersion1; //必須指定,否則不會生效,沒有回調(diào)產(chǎn)生。
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: @"結(jié)束"] 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];
一直以來,我認(rèn)為只有這種方法實現(xiàn)。好吧,其實我沒有想過有沒有其它實現(xiàn)方法的問題。直到有一天看類似效果的代碼時驚奇的發(fā)現(xiàn):怎么 沒有CTRunDelegate? 于是就仔細(xì)想了一下這個問題,創(chuàng)建CTFrame的時候會指定一個path,通常這個path我會使用一個CGRect完事,然后在 有圖片的地方使用CTRunDelegate處理一下,但其實完全可以使用CGMutablePath來畫出一塊不規(guī)則的文本路徑,比如:這樣,就可以在預(yù)定的位置畫圖片了,而不用會CTRunDelegate來特殊處理,這種方式比較適合圖片位置固定的應(yīng)用。
轉(zhuǎn)自madongsheng
開發(fā)中有時候需要一個圖片icon加一串描述的樣式,這時候用圖文混排就減少了很多UI方面的工工作
效果如下
你的意思是計算字符串占屏幕的寬度吧,大小寫不一樣,漢子英文也不一樣,你可以把文字裝在Label里面,然后讓label sizetofit 然后根據(jù)Label的寬度就知道這一串字符占多少屏幕了
圖文混排
CTFrameRef textFrame // coreText 的 frame
CTLineRef line // coreText 的 line
CTRunRef run // line 中的部分文字
相關(guān)方法:
CFArrayRef CTFrameGetLines (CTFrameRef frame ) //獲取包含CTLineRef的數(shù)組
void CTFrameGetLineOrigins(
CTFrameRef frame,
CFRange range,
CGPoint origins[] ) //獲取所有CTLineRef的原點
CFRange CTLineGetStringRange (CTLineRef line ) //獲取line中文字在整段文字中的Range
CFArrayRef CTLineGetGlyphRuns (CTLineRef line ) //獲取line中包含所有run的數(shù)組
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) 根據(jù)保存的表情文字的Range計算表情圖片的Frame
textFrame 通過CTFrameGetLines 獲取所有l(wèi)ine的數(shù)組 lineArray
遍歷lineArray中的line通過CTLineGetGlyphRuns獲取line中包含run的數(shù)組 runArray
遍歷runArray中的run 通過CTRunGetStringRange獲取run的Range
判斷表情文字的location是否在run的Range
如果在 通過CTLineGetOffsetForStringIndex獲取x的值 y的值為line原點的值
僅供參考
可以使用CoreText, 但學(xué)習(xí)的話,也要花不短的時間。
或者你可以換一種思路, 例如上面的內(nèi)容,在接口端解析內(nèi)容返回一個內(nèi)容數(shù)組。文字是一組,一張圖是一組。這樣在ios端顯示時,只需要解析這個數(shù)組就可以了。如果是文本用UILabel展示,如果是圖片鏈接,用UIImageView展示。
在我們iOS項目開發(fā)中,我們經(jīng)常會遇到圖文混排的情況,那么什么是圖文混排呢?
那么什么是圖文混排呢?
在這里我給大家舉個例子大家就明白了,例如我們在微博類,社交聊天應(yīng)用中常常會遇到各種表情,各種鏈接的解析。問題來了,圖文混排的形式有哪些呢?
圖文混排的形式:
1.富文本(attributeString)
我們可以采用attributeString來進行圖文混排.例如一個文字上插入一個圖片
什么是coreText?
iOS/OSX中用于描述富文本的類是NSAttributedString,顧名思義,它比NSString多了Attribute的概念。它可以包含很多屬性,粗體,斜體,下劃線,顏色,背景色等等,每個屬性都有其對應(yīng)的字符區(qū)域。在OSX上我們只需解析完畢相應(yīng)的數(shù)據(jù),準(zhǔn)備好NSAttributedString即可,底層的繪制完全可以交給相應(yīng)的控件完成。但是在iOS上就沒有這么方便,想要繪制Attributed String就需要用到CoreText了。(當(dāng)然iOS6之后已經(jīng)有AttributedLabel了。)
使用CoreText進行NSAttributedString的繪制,最重要的兩個概念就是CTFrameSetter和CTFrame。
其中CTFramesetter是由CFAttributedString(NSAttributedString)初始化而來,可以認(rèn)為它是CTFrame的一個Factory,通過傳入CGPath生成相應(yīng)的CTFrame并使用它進行渲染:直接以CTFrame為參數(shù)使用CTFrameDraw繪制或者從CTFrame中獲取CTLine進行微調(diào)后使用CTLineDraw進行繪制。
一個CTFrame是由一行一行的CLine組成,每個CTLine又會包含若干個CTRun(既字形繪制的最小單元),通過相應(yīng)的方法可以獲取到不同位置的CTRun和CTLine,以實現(xiàn)對不同位置touch事件的響應(yīng)。
ios7 開始,功能強大,簡單易用,也可以進行圖文混排. TextKit并沒有新增的類,他是在原有的文本顯示控件上的封裝,可以使用平時我們最喜歡使用的UILabel,UITextField,UITextView里面就可以使用了?,F(xiàn)在來詳細(xì)介紹一下.
1).NSAtrributedString
這是所有TextKit的載體,所有的信息都會輸入到NSAttributedString里面,然后將這個String輸入到Text控件里面就可以顯示了。
2).NSTextAttachment
iOS7新增的類,作為文本的附件,可以放文件,可以放數(shù)據(jù),以 NSAttachmentAttributeName這個key放入NSAttributedString里面,在表情混排這里,我們將放入image。
3).重載NSTextAttachment
本來是可以直接使用NSTextAttachment,但是我們需要根據(jù)文字大小來改變表情圖片的大小,于是我們需要重載NSTextAttachment,NSTextAttachment實現(xiàn)了NSTextAttachmentContainer,可以給我們改變返回的圖像,圖像的大小。
利用UIWebView加載HTML實現(xiàn)圖文混排
但是注意:UIWebView本身有內(nèi)存問題,占用內(nèi)存相比較而較大不推薦,但是使用比較靈活,
新聞標(biāo)題:ios開發(fā)圖文混編,ios混合開發(fā)
瀏覽地址:http://jinyejixie.com/article6/dsdgiog.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站改版、小程序開發(fā)、網(wǎng)站建設(shè)、網(wǎng)站制作、手機網(wǎng)站建設(shè)、營銷型網(wǎng)站建設(shè)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)