我具有其中绘制使用CoreText一些属性文本的图一些代码。在此,我在寻找的网址,使他们的蓝色。我们的想法是在UIWebView的所有开销不会带来只是为了获得可点击的链接。一旦链路(而不是整个表视图细胞)上的用户的水龙头,我想断火,这将随后被用于呈现包含要该URL的web视图模态的视图的委托方法。

我保存的路径和字符串本身作为视图的实例变量,以及绘图代码发生在-drawRect:(我已经离开它的简洁)。

我的触摸处理然而,虽然不完整,不打印什么,我想指望它。它是如下所示:

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

    NSLog(@"attribString = %@", self.attribString);
    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)self.attribString);
    CTFrameRef ctframe = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, self.attribString.length), attribPath, NULL);

    CFArrayRef lines = CTFrameGetLines(ctframe);
    for(CFIndex i = 0; i < CFArrayGetCount(lines); i++)
    {
        CTLineRef line = CFArrayGetValueAtIndex(lines, i);
        CGRect lineBounds = CTLineGetImageBounds(line, context);

        // Check if tap was on our line
        if(CGRectContainsPoint(lineBounds, point))
        {
            NSLog(@"Tapped line");
            CFArrayRef runs = CTLineGetGlyphRuns(line);
            for(CFIndex j = 0; j < CFArrayGetCount(runs); j++)
            {
                CTRunRef run = CFArrayGetValueAtIndex(runs, j);
                CFRange urlStringRange = CTRunGetStringRange(run); 
                CGRect runBounds = CTRunGetImageBounds(run, context, urlStringRange);

                if(CGRectContainsPoint(runBounds, point))
                {
                    NSLog(@"Tapped run");
                    CFIndex* buffer = malloc(sizeof(CFIndex) * urlStringRange.length);
                    CTRunGetStringIndices(run, urlStringRange, buffer);
                    // TODO: Map the glyph indices to indexes in the string & Fire the delegate
                }
            }
        }
    }
}

这不是目前最漂亮的代码,我还在努力,只是使它工作,所以请原谅的代码质量。

我遇到的问题是,当我点击的链接外,我的期望会发生,发生:没有被炒鱿鱼

不过,我希望如果我点击同一行链路上,这不会发生在得到印刷"Tapped line",并且我希望双方"Tapped line""Tapped run"得到印如果在URL我水龙头。

我不能确定在何处借此进一步,我看过了解决此问题的资源是可可特有的(这几乎是完全不适用),或缺乏相关信息,具体的情况。

我会很乐意采取指向文档里面详细如何正确去,如果触摸发生核心文本的范围内绘制了代码检测,但在这一点上,我只是想解决这个问题,所以任何帮助将不胜感激。

更新:我有我的问题缩小到一个协调的问题。我已经翻转坐标(而不是如上所示),我得到的问题是,触摸注册为我所期待的,但坐标空间被翻转,我似乎不能翻转回来。

有帮助吗?

解决方案

我刚刚做这个来从触摸位置的字符串的字符索引。行号将是我在这种情况下:

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@"touch ended");

    UITouch* touch = [touches anyObject];

    CGPoint pnt = [touch locationInView:self];

    CGPoint reversePoint = CGPointMake(pnt.x, self.frame.size.height-pnt.y);

    CFArrayRef lines = CTFrameGetLines(ctFrame);

    CGPoint* lineOrigins = malloc(sizeof(CGPoint)*CFArrayGetCount(lines));

    CTFrameGetLineOrigins(ctFrame, CFRangeMake(0,0), lineOrigins);

    for(CFIndex i = 0; i < CFArrayGetCount(lines); i++)
    {
        CTLineRef line = CFArrayGetValueAtIndex(lines, i);

        CGPoint origin = lineOrigins[i];
        if (reversePoint.y > origin.y) {
            NSInteger index = CTLineGetStringIndexForPosition(line, reversePoint);
            NSLog(@"index %d", index);
            break;
        }
    }
    free(lineOrigins);
}

其他提示

您可以尝试添加文本绘制到CALayer的,在你的touchesEnded添加这个新层的意见吧层的子层和则hitTest反对呢?如果你这样做,你应该能够通过使比绘制文本越大层来创建一个更大的触摸区域。

// hittesting 
UITouch *touch = [[event allTouches] anyObject];
touchedLayer = (CALayer *)[self.layer hitTest:[touch locationInView:self]];

夫特3版尼克H247的回答:

var ctFrame: CTFrame?

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let touch = touches.first, let ctFrame = self.ctFrame else { return }

    let pnt = touch.location(in: self.view)
    let reversePoint = CGPoint(x: pnt.x, y: self.frame.height - pnt.y)
    let lines = CTFrameGetLines(ctFrame) as [AnyObject] as! [CTLine]

    var lineOrigins = [CGPoint](repeating: .zero, count: lines.count)
    CTFrameGetLineOrigins(ctFrame, CFRange(location: 0, length: 0), &lineOrigins)

    for (i, line) in lines.enumerated() {
        let origin = lineOrigins[i]

        if reversePoint.y > origin.y {
            let index = CTLineGetStringIndexForPosition(line, reversePoint)
            print("index \(index)")
            break
        }
    }
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top