在UILabel / UITextView中触及单词 [英] Getting the word touched in a UILabel/UITextView

查看:134
本文介绍了在UILabel / UITextView中触及单词的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要做的是创建一个文本容器组件,该组件能够指示当触摸它时最接近的单词(即触摸点后面一词)。

What I'd like to do is to create a text-container component that is able to indicate what is the nearest word when there's is a touch on it (i.e. the word "behind" the touched point).

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

First, I created a UILabel subclass and overrode the touchesEnded:withEvent: method to determine the touched CGPoint. I also wrote a method that compute the corresponding "frame" (CGRect) of each word of the text using sizeWithFont:forWidth:lineBreakMode:. With the touched CGPoint and this frame, I can determine which word is actually being touched. But the method that compute the frame only works with mono-line text.

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

So now I need to know which part of the text is on a given line (i.e. how the text has been splited), so that I can figure the correct left-margin and top-margin of each word.

我知道如何获得这个吗?
或者你可能有一个更简单的解决方案来实现这个目标吗? 遗憾的是,这篇文章不太有用......

Any idea how I can obtain this? Or maybe have you a more straightforward solution to achieve this? This post was unfortunately not very helpful......

推荐答案

(链接帖子中有一个示例代码项目的链接,其中包含一些有用的示例代码,但是我这里也将概述你的过程。)

(There is a link to a sample code project in your linked post that does contain some useful sample code, but I will outline the process for you here too.)

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

In short, you are going to need to use Core Text, which is Apple's advanced C-based text handling framework that backs all sophisticated text layout in iOS and OS X.

完整的代码将涉及到一些问题,但您想要了解的关键方法是:

The full code is going to be somewhat involved, but key methods you are going to want to look at are:

CTFramesetterCreateWithAttributedString() - 将此项与您从标签文本中获得的NSAttributedString结合使用,以创建框架集

CTFramesetterCreateWithAttributedString() - use this, in conjunction with an NSAttributedString that you will get from your label's text - to create the framesetter

CTFramesetterCreateFrame() - 使用此方法从上面的框架设置中获取文本的CTFrameRef。您需要使用标签边界创建一个CGPathRef来执行此操作。

CTFramesetterCreateFrame() - use this to get a CTFrameRef for your text from the above framesetter. You will need to create a CGPathRef using your label bounds to do this.

CTFrameGetLines(),CTFrameGetLineOrigins() - 使用这些来获取与排版行对应的CTLineRef,以及分别是行原点的坐标,然后使用CTLineGetStringIndexForPosition()在触摸位置找到字符索引。

CTFrameGetLines(), CTFrameGetLineOrigins() - use these to get CTLineRefs corresponding to the typeset lines, and the coordinates of the line origins, respectively, then use CTLineGetStringIndexForPosition() to find the character index at a touch location.

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

You can then use this character index (in the line's reference frame) to work backward and find the actual character/word/etc within your full string.

不要忘记问题因几个问题而变得复杂:

Don't forget that matters are complicated by a couple issues:


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

  1. If you use UILabel's native drawing you will have to take care to perfectly match your typesetting metrics, which can be cumbersome since most of the objects (e.g. CTFontRef) are not toll-free bridged with their UIKit counterparts. Implementing your own drawing may, sometimes, be easier, which will guarantee metric matching.

核心文本使用相对于普通iOS绘图系统的倒置坐标系。如果你得到了古怪的结果,特别是如果你自己绘图,这是值得一看的。

Core Text uses an inverted coordinate system with respect to the normal iOS drawing system. If you are getting wacky results, and especially if you do your own drawing, this is something to take a look at.

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

Not the easiest task in the world, but far from impossible. Good luck!

这篇关于在UILabel / UITextView中触及单词的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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