Как определить, какое слово коснулось CoreText - PullRequest
2 голосов
/ 11 марта 2012

Я использую CoreText для создания пользовательского представления.Следующим шагом для меня является определение того, какое слово вводится в событие касания / жеста.Я провел исследование по этому вопросу и нашел совет о том, как индивидуально пометить URL, чтобы получать прикосновения, но ничего общего.Кто-нибудь имеет какие-либо идеи о том, как это сделать?

ОБНОВЛЕНИЕ:

Вот код в моем drawRect: метод self.attribString = [копия aString];

CGContextRef context = UIGraphicsGetCurrentContext();

// Flip the coordinate system
CGContextSetTextMatrix(context, CGAffineTransformIdentity);
CGContextTranslateCTM(context, 0, self.bounds.size.height);
CGContextScaleCTM(context, 1.0, -1.0);

CGMutablePathRef path = CGPathCreateMutable(); //1
CGPathAddRect(path, NULL, self.bounds );

CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)aString); //3
CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, [aString length]), path, NULL);

CTFrameDraw(frame, context); //4
UIGraphicsPushContext(context);
frameRef = frame;

CFRelease(path);
CFRelease(framesetter);

Здесь я пытаюсь обработать событие касания.

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint point = [touch locationInView:self];
    CGContextRef context = UIGraphicsGetCurrentContext();

    CFArrayRef lines = CTFrameGetLines(frameRef);
    for(CFIndex i = 0; i < CFArrayGetCount(lines); i++)
    {
        CTLineRef line = CFArrayGetValueAtIndex(lines, i);
        CGRect lineBounds = CTLineGetImageBounds(line, context);
        NSLog(@"Line %ld (%f, %f, %f, %f)", i, lineBounds.origin.x, lineBounds.origin.y, lineBounds.size.width, lineBounds.size.height);
        NSLog(@"Point (%f, %f)", point.x, point.y);
        if(CGRectContainsPoint(lineBounds, point))
        {

Кажется, что CTLineGetImageBounds возвращает неправильное начало (размер кажется правильным), вот один пример строки 0 NSLog "(0.562500), -0,281250, 279,837891, 17,753906) ".

1 Ответ

2 голосов
/ 12 марта 2012

В touchesEnded:withEvent: нет «текущего контекста».Вы не рисуете в этой точке.Таким образом, вы не можете вызвать CTLineGetImageBounds() осмысленно.

Я считаю, что лучшее решение здесь - это использовать CTFrameGetLineOrigins(), чтобы найти правильную строку (проверяя происхождение Y), а затем использовать CTLineGetStringIndexForPosition(), чтобы найтиправильный символ в строке (после вычитания начала строки из point).Это лучше всего подходит для простых стековых линий, которые запускают весь вид (например, ваш).

Другие решения:

  • Рассчитать все прямоугольники линий во время drawRect: и кэшироватьих.Тогда вы можете просто выполнить проверку прямоугольника в touchesEnded:....Это очень хорошее решение, если рисование менее распространено, чем постукивание.Если рисование значительно чаще, чем постукивание, то это плохой подход.

  • Все ваши расчеты выполняются с использованием CTLineGetTypographicBounds().Это не требует графического контекста.Вы можете использовать это для обработки прямоугольников.

  • В drawRect: сгенерируйте CGLayer с текущим контекстом и сохраните его в ivar.Затем используйте контекст из CGLayer для вычисления CTLineGetImageBounds().Контекст из CGLayer будет «совместим» с графическим контекстом, который вы используете для рисования.

Примечание: почему вы звоните UIGraphicsPushContext(context); в drawRect:?Вы устанавливаете текущий контекст в текущий контекст.Это не имеет смысла.И я не вижу соответствующего UIGraphicsPopContext().

...