我正在使用 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/