【问题标题】:Getting the word touched in a UILabel/UITextView在 UILabel/UITextView 中获取单词
【发布时间】:2012-02-07 08:59:04
【问题描述】:

我想做的是创建一个文本容器组件,该组件能够在触摸时指示最近的单词是什么(即触摸点“后面”的单词)。

首先,我创建了一个 UILabel 子类并覆盖了 touchesEnded:withEvent: 方法来确定被触摸的 CGPoint。我还编写了一个方法,使用 sizeWithFont:forWidth:lineBreakMode: 计算文本每个单词的相应“框架”(CGRect)。通过触摸的 CGPoint 和这一帧,我可以确定实际触摸的是哪个单词。但是计算框架的方法只适用于单行文本。

所以现在我需要知道文本的哪一部分在给定的行上(即文本是如何被分割的),这样我才能计算出每个单词的正确左边距和上边距。

知道如何获得这个吗? 或者,也许您有更直接的解决方案来实现这一目标? This post was unfortunately not very helpful......

【问题讨论】:

    标签: ios text word touch uilabel


    【解决方案1】:

    (在您的链接帖子中有一个示例代码项目的链接,其中确实包含一些有用的示例代码,但我也会在这里为您概述该过程。)

    简而言之,您将需要使用 Core Text,它是 Apple 基于 C 语言的高级文本处理框架,支持 iOS 和 OS X 中所有复杂的文本布局。

    完整的代码会有所涉及,但您要查看的关键方法是:

    CTFramesetterCreateWithAttributedString() - 将它与您将从标签文本中获得的 NSAttributedString 结合使用 - 来创建框架设置器

    CTFramesetterCreateFrame() - 使用它从上面的 framesetter 中为您的文本获取 CTFrameRef。您需要使用标签边界创建一个 CGPathRef 来执行此操作。

    CTFrameGetLines(), CTFrameGetLineOrigins() - 使用它们分别获取排版线对应的CTLineRefs,以及线原点的坐标,然后使用CTLineGetStringIndexForPosition() 找到触摸位置的字符索引。

    然后您可以使用此字符索引(在行的参考框架中)向后工作并在完整字符串中找到实际的字符/单词/等。

    不要忘记,有几个问题会使事情变得复杂:

    1. 如果您使用 UILabel 的原生绘图,则必须注意完美匹配您的排版指标,这可能很麻烦,因为大多数对象(例如 CTFontRef)不是免费桥接其 UIKit 对应对象。有时,实现自己的绘图可能更容易,这将保证度量匹配。

    2. Core Text 使用相对于普通 iOS 绘图系统的倒置坐标系统。如果你得到古怪的结果,特别是如果你自己画,这是值得一看的。

    这不是世界上最简单的任务,但远非不可能。祝你好运!

    【讨论】:

    • 实际上,我想避免自己绘制文本,因为考虑到最初的需要,这似乎有点开销。我会考虑您提供的 CoreText 键功能,谢谢!
    【解决方案2】:

    虽然这是一个老问题,但我认为这可能会有所帮助。

    由于学习核心文本量很大,我选择了GLTapDemo by German Laullon

    通过一些更改,这对于检测 UILabel 上的触摸词非常有用。

    【讨论】:

    • 我尝试了 VSWordDetector 解决方案和这个解决方案,发现这个解决方案更适合我的用例。
    【解决方案3】:

    经过一番搜索,我为此编写了一个代码。代码适用于 UITextViewUILabel
    只需下载VSWordDetector.zip 然后解压缩并将文件夹VSWordDetector 拖放到您的项目中。
    有两个文件VSWordDetector.hVSWordDetector.m
    #import VSWordDetector.h 在你的ViewController 类中。

    @property (strong, nonatomic) VSWordDetector *wordDetector;
    

    注意:使其属性不要作为本地。

    现在已经为您准备好了,只需将其添加到 textViewsLabels

    -(void)viewDidLoad
    {
       self.wordDetector = [[VSWordDetector alloc] initWithDelegate:self];
       [self.wordDetector addOnView:textView];
       [self.wordDetector addOnView:label];
    }
    
    -(void)wordDetector:(VSWordDetector *)wordDetector detectWord:(NSString *)word
    {
       NSLog(@"Detected Word: %@", word);
    }
    

    当您点击连接的标签或 textView 时,将调用此委托方法。

    编辑: Sample Code 用于 VSWordDetector

    建议编辑:如果您不想在此处下载示例代码,请参考这两个文件的代码。请参阅此要点文件VSWordDetector

    【讨论】:

    • @NijilNair 对不起,但我不能说你哪里做错了。所以我做了一个示例,请参阅我的答案的编辑部分。
    • @Sulthan - 压缩代码是单独的代码。我制作了对新生有帮助的样品。只有当我的代码不工作并且有问题时才投反对票。
    • @Sulthan - 正如我已经说过的,新生在某些情况下无法得到解释。我不喜欢制作样品并提供给他人,但为此我必须做到让人们理解。
    • @Sulthan - 我没有粘贴整个代码,因为它太长了。
    • @ChrisHarrison - 谢谢...实际上提供示例链接的原因是代码太长,无法粘贴到此处。如果我这样做,它将使它成为访客的长滚动条。而且有很多答案只是给出了其他代码的示例代码链接,即使我给出了我自己的示例代码的链接。无论如何,我已按照您的建议将 .h 和 .m 文件作为文本提供。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-17
    • 1970-01-01
    • 2014-03-12
    • 1970-01-01
    相关资源
    最近更新 更多