Получение CGRect для текста в UITextView с целью выделения с помощью CALayer

Я пытаюсь нарисовать прозрачный CALayer в UITextView, чтобы выделить совпадающий текст при поиске.

Я нашел правильный способ сделать это, но до сих пор не нашел правильных координат. Мне нужно найти источник текстового контейнера. Прямо сейчас я получаю происхождение textView и смещаю происхождение слоя на это:

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];

Я получаю следующий результат, если перемещаю текстовое поле или не делю смещения на 2: Рамка слоя выключена

Я хотел бы знать, на правильном ли я пути, а также как найти источник объекта NSTextContainer, если это так.


person Myron Slaw    schedule 15.12.2013    source источник
comment
если ваше совпадение находится на двух строках, вы получите прямоугольник, охватывающий все две строки   -  person Jesús A. Álvarez    schedule 16.12.2013
comment
да, я перехожу к этой проблеме. Но смысл этого заключался в том, чтобы выяснить, как нарисовать слой в правильном положении над текстом.   -  person Myron Slaw    schedule 16.12.2013
comment
Я понял это. Я собираюсь опубликовать ответ в ближайшее время.   -  person Myron Slaw    schedule 16.12.2013
comment
Привет, джентльмены, у вас есть какое-нибудь решение для слоя, рисуемого через две линии, покрывающие целые линии, пожалуйста?   -  person ilteris    schedule 16.12.2013


Ответы (2)


Чтобы правильно расположить слой, вам нужно только добавить self.textView.textContainerInset.top к textRect.origin.y, а не источнику текстового представления.

Но, как я сказал в комментарии, это не сработает, если ваше совпадение находится на двух строках. Вы можете установить цвет фона совпадающего диапазона, чтобы выделить его (используя свойство attributedText), но тогда вы не сможете добавить закругленные углы или тень.

person Jesús A. Álvarez    schedule 16.12.2013
comment
+1 за правильный ответ на вопрос о позиции (вы меня тоже обыграли). На самом деле мне нужно использовать CALayer, потому что я не хочу менять атрибуты текста, просто чтобы выделить результаты поиска. Приведенный выше код настроен таким образом, чтобы выяснить, как получить геометрию из текста (отправной точки) и правильно отрисовать слой. - person Myron Slaw; 16.12.2013
comment
Кроме того, диапазон глифа может не совпадать с диапазоном символов с некоторыми символами, вы должны преобразовать его с помощью glyphRangeForCharacterRange:actualCharacterRange: - person Jesús A. Álvarez; 16.12.2013
comment
Это то, что я использовал, чтобы получить диапазон глифов. Вторая линия. - person Myron Slaw; 16.12.2013
comment
@Zydeco Есть ли способ добавить более круглые углы к выделенному тексту, когда совпадающий текст находится на двух строках? У меня именно эта проблема, прямоугольник неправильно рисуется через две строки. - person ilteris; 16.12.2013
comment
Я задал свой вопрос здесь: stackoverflow.com/questions/20689475/ - person ilteris; 19.12.2013

[textView textContainerInset]

Использование источника текстового представления не будет работать, потому что вставки могут быть изменены где-то еще. Примером может быть, если свойство AutomaticAdjustsScrollViewInsets родительского контроллера представления имеет значение YES, или происходит какой-либо пользовательский макет текстового контейнера.

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

Это решение для правильной геометрии, но не в том случае, если текст занимает две строки.

person Myron Slaw    schedule 16.12.2013
comment
Привет @Lone Gunman. Есть ли у вас решение проблемы, когда текст занимает две строки? В настоящее время он рисует для меня большой прямоугольник через две строки. - person ilteris; 16.12.2013
comment
у меня проблемы с двойными линиями. Разместил это в новом вопросе: stackoverflow.com/questions/20694942/ - person Myron Slaw; 20.12.2013
comment
Нашел решение проблемы с двойной строкой: lines" title="использование калайера для выделения текста в uitextview, который занимает несколько строк"> stackoverflow.com/questions/20694942/ - person Myron Slaw; 29.12.2013