Как выделить CoreText с изменением цвета подсветки? - PullRequest
5 голосов
/ 21 июля 2011

У меня есть подкласс UIView, который реализует код для рисования CoreText.В приложении этот UIView рисуется внутри UIScrollView.Вот код, который я в настоящее время использую в drawRect: для рендеринга 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);

В моем NSAttributedString у меня есть определенные текстовые атрибуты для цвета текста.

Что мне нужно помочь сконцептуально, как это должно быть достигнуто?Меня смущают различные методы рисования рамок, слоев и т. Д. Я пытался просмотреть несколько книг и других ресурсов, но мне кажется, что мне не хватает некоторых базовых вещей.

Вот мои требования:

  1. Очевидно, что при изменении ориентации выделение необходимо перерисовать в новом месте.
  2. Необходимо выделить программным способом цвет подсветки для отдельных выделений.
  3. Идеально для работы, мне не нужно перерисовывать весь CoreText UIView, когда я просто изменяю цвет подсветки одного выделения.
  4. Отдельные Rects должны иметь возможность группироваться вместеобразуют одно выделение, поскольку выделение может охватывать диапазон, выходящий за пределы одного CTLine.
  5. В конечном счете, я хочу реализовать UIMenuController в представлении CoreText, поэтому я считаю, что выделение следует рисовать под CoreText UIView?

Буду очень признателен за любую помощь.

Вот что у меня естьдо сих пор пробовал:

Я добавил новый UIView в качестве подпредставления к UIScrollView, чтобы содержать основные моменты.Затем я добавляю отдельные UIViews для основных моментов.Когда я создаю фиктивные «тестовые» выделения, они правильно отображаются в представлении CoreText.Я также могу легко изменить цвет подсветки.Однако, когда я собираюсь получить фактическую информацию о линиях из представления CoreText для создания реальных бликов, он возвращает ноль линий.Может ли это быть из-за того, что drawRect еще не закончил рисование или что-то еще?

Вот несколько вопросов:

  1. Должен ли я добавить UIView в качестве подпредставления к UIScrollView, чтобы содержать всеосновные моменты с дополнительными подпредставлениями для каждого отдельного основного момента?Затем сохраните каждую выделенную область UIView во вложенном NSArray?
  2. Если я изменю цвет подсветки под CoreText UIView, это приведет к перерисовке всего UIView?Если да, то как я могу проектировать вокруг этого?
  3. Это правда, что если я хочу, чтобы CoreText UIView получал входные данные для UIMenuController, я должен поместить объекты подсветки под CoreText UIView?

Я видел этот проект с открытым исходным кодом:

https://github.com/Cocoanetics/NSAttributedString-Additions-for-HTML

Это удивительно, что он может сделать, но гораздо сложнее и детальнее, чем мне нужно.Код отображает каждый отдельный глиф, используя CoreText, и разрешает выделение, а это здорово.Тем не менее, я стараюсь сделать свой код простым и легким.Я очень мало знаю о CoreGraphics, CoreAnimation или CoreText.

Я также видел этот вопрос:

Базовый текст - получить координаты пикселей из NSRange

Ответ на вопрос предоставляет вызовы для определения границ Rect для данного диапазона в данной строке.Я думаю, что могу выяснить эти звонки.

ОБНОВЛЕНИЕ

Вот что я сделал сейчас.Я уверен, что это неправильно, но это единственный способ найти способ заставить его работать ...

  1. Создать UIView в качестве контейнера для добавления в UIScrollView в качестве подпредставления.
  2. Передайте UIView в CoreTextView.Я также передаю массив диапазонов строк в CoreTextView, чтобы указать, какие строки должны быть выделены.
  3. Добавить CoreTextView как подпредставление UIScrollView.Таким образом, UIView находится под CoreTextView.
  4. В функции drawRect: CoreTextView я рисую CoreText.Затем я вызываю функцию для вычисления основных моментов.
  5. Каждый NSRange проверяется по строкам и вычисляется CGRect каждого совпадения в строке.
  6. CGRect используется для создания нового UIView. Этот UIView добавляется как subView контейнера UIView. Он также добавляется в NSArray, чтобы я мог отслеживать его и при необходимости изменять цвет подсветки для отдельной подсветки.

Это не вызывает drawRect каждый раз, когда в контейнер добавляется подсветка или изменяется цвет. Однако я знаю, что это не идеальное решение. Проблемы с этим решением:

  1. Когда UIViewController вызывает setNeedsDisplay для CoreTextView, невозможно узнать, когда он завершил рисование. Я все еще не могу найти способ сделать обратный вызов, чтобы сказать ViewController, что можно приступить к следующей задаче.
  2. Добавляя UIViews к другому контейнеру UIView, drawRect технически рисует элементы вне своего прямоугольника, который, как я знаю, является нет-нет.
  3. Я уверен, что это не самый эффективный способ сделать это, хотя, похоже, он работает довольно хорошо.

1 Ответ

2 голосов
/ 25 июля 2011

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

Вместо того, чтобы создавать множество представлений, вместо этого поместите основной текст в CALayer. Затем вы можете создать дополнительные слои подсветки, чтобы поместить поверх текста. Это держит все внутри одного представления. Слои намного дешевле, чем просмотры. Если вы просто пытаетесь выделить стиль «подсветкой», то вы можете просто установить backgroundColor и frame для слоев, и все готово.

...