我有一个 UILabel
,它的长度可能会有所不同,具体取决于我的应用程序在 iPhone 或 iPad 上以纵向还是横向模式运行。当文本太长而无法在一行上显示并且它被截断时,我希望用户能够按下它并获得全文的弹出窗口。
如何检查 UILabel
是否截断文本?有可能吗?现在我只是根据我所处的模式检查不同的长度,但效果不是很好。
I have a UILabel
that can be varying lengths depending on whether or not my app is running in portrait or landscape mode on an iPhone or iPad. When the text is too long to show on one line and it truncates I want the user to be able to press it and get a popup of the full text.
How can I check to see if the UILabel
is truncating the text? Is it even possible? Right now I'm just checking for different lengths based on what mode I'm in but it does not work super well.
发布评论
评论(23)
您可以计算字符串的宽度并查看宽度是否为大于
label.bounds.size.width
NSString UIKit Additions 有几种方法来计算具有特定字体的字符串的大小。但是,如果您的标签有一个最小字体大小,允许系统将文本缩小到该大小。您可能需要使用 sizeWithFont:minFontSize:actualFontSize:forWidth:lineBreakMode: 在这种情况下。
You can calculate the width of the string and see if the width is greater than
label.bounds.size.width
NSString UIKit Additions has several methods for computing the size of the string with a specific font. However, if you have a minimumFontSize for your label that allows the system to shrink the text down to that size. You may want to use sizeWithFont:minFontSize:actualFontSize:forWidth:lineBreakMode: in that case.
Swift (作为扩展) - 适用于多行 uilabel:
swift4: (
boundingRect
的attributes
参数略有改变)swift3:
swift2:
Swift (as extension) - works for multi line uilabel:
swift4: (
attributes
param ofboundingRect
changed slightly)swift3:
swift2:
编辑:我刚刚看到我的答案被赞成,但我给出的代码片段已被弃用。
现在最好的方法是(ARC):
注意计算的大小不是整数值。因此,如果您执行诸如
int height = rect.size.height
之类的操作,您将丢失一些浮点精度,并且可能会得到错误的结果。旧答案(已弃用):
如果您的标签是多行的,您可以使用以下代码:
EDIT: I just saw my answer was upvoted, but the code snippet I gave is deprecated.
Now the best way to do this is (ARC) :
Note the calculated size is not integer value. So if you do things like
int height = rect.size.height
, you will lose some floating point precision and may have wrong results.Old answer (deprecated) :
If your label is multiline, you can use this code :
看起来
intrinsicContentSize
可以完成使用attributedText
和text
设置文本的标签的工作。考虑到这一点,我认为我们可以安全地放弃所有边界框簿记并简化如下:Swift 5.x
It seems
intrinsicContentSize
will get the job done for labels with text set withattributedText
andtext
. With that in mind, I think we can safely ditch all the bounding box bookkeeping and simplify as follows:Swift 5.x
Swift 3
您可以在分配字符串后计算行数,并与标签的最大行数进行比较。
Swift 3
You can count the number of lines after assigning the string and compare to the max number of lines of the label.
你可以用 UILabel 创建一个类别
you can make a category with UILabel
要添加到 iDev 的答案,您应该使用
intrinsicContentSize
而不是frame< /code>,使其适用于自动布局
To add to iDev 's answer, you should use
intrinsicContentSize
instead offrame
, to make it works for Autolayout使用此类别可查找标签在 iOS 7 及更高版本上是否被截断。
Use this category to find if a label is truncated on iOS 7 and above.
就是这样。这适用于
attributedText
,然后返回到纯text
,这对于我们处理多种字体系列、大小甚至 NSTextAttachments 的人来说非常有意义!与自动布局一起工作得很好,但显然在我们检查 isTruncated 之前必须定义和设置约束,否则标签本身甚至不知道如何布局自己,所以它甚至不知道它是否被截断。
仅使用简单的
NSString
和sizeThatFits
无法解决此问题。我不确定人们是如何获得这样的积极结果的。顺便说一句,正如多次提到的,使用sizeThatFits
根本不理想,因为它考虑了numberOfLines
来计算结果大小,这违背了我们想要的整个目的。这样做,因为无论是否被截断,isTruncated
总是返回false
。This is it. This works with
attributedText
, before falling back to plaintext
, which makes a lot of sense for us folks who deal with multiple font families, sizes, and even NSTextAttachments!Works fine with autolayout, but obviously the constraints must be defined and set before we check
isTruncated
, otherwise the label itself wont even know how to lay itself out, so no way it would even know if its truncated.It doesnt work to approach this problem with just a plain
NSString
andsizeThatFits
. Im not sure how people were getting positive results like that. BTW, as mentioned numerous times, usingsizeThatFits
is not ideal at all because it takes into accountnumberOfLines
for the resulting size, which defeats the whole purpose of what we are trying to do, becauseisTruncated
would always returnfalse
regardless if its truncated or not.这是 Swift 3 中选定的答案(作为扩展)。 OP 正在询问 1 行标签。我在这里尝试的许多快速答案都是特定于多行标签的,并且在单行标签上没有正确标记。
Here's the selected answer in Swift 3 (as an extension). The OP was asking about 1 line labels. Many of the swift answers I tried here are specific to multi-line labels and aren't flagging correctly on single line labels.
这适用于 iOS 8:
This works for iOS 8:
我编写了一个用于处理 UILabel 截断的类别。适用于 iOS 7 及更高版本。希望有帮助!
uilabel 尾部截断
I have written a category for working with UILabel's truncation. Works on iOS 7 and later. Hope it helps !
uilabel tail truncation
您可以计算字符串的宽度,看看宽度是否大于标签宽度。
You can calculate the width of the string and see if the width is greater than label width.
为了添加 @iDev 所做的,我将
self.frame.size.height
修改为使用label.frame.size.height
并且也没有使用NSStringDrawingUsesLineFontLeading
。经过这些修改后,我完美地计算了截断何时发生(至少对于我的情况)。To add to what @iDev did, I modified the
self.frame.size.height
to uselabel.frame.size.height
and also did not useNSStringDrawingUsesLineFontLeading
. After those modifications, I achieved perfect calculation of when the truncation would happen (at least for my case).我遇到了
boundingRect(with:options:attributes:context:) 问题
当使用自动布局(设置最大高度)和带有NSParagraph.lineSpacing
行之间的间距被忽略(即使将
attributes
传递给boundingRect
方法)因此标签在被截断时可能被认为没有被截断。我找到的解决方案是使用
UIView.sizeThatFits
< /a>:I had issues with
boundingRect(with:options:attributes:context:)
when using autolayout (to set a max height) and an attributed text withNSParagraph.lineSpacing
The spacing between lines was ignored (even when passed in
attributes
to theboundingRect
method) so the label might be considered as not truncated when it was.The solution I found is to use
UIView.sizeThatFits
:确保在 viewDidLayoutSubviews 中调用其中一个。
Make sure to call either of these in viewDidLayoutSubviews.
SWIFT 5
设置为仅显示 3 行的多行 UILabel 示例。
尽管用户可以选择返回键添加额外的行而不添加“文本宽度”,但在这种情况下类似的东西也可能有用。
SWIFT 5
Example for a multiple lined UILabel that is set to display only 3 lines.
Though the user may select the return key adding an extra line without adding to the "text width" in that case something like this may also be useful.
在 Swift 5.x 中
In Swift 5.x
因为上面的所有答案都使用折旧方法,所以我认为这可能有用:
Because all the answers above use depreciated methods, i thought this could be useful:
使用 numberOfLines 并不总是有用,因为它可能为零,并且标签可能由于高度限制而被截断。另外,在我的情况下,
intrinsicContentSize
没有返回正确的大小。您可以使用此扩展:Using
numberOfLines
is not always useful because it may be zero and label can be truncated because of height constraints. Also,intrinsicContentSize
didn't return the correct size in my case. You can use this extension:为了处理 iOS 6(是的,我们中的一些人仍然必须这样做),这是对 @iDev 答案的另一个扩展。关键要点是,对于 iOS 6,在调用 sizeThatFits 之前确保 UILabel 的 numberOfLines 设置为 0;如果没有,它会给你一个结果,显示“绘制标签文本需要绘制 numberOfLines 高度的点”。
To handle iOS 6 (yes, some of us still have to), here's yet another expansion to @iDev's answer. The key takeaway is that, for iOS 6, to make sure your UILabel's numberOfLines is set to 0 before calling sizeThatFits; if not, it'll give you a result that says "the points to draw numberOfLines worth of height" is needed to draw the label text.
Swift 3 解决方案
我认为最好的解决方案是(1)创建一个与您要检查是否有截断的标签,(2)调用
.sizeToFit()
,(3)将虚拟标签的属性与您的标签进行比较实际标签。例如,如果您想检查具有不同宽度的单行标签是否被截断,那么您可以使用此扩展:
...但同样,您可以轻松修改上述代码以满足您的需求。假设您的标签是多行的并且具有不同的高度。然后扩展看起来像这样:
Swift 3 solution
I think the best solution is to (1) create a
UILabel
with the same properties as the label you're checking for truncation, (2) call.sizeToFit()
, (3) compare the attributes of the dummy label with your actual label.For example, if you want to check whether a one lined label that has varying width truncates or not, then you can use this extension:
...but again, you can easily modify the above code to fit your needs. So let's say your label is multilined and has varying height. Then the extension would look something like this:
设置标签的标题属性是不是很容易,设置此属性将在悬停时显示完整的标签。
您可以计算标签的长度和div宽度(转换为长度 - jQuery / Javascript - 如何将像素值 (20px) 转换为数字值 (20))。
如果长度大于 div 宽度,则设置 jquery 设置标题。
Wouldnt it be easy to set the title attribute for the label , setting this will display full label when hovered.
you can calculate the length of the label and div width (convert to length - jQuery / Javascript - How do I convert a pixel value (20px) to a number value (20)).
set jquery to set title if length is greater than the div width.