I have a subclass of UIView that implements code to draw CoreText. In the application, that UIView is drawn inside a UIScrollView. Here is the code that I currently use in drawRect: to render an NSAttributedString:
CGContextRef context = UIGraphicsGetCurrentContext();
float viewHeight = self.bounds.size.height;
CGContextTranslateCTM(context, 0, viewHeight);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextSetTextMatrix(context, CGAffineTransformMakeScale(1.0, 1.0));
CGMutablePathRef path = CGPathCreateMutable();
CGRect bounds = CGRectMake(PADDING_LEFT, -PADDING_TOP, self.bounds.size.width-20.0, self.bounds.size.height);
CGPathAddRect(path, NULL, bounds);
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFMutableAttributedStringRef)attrString);
CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL);
CFRelease(framesetter);
CFRelease(path);
CTFrameDraw(frame, context);
In my NSAttributedString, I have certain text attributes to color the text.
What I need help with is conceptually, how should this be accomplished? I am confused by all the various methods of drawing frames, layers, etc. I have tried to review several books and other resources, but I feel like I'm missing some basic stuff.
Here are my requirements:
I would greatly appreciate any assistance.
Here is what I have tried so far:
I added a new UIView as a subview to the UIScrollView to contain the highlights. I then add individual UIViews for the highlights themselves. When I create dummy "test" highlights, they appear correctly under the CoreText view. I can also easily change the highlight color. However, when I go to acquire actual information about the lines from the CoreText view to create real highlights, it returns zero lines. Could this be because drawRect isn't finished drawing yet or something else?
Here are some questions:
I have seen this open source project:
https://github.com/Cocoanetics/NSAttributedString-Additions-for-HTML
This is amazing what it can do, but is far more complex and detailed than I need. The code renders each individual glyph run using CoreText and permits highlighting, which is awesome. However, I am trying to keep my code simple and lightweight. I know very little about CoreGraphics, CoreAnimation or CoreText.
I have also seen this question:
Core Text - Get Pixel Coordinates from NSRange
The answer to the question provides the calls to determine the bounds of a Rect for a given range in a given line. I think I can figure out those calls.
UPDATE
Here is what I have done now. I'm sure this is wrong, but it is the only way I could find to make it work...
This does not call drawRect each time a highlight is added to the container or color changed. However, I know this isn't an ideal solution. Problems with this solution:
Your basic idea isn't too bad for highlighting. I don't know if it's really easier than just highlighting the glyphs while you draw, but it's not a bad idea, and makes it easy to turn on and off highlighting, so that's pretty nice.
Rather than creating lots of views, put your Core Text onto a CALayer
instead. Then you can create additional highlighting layers to put over the text. This keeps everything inside of a single view. Layers are much cheaper than views. If you're just trying to do "highlighter" style highlighting, then you can just set the backgroundColor
and frame
for the layers and you're done.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With