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

查看:26
本文介绍了在 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() - 分别获取排版线对应的CTLineRefs,线原点坐标,然后使用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.

Core Text 使用相对于普通 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天全站免登陆