Using Core Text text highlighting

Using Core Text text highlighting
text highlight the effect of.Png

Before the implementation of a UILabel click on the text to achieve text highlighting effect. In fact, is the use of Core Text implementation: text CFAttributedString using correlation method Core Text (rich text) drawrect: attributes override the UILabel text, each click change after the CFAttributedString property and Core Text redraw UILabel, first look at the CoreText.


Frame level

Core Text is an advanced, low-level technology for laying out text and handling fonts. Core Text works directly with Core Graphics (CG), also known as Quartz, which is the high-speed graphics rendering engine that handles two-dimensional imaging at the lowest level in OS X and iOS.

The official document mentions that the Core Text is a low-level text layout that handles the font of the framework, directly interacting with the Core Graphics. Core Text is actually implemented in C, so it is very flexible to use, and can be drawn directly on the context.

Using Core Text text highlighting
related framework hierarchy.Png

from the framework of the hierarchical structure, it can be proved that the CoreText is quite low-level, the use of Core Text to achieve the function of all the controls for his bottom.

Drawing principle

Using Core Text text highlighting
Text Core layout engine structure.Png

Figure Core is a hierarchical structure of Text Object.

CTFramesetter: the top layer in the hierarchy, accepting a attributed string and a graphics path as input, framesetter can generate frames of text (CTFrameRef). Each CTFrame object represents a paragraph. CTFramesetter will use typesetter object when producing frames (CTTypesetterRef), framesetter is responsible for the application of paragraph style to frame, typesetter is responsible for the rich text characters converted to graphical form and fill in the form frame line object (CTLine).

CTLine: each CTFrame object contains one or more line (CTLine) objects, each line represents a line of text.

CTRun: each CTLine object contains an array of glyph run (CTRun) objects. A glyph run is a series of direction (and) with the same attributes of continuous glyph. A CTLine object may contain one or more CTRun object.

Since the CTFrame can be directly drawn to their own graphics context, we can change the properties of the NSAttributedString object to change the appearance of CTFrame object draw out.

Click highlight

Get click position

Click to get / / Character in the whole text in Index func indexOf (point: CGPoint ->); CFIndex{reversedPoint = CGPoint let / / reversal coordinate (x: point.x, y: self.bounds.maxY - point.y) / / lines lines = let for paragraph CTFrameGetLines (mCTFrame!) as NSArray lines origin var / / get the coordinates (originsArray = [CGPoint] repeating:.Zero, count: lines.count CTFrameGetLineOrigins (mCTFrame), CFRangeMake! (0, lines.count), & for I in 0..< originsArray) {if (reversedPoint.y; lines.count > originsArray[i].y) {/ / let traversal to click on the line = lines.object (at: I) as! CTLine / / line and click on the corresponding coordinate acquisition point Hit character Index CTLineGetStringIndexForPosition (line, reversedPoint)}} return 0} in

Index can be obtained by calculating the corresponding String Index Range.

About func CTLineGetStringIndexForPosition (line: CTLine position: CGPoint _, _) -> CFIndex: this method is based on the analysis of the line click character was created by typesetter which, and the analysis of its corresponding character position.

Add attribute attributes

Override func draw (_ rect: CGRect) {let context = UIGraphicsGetCurrentContext (context)?.convertCoordinateSystem (view: self) let mutablePath UIBezierPath (rect: rect) = let mutableAttributeString = NSMutableAttributedString (string: self.text!) mutableAttributeString.addAttribute (NSFontAttributeName, value: ARLTICLE_CONTENT_FONT, range: NSMakeRange (0, mutableAttributeString.length)) / / text format let (style = NSMutableParagraphStyle) style.lineSpacing = LINE_SPACING style.alignment =.Justified (mutableAttributeString.addAttribute NSParagraphStyleAttributeName, value: style, range: NSMakeRange (0, mutableAttributeString.length)) / * * Omitted here calculation highlight range related code * / / / range String Range mutableAttributeString.addAttributes: high ([NSBackgroundColorAttributeName: MAIN_COLOR, NSForegroundColorAttributeName: HIGHT_LIGHT_TEXT_COLOR], range:range highlightWordsLoaction.removeLast (allowSelectWord)}}) = true let framesetter = CTFramesetterCreateWithAttributedString (mutableAttributeString) / / mCTFrame had previously declared mCTFrame = (framesetter CTFramesetterCreateFrame, CFRangeMake (0, mutableAttributeString.length), mutablePath.cgPath (CTFrameDraw, NIL) mCTFrame!, context)}!


Do not fill the pit from second to highlight the position forward offset, and the UILabel height calculation is not accurate, complete complementary solution.