cocoa-touch - 如何检测哪个单词与 CoreText 接触

标签 cocoa-touch ios5 core-text

我正在使用 CoreText 来布局自定义 View 。我的下一步是检测在触摸事件/手势事件上点击了哪个单词。我对此进行了研究,并找到了有关如何自定义标签网址以接收触摸的建议 - 但没有通用的。有人知道如何做到这一点吗?

更新:

这是我的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 返回了错误的原点(大小似乎正确),这是 NSLog“第 0 行(0.562500,-0.281250,279.837891,17.753906)”的一个示例。

最佳答案

touchesEnded:withEvent: 中没有“当前上下文”。此时你还没有画画。因此,您无法有意义地调用 CTLineGetImageBounds()

我相信这里最好的解决方案是使用 CTFrameGetLineOrigins() 查找正确的行(通过检查 Y 原点),然后使用 CTLineGetStringIndexForPosition() 查找行内的正确字符(从减去行原点之后)。这最适合运行整个 View (例如您的 View )的简单堆叠线。

其他解决方案:

  • drawRect:期间计算所有线矩形并缓存它们。然后你可以在 touchesEnded:... 中进行矩形检查。如果绘图不像点击那么常见,那么这是一个非常好的解决方案。如果绘图比点击明显更常见,那么这是一个糟糕的方法。

  • 使用 CTLineGetTypgraphicBounds() 进行所有计算。这不需要图形上下文。您可以使用它来计算矩形。

  • drawRect:中使用当前上下文生成一个CGLayer并将其存储在ivar中。然后使用 CGLayer 中的上下文来计算 CTLineGetImageBounds()CGLayer 中的上下文将与您用于绘制的图形上下文“兼容”。

旁注:为什么要在 drawRect: 中调用 UIGraphicsPushContext(context);?您正在将当前上下文设置为当前上下文。这没有道理。我没有看到相应的 UIGraphicsPopContext()

关于cocoa-touch - 如何检测哪个单词与 CoreText 接触,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9657635/

相关文章:

ios - cocoa touch 中的简单富 TextView

iphone - NSFileManager 泄漏

iphone - 未找到 CATransform3DMakeRotation 符号

objective-c - 键盘出现时 View 可以向上推吗?

objective-c - CTFrameGetLineOrigin 令人难以置信的奇怪错误

ios - 在合并的 PDF 中添加页码

objective-c - 关闭键盘的简单方法?

objective-c - switch 中未处理枚举值 'UIGestureRecognizerStatePossible' 、 'UIGestureRecognizerStateCancelled' 和 'UIGestureRecognizerStateFailed'

iphone - 支持横向一圈UIVIEWS :

ios - 为什么不用指针变量