我想做的是创建一个文本容器组件,该组件能够在触摸时指示最近的单词是什么(即触摸点“后面”的单词)。
首先,我创建了一个 UILabel 子类并重写 TouchesEnded:withEvent: 方法来确定触摸的 CGPoint。我还编写了一个方法,使用 sizeWithFont:forWidth:lineBreakMode: 计算文本每个单词的相应“框架”(CGRect)。通过被触摸的 CGPoint 和这个框架,我可以确定哪个单词实际上被触摸了。但计算框架的方法仅适用于单行文本。
所以现在我需要知道文本的哪一部分位于给定行上(即文本如何分割),以便我可以计算出每个单词的正确左边距和上边距。
知道如何获得这个吗?
或者也许您有更直接的解决方案来实现这一目标? 不幸的是,这篇文章不是很有帮助........ 。
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).
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......
发布评论
评论(3)
(您的链接文章中有一个示例代码项目的链接,其中确实包含一些有用的示例代码,但我也会在这里为您概述该过程。)
简而言之,您将需要使用 Core Text,这是 Apple 的基于 C 的高级文本处理框架,支持 iOS 和 OS X 中的所有复杂文本布局。
完整的代码将有所涉及,但您需要查看的关键方法是:
CTFramesetterCreateWithAttributedString() - 在与一个结合您将从标签文本中获取的 NSAttributedString - 创建框架设置器
CTFramesetterCreateFrame() - 使用它从上面的框架设置器获取文本的 CTFrameRef。您需要使用标签边界创建 CGPathRef 来执行此操作。
CTFrameGetLines()、CTFrameGetLineOrigins() - 使用它们分别获取与排版行相对应的 CTLineRef 以及行原点的坐标,然后使用 CTLineGetStringIndexForPosition() 查找触摸位置处的字符索引。
然后,您可以使用此字符索引(在行的参考框架中)向后工作并在完整字符串中找到实际的字符/单词/等。
不要忘记,有几个问题会让事情变得复杂:
如果您使用 UILabel 的本机绘图,您将必须小心地完美匹配您的排版指标,这可能很麻烦,因为大多数对象(例如 CTFontRef)都不是免费电话与 UIKit 同行桥接。有时,实现您自己的绘图可能会更容易,这将保证指标匹配。
Core Text 使用与普通 iOS 绘图系统相反的坐标系。如果您得到奇怪的结果,特别是如果您自己绘图,那么值得一看。
这不是世界上最简单的任务,但也绝非不可能。祝你好运!
(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.)
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() - use this, in conjunction with an NSAttributedString that you will get from your label's text - to create the framesetter
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() - 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:
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.
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!
经过一番搜索后,我为此编写了一段代码。代码适用于
UITextView
和UILabel
。只需下载VSWordDetector.zip,然后解压缩并拖动到将文件夹
VSWordDetector
放入您的项目中。有两个文件
VSWordDetector.h
和VSWordDetector.m
#import VSWordDetector.h
在您的ViewController
类中。注意:让它的属性不要当作本地的。
现在已经准备好了,只需将其添加到
textViews
或Labels
This当您点击连接的标签或textView时,将调用委托方法。
编辑: VSWordDetector 的示例代码。
建议编辑:如果您不想下载示例代码,这里是这两个文件的代码。请参阅此要点文件 VSWordDetector。
After searching a bit I have written a code for this. Code will work for
UITextView
andUILabel
.Just download VSWordDetector.zip then unzip it and drag & drop the folder
VSWordDetector
into your project.There are two files
VSWordDetector.h
andVSWordDetector.m
#import VSWordDetector.h
in yourViewController
class.Note: Make its property don't take as locally.
Now its ready for you, Just add it on
textViews
orLabels
This delegate method will be call when you will tap on connected label or textView.
EDIT: Sample Code for VSWordDetector.
SUGGESTED EDIT: If you don't want to download the sample code here is the code for both file. Please see this gist file VSWordDetector.
虽然这是一个老问题,但我认为这可能会有所帮助。
由于学习核心文本很大,我选择了 German Laullon 的 GLTapDemo
经过一些更改,这非常适合检测 UILabel 上触摸的单词。
Though this is an old question, but i thought this might be of some help.
Since learning core text was huge, i opted for GLTapDemo by German Laullon
With a few changes , this works great for detecting touched word on UILabel.