使用CoreText和触摸创建可单击的操作 [英] Using CoreText and touches to create a clickable action

查看:208
本文介绍了使用CoreText和触摸创建可单击的操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在视图中有一些代码,它使用CoreText绘制一些属性文本。在这里,我正在搜索网址并将其设为蓝色。我们的想法是不要带来 UIWebView 的所有开销,只是为了获得可点击的链接。一旦用户点击该链接(而不是整个表视图单元格),我想触发一个委托方法,该方法将用于呈现一个模态视图,其中包含一个到该URL的Web视图。

I have some code in a view which draws some attributed text using CoreText. In this, I'm searching for urls and making them blue. The idea is to not bring in all the overhead of a UIWebView just to get clickable links. Once a user taps on that link (not the whole table view cell), I want to fire off a delegate method which will then be used to present a modal view which contains a web view going to that url.

我将路径和字符串本身保存为视图的实例变量,绘图代码发生在 -drawRect:(I为了简洁起见,我把它留了下来。

I'm saving the path and the string itself as instance variables of the view, and the drawing code happens in -drawRect: (I've left it out for brevity).

我的触摸处理程序然而,虽然不完整,却没有打印出我期望的内容。它位于:

My touch handler however, while incomplete, is not printing what I'd expect it to. It is below:

- (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
                }
            }
        }
    }
}

目前这不是最漂亮的代码,我仍然试图让它工作,所以请原谅代码质量。

It's not the prettiest code at the moment, I'm still trying to just make it work, so forgive the code quality.

问题我有的是当我点击链接之外时,我预期会发生什么,发生:什么都没有被解雇。

The problem I'm having is that when I tap outside the link, what I expect would happen, happens: Nothing gets fired.

但是,我希望点击线如果我点击链接所在的同一行就会打印出来,这不会发生,我希望Tapped line点击运行如果点击网址就会打印出来。

However, I would expect "Tapped line" to get printed if I tap the same line the link is on, which doesn't happen, and I would expect both "Tapped line" and "Tapped run" to get printed if I tap on the URL.

我是我不确定在哪里进一步采取这些措施,我为解决这个问题而寻找的资源是Cocoa特有的(几乎完全不适用),或者缺乏关于这个具体案例的信息。

I'm unsure as to where to take this further, the resources I've looked at for resolution to this issue are Cocoa specific (which is almost completely inapplicable), or lacking information on this specific case.

我很乐意接受指向文档的指示,详细说明如何正确检测是否触摸oc在核心文本绘制代码的范围内,但是在这一点上,我只是想解决这个问题,所以任何帮助都会非常感激。

I'll gladly take pointers to documentation which detail how to properly go about detecting if a touch occurred within the bounds of a core text drawing over code, but at this point, I just want to resolve this problem, so any help would be greatly appreciated.

更新:我已将问题缩小到坐标问题。我已经翻转了坐标(而不是如上所示),我得到的问题是按照我的预期触及寄存器,但坐标空间被翻转,我似乎无法将其翻转。

UPDATE: I have narrowed down my problem to a coordinate issue. I have flipped the coordinates (and not as shown above) and the problem I'm getting is that touches register as I'd expect, but the coordinate space is flipped, and I can't seem to flip it back.

推荐答案

我刚刚完成此操作以从触摸位置获取字符串字符索引。在这种情况下,行号是i:

I have just done this to get the string character index from the touch position. The line number would be i in this case:

- (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);
}

这篇关于使用CoreText和触摸创建可单击的操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆