There are many times when you need to use a mix of graphics and text, such as expressions in chat bubbles, spaces, and expressions in Weibo, such as:
Hearts and words together.
The more complicated situation is that the expression is mixed between the words.
To do this, first describe the classes in iOS that display attribute text.
The class used for text display, in addition to the Text property, has the Attributedtext property, which is the nsattributedstring type, which enables different fonts, colors, and even the ability to display images as text in different text.
The use of this string is described below.
With a micro-blog content for the application of the scene, how to find out the expression, topics and other content, where the expression replaced with emoticons, topics such as highlighting.
The main content used here is: regular expression, nsattributedstring, nstextattachment and other knowledge.
"Regular expression"
The regular expression in the previous section (110) The basic use of regular expressions and the use of Regexkitlite is introduced, mainly to find all special locations and non-special locations.
"nsattributedstring"
This is a feature that allows you to set properties, display pictures, and so on for a specific range of text.
The following is an introduction to the normal string initialization nsattributedstring, and the expression ([< expression name), the topic (#< topic Content >#), the URL all highlight method.
① Initializes a property string with the text of the microblog string.
nsmutableattributedstring *attributedtext = [[Nsmutableattributedstring alloc] initwithstring:text];
② specifies the matching rule.
NSString *emotionpattern = @ "\\[[a-za-z\\u4e00-\\u9fa5]+\\]"; NSString *topicpattern = @ "#[0-9a-za-z\\u4e00-\\u9fa5]+#"; NSString *urlpattern = @ "[a-za-z]+://[^\\s]*"; NSString *pattern = [NSString stringwithformat:@ "%@|%@|%@", Emotionpattern,topicpattern,urlpattern];
③ the matching range is highlighted, you only need to call Nsmutableattributedstring's AddAttribute::: property to set the Color property for a specific range of text.
[Text Enumeratestringsmatchedbyregex:pattern usingblock:^ (Nsinteger capturecount, NSString *const __unsafe_ unretained *capturedstrings, const nsrange *capturedranges, volatile BOOL *const stop) { [attributedtext Addattribute:nsforegroundcolorattributename Value:[uicolor Bluecolor] range:*capturedranges]; }];
In this way, all matching ranges will be marked red.
④ sets the Attributedtext property of the control to the Attributedtext value created above.
"nstextattachment"
Nstextattachment can set images and bounds to specify pictures and sizes, and can be packaged as nsattributedstring, which is the basis for text-to-picture blending.
Here's how to create a nstextattachment with a small picture and wrap it in nsattributedstring.
Adjusting the x and y of bounds can fix the position of the picture in the string.
Nstextattachment *attach = [[Nstextattachment alloc] init]; Attach.image = [UIImage imagenamed:@ "Avatar_vgirl"]; Attach.bounds = CGRectMake (0,-3, 15, 15); nsattributedstring *emotionstr = [nsattributedstring Attributedstringwithattachment:attach];
"Replace the emoticons in the string with emoticons"
For simplicity, replace the contents of all expression positions with a picture avatar_vgirl.
A natural idea is to call Attributedtext's Replace method and replace the expression with a picture (nsattributedstring wrapped nstextattachment). But there is a problem with this approach.
For example, the following sentence:
Today sent [laughter cry] a very interesting thing [laughs cry].
Replace the first expression [laughter cry] as a picture, the length of the string may change, at this point when processing the second expression, the calculated position may be wrong, so you should find all the expression position and then unified replacement.
So we can use Regexkitlite two methods, respectively find matching and unmatched, save them up, and then according to the position of the order, and finally in sequence splicing, splicing for the expression for pictures, other special words Fugauliang, the rest of the normal display.
Because we want to put the text and the range into the array, so we should define a model, for the sake of convenience, set two members to store the current part is not the expression, is not special content.
The code for the model is as follows:
@interface Textsegment:nsobject@property (nonatomic, copy) NSString *text; @property (nonatomic, assign) Nsrange range;@ Property (Nonatomic, assign, getter=isspecial) bool special; @property (nonatomic, assign, getter=isemotion) bool Emotion ; @end
Assuming the text is the entire content of the microblog, the following code implements the special content and non-special content into the array, and determine whether it is an expression, the expression is characterized by [], using Hasprefix: and Hassufix: Judgment.
NSString *emotionpattern = @ "\\[[a-za-z\\u4e00-\\u9fa5]+\\]"; NSString *topicpattern = @ "#[0-9a-za-z\\u4e00-\\u9fa5]+#"; NSString *urlpattern = @ "[a-za-z]+://[^\\s]*"; NSString *pattern = [NSString stringwithformat:@ "%@|%@|%@", Emotionpattern,topicpattern,urlpattern]; Replace [expression] with attachment image, cannot use replace and insert, because will change the relative position of the back, should get all position first, and then unify to revise. Special and non-special parts should be scattered and then spliced. Nsmutablearray *parts = [Nsmutablearray array]; [Text Enumeratestringsmatchedbyregex:pattern usingblock:^ (Nsinteger capturecount, NSString *const __unsafe_ unretained *capturedstrings, const nsrange *capturedranges, volatile BOOL *const stop) {if (*capturedrang ES). Length = = 0) return; Textsegment *seg = [[Textsegment alloc] init]; Seg.text = *capturedstrings; Seg.range = *capturedranges; Seg.special = YES; Seg.emotion = [Seg.text hasprefix:@ "["] && [Seg.text hassuffix:@ "]"]; [Parts addobject:seg]; }]; [Text Enumeratestringsseparatedbyregex:pattern usingblock:^ (Nsinteger capturecount, NSString *const __unsafe_ unretained *capturedstrings, const nsrange *capturedranges, volatile BOOL *const stop) {if (*capturedrang ES). Length = = 0) return; Textsegment *seg = [[Textsegment alloc] init]; Seg.text = *capturedstrings; Seg.range = *capturedranges; Seg.special = NO; [Parts addobject:seg]; }];
Through the above code, we put all the text part into the parts array, for stitching convenience, we should follow the position of the beginning of the order, from front to back stitching.
This requires ordering the parts array based on the Range.location property of the model, which is more commonly sorted by block.
The block passes in two arrays of objects obj1, OBJ2, and requires that the collation nsorderedascending, Nsorderedsame, nsordereddescending be returned.
nsorderedascending refers to Obj1<obj2, the system is sorted by default in ascending order, so to achieve ascending, it is found that Obj1<obj2 should return nsorderedascending.
[Parts Sortusingcomparator:^nscomparisonresult (ID obj1, id obj2) { textsegment *ts1 = obj1; Textsegment *ts2 = obj2; Descending refers to the obj1>obj2 //ascending refers to the obj1<obj2 //To be implemented in ascending order, which is returned according to the above rules. //The system is sorted by default in ascending order. if (Ts1.range.location < ts2.range.location) { return nsorderedascending; } return nsordereddescending; }];
The next step is to stitch a newly created nsattributedstring from front to back, splicing different content depending on the content.
nsmutableattributedstring *attributedtext = [[Nsmutableattributedstring alloc] init]; Nsinteger cnt = Parts.count; for (Nsinteger i = 0; i < cnt; i++) {textsegment *ts = parts[i]; if (ts.isemotion) {nstextattachment *attach = [[Nstextattachment alloc] init]; Attach.image = [UIImage imagenamed:@ "Avatar_vgirl"]; Attach.bounds = CGRectMake (0,-3, 15, 15); nsattributedstring *emotionstr = [nsattributedstring Attributedstringwithattachment:attach]; [Attributedtext APPENDATTRIBUTEDSTRING:EMOTIONSTR]; }else if (ts.isspecial) {nsattributedstring *special = [[Nsattributedstring alloc] InitWithString:ts.text attribut Es:@{nsforegroundcolorattributename:[uicolor Redcolor]}]; [Attributedtext appendattributedstring:special]; }else{[Attributedtext appendattributedstring:[[nsattributedstring alloc] initWithString:ts.text]]; } }
Finally, set the Attributedtext to the control.
"Calculate the size of the nsattributedstring"
① before the text, calculate the size of the code as follows: You need to specify the font and range limits, generally limit the width, height is not limited (set to maxfloat), so that the correct multi-line size can be calculated.
Cgsize contentsize = [text Sizewithfont:contentfont constrainedtosize:cgsizemake (MAXW, Maxh)]
② for nsattributedstring, there are also methods for calculating dimensions,Note You must set the font for Attributedtext before calculating。
[Attributedtext addattribute:nsfontattributename Value:[uifont systemfontofsize:14] Range:NSMakeRange (0, Attributedtext.length)];
Then call Boundingrectwithsize::: Calculate the size, note that the options must be selected Options:nsstringdrawinguseslinefragmentorigin to get the correct size.
Cgsize contentsize = [Attributedtext boundingrectwithsize:cgsizemake (MaxWidth, maxheight) options: Nsstringdrawinguseslinefragmentorigin context:nil].size;
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
(111) Text-to-image blending base-using regular segmentation and stitching attribute strings