Getting CGRect for text in a UITextView for the purpose of highlighting with a CALayer
Asked Answered
D

2

5

I am trying to draw a transparent CALayer in a UITextView in order to highlight matched text in a search.

I've figured out the correct way to do this, but still haven't found the correct coordinates. I need to find the origin of the text container. Right now, I get the textView's origin, and offset the layer's origin by that:

NSRange match = [[[self textView]text]rangeOfString:@"predict the future"];
NSRange glyphRange = [manager glyphRangeForCharacterRange:match actualCharacterRange:NULL];

CGRect textRect = [manager boundingRectForGlyphRange:glyphRange inTextContainer:[[self textView]textContainer]];

CGPoint textViewOrigin = self.textView.frame.origin;
textRect.origin.x += (textViewOrigin.x / 2);
textRect.origin.y += (textViewOrigin.y / 2);


CALayer* roundRect = [CALayer layer];
[roundRect setFrame:textRect];
[roundRect setBounds:textRect];

[roundRect setCornerRadius:5.0f];
[roundRect setBackgroundColor:[[UIColor blueColor]CGColor]];
[roundRect setOpacity:0.2f];
[roundRect setBorderColor:[[UIColor blackColor]CGColor]];
[roundRect setBorderWidth:3.0f];
[roundRect setShadowColor:[[UIColor blackColor]CGColor]];
[roundRect setShadowOffset:CGSizeMake(20.0f, 20.0f)];
[roundRect setShadowOpacity:1.0f];
[roundRect setShadowRadius:10.0f];

[[[self textView]layer]addSublayer:roundRect];

I get the following result if I move the text field, or if I don't divide the offsets by 2: The layer frame is off

I'd like to know if i'm on the right track and also how to find the NSTextContainer object's origin if so.

Diploid answered 15/12, 2013 at 20:33 Comment(4)
if your match is across two lines, you'll get a rectangle that encompasses the whole two linesHennessy
yeah I'm on to that problem next. But the point of this was to figure out how to draw the layer in the correct position over text.Diploid
I've figured it out. I'm going to post an answer shortly.Diploid
Hi gentlemen, do you have any solution for layer being drawn across two lines covering the whole lines please?Fasces
D
8

To position the layer correctly, you only have to add self.textView.textContainerInset.top to textRect.origin.y, not the text view's origin.

But as I said in the comment, it won't work nicely if your match is across two lines. You may want to set the background colour of the matched range to highlight it, (using the attributedText property), but then you can't add the rounded corners or shadow.

Dragonet answered 16/12, 2013 at 0:5 Comment(5)
+1 for the correct answer for the position issue (you beat me too it). I actually need to use a CALayer because I don't want to change attributes on the text, just to highlight search results. The set up the above code that way just to figure out how to get geometry from the text (a starting point) and get a layer drawn correctly.Diploid
also, the glyph range may not be the same as the character range with some characters, you should convert it with glyphRangeForCharacterRange:actualCharacterRange:Hennessy
That's what I used to get the glyph range. Second line.Diploid
@Zydeco is there any way to add the rounder corners on the highlighted text when the matched text is across two lines? I am having this exact problem, the rect is being drawn incorrectly across two lines.Fasces
I asked my question here: #20689975Fasces
D
1

[textView textContainerInset]

Using the origin of the text view will not work because the insets may be changed somewhere else. An example would be if the parent view controller’s automaticallyAdjustsScrollViewInsets property is YES, or some custom text container layout is going on.

UIEdgeInsets textContainerInset = [[self textView]textContainerInset];
textRect.origin.x += textContainerInset.left;
textRect.origin.y += textContainerInset.top;

This is a solution for getting the geometry correct, but not if the text spans two lines.

Diploid answered 16/12, 2013 at 0:19 Comment(3)
Hi @Lone Gunman. Do you have any solution for the problem when text spans two lines? Currently it draws a big rect across two lines for me.Fasces
i'm having issues with the double lines. Posted it in a new question: #20695442Diploid
Found the solution for the double line issue: #20695442Diploid

© 2022 - 2024 — McMap. All rights reserved.