如何截断 UITextView 内容以适应缩小的尺寸?

发布于 2024-11-29 06:47:46 字数 754 浏览 1 评论 0原文

我真的很难理解这个问题。

正如标题所示,我在 iPhone 应用程序的视图上有多个 UITextView。我以编程方式创建它们并成功地用文本填充该文本视图,但在某些情况下,我放入视图中的文本占用的空间比我为其分配的框架更多。在这种情况下,我希望截断文本,但我不知道该怎么做。

我已经预定义了以下常量;

#define viewOriginX  20
#define viewOriginY 180

这是我的 UITextView 创建代码;

textViewOne = [[UITextView alloc] initWithFrame:CGRectMake(viewOriginX, viewOriginY + 65, 280, 45];
textViewOne.delegate = self;
textViewOne.scrollEnabled = NO;
textViewOne.contentInset = UIEdgeInsetsZero;
textViewOne.font = viewFont;
textViewOne.textColor = [UIColor blackColor];
textViewOne.textAlignment = UITextAlignmentLeft;
[self.view addSubview:textViewOne];

在某些情况下,我这里有 15 到 20 行文本,我想将其截断为 2 行。

谁能帮助我朝正确的方向前进?

提前致谢! :D

I'm having real trouble getting my head around this issue.

As the title suggests, I have several UITextViews on a view in an iPhone application. I am programmatically creating them and successfully filling that textview with text, but in some cases the text I put in the view takes up more space than the frame I allocate for it. In this case I would like the text to be truncated, but I can't figure out how to do it.

I have predefined the following constants;

#define viewOriginX  20
#define viewOriginY 180

Here is my UITextView creation code;

textViewOne = [[UITextView alloc] initWithFrame:CGRectMake(viewOriginX, viewOriginY + 65, 280, 45];
textViewOne.delegate = self;
textViewOne.scrollEnabled = NO;
textViewOne.contentInset = UIEdgeInsetsZero;
textViewOne.font = viewFont;
textViewOne.textColor = [UIColor blackColor];
textViewOne.textAlignment = UITextAlignmentLeft;
[self.view addSubview:textViewOne];

In some cases I have 15 to 20 lines of text in here and I would like to truncate it to 2 lines.

Can anyone help me in the right direction?

Thanks in advance! :D

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

难得心□动 2024-12-06 06:47:46

原始答案(iOS 6及更低版本)

遗憾的是,如果您需要可编辑视图,则带有numberOfLinesUILabel不会这样做。或者您想要 UITextView 的(原生)垂直对齐方式。

下面是一个 NSString 类别,它根据矩形中的大小从字符串中删除单词:

@interface NSString (StringThatFits)
- (NSString *)stringByDeletingWordsFromStringToFit:(CGRect)rect
                                         withInset:(CGFloat)inset
                                         usingFont:(UIFont *)font
@end

@implementation NSString (StringThatFits)
- (NSString *)stringByDeletingWordsFromStringToFit:(CGRect)rect
                                         withInset:(CGFloat)inset
                                         usingFont:(UIFont *)font
{
    NSString *result = [self copy];
    CGSize maxSize = CGSizeMake(rect.size.width  - (inset * 2), FLT_MAX);
    CGSize size = [result sizeWithFont:font
                           constrainedToSize:maxSize
                               lineBreakMode:UILineBreakModeWordWrap];
    NSRange range;

    if (rect.size.height < size.height)
        while (rect.size.height < size.height) {

            range = [result rangeOfString:@" "
                                        options:NSBackwardsSearch];

            if (range.location != NSNotFound && range.location > 0 ) {
                result = [result substringToIndex:range.location];
            } else {
                result = [result substringToIndex:result.length - 1];
            }

            size = [result sizeWithFont:font
                            constrainedToSize:maxSize
                                lineBreakMode:UILineBreakModeWordWrap];
        }

    return result;
}
@end

对于 UITextView,使用 8 的插入来说明 UIKit 绘制它们的方式:

CGRect rect = aTextView.frame;
NSString *truncatedString = [theString stringByDeletingWordsFromStringToFit:rect
                                     withInset:8.f
                                     usingFont:theTextView.font];

更新的答案(iOS 7)

现在UITextView内部使用TextKit,它更容易。

不要截断实际字符串,而是将 text(或 attributedText)属性设置为整个字符串并截断容器中显示的文本量(就像我们对 UILabel 所做的那样):

self.textView.scrollEnabled = NO;
self.textView.textContainer.maximumNumberOfLines = 0;
self.textView.textContainer.lineBreakMode = NSLineBreakByTruncatingTail;

Original Answer (iOS 6 and below)

Sadly, UILabel with numberOfLines wont do it if you need the view to be editable. Or you want UITextView's (native) vertical alignment.

Here's an NSString category that deletes words from a string, according to it's size in a rect:

@interface NSString (StringThatFits)
- (NSString *)stringByDeletingWordsFromStringToFit:(CGRect)rect
                                         withInset:(CGFloat)inset
                                         usingFont:(UIFont *)font
@end

@implementation NSString (StringThatFits)
- (NSString *)stringByDeletingWordsFromStringToFit:(CGRect)rect
                                         withInset:(CGFloat)inset
                                         usingFont:(UIFont *)font
{
    NSString *result = [self copy];
    CGSize maxSize = CGSizeMake(rect.size.width  - (inset * 2), FLT_MAX);
    CGSize size = [result sizeWithFont:font
                           constrainedToSize:maxSize
                               lineBreakMode:UILineBreakModeWordWrap];
    NSRange range;

    if (rect.size.height < size.height)
        while (rect.size.height < size.height) {

            range = [result rangeOfString:@" "
                                        options:NSBackwardsSearch];

            if (range.location != NSNotFound && range.location > 0 ) {
                result = [result substringToIndex:range.location];
            } else {
                result = [result substringToIndex:result.length - 1];
            }

            size = [result sizeWithFont:font
                            constrainedToSize:maxSize
                                lineBreakMode:UILineBreakModeWordWrap];
        }

    return result;
}
@end

For a UITextView, use an inset of 8 to account for the way UIKit draws them:

CGRect rect = aTextView.frame;
NSString *truncatedString = [theString stringByDeletingWordsFromStringToFit:rect
                                     withInset:8.f
                                     usingFont:theTextView.font];

Updated Answer (iOS 7)

Now UITextView uses TextKit internally, it's much easier.

Rather than truncating the actual string, set the text (or attributedText) property to the whole string and truncate the amount of text displayed in the container (just like we do with UILabel):

self.textView.scrollEnabled = NO;
self.textView.textContainer.maximumNumberOfLines = 0;
self.textView.textContainer.lineBreakMode = NSLineBreakByTruncatingTail;
迟到的我 2024-12-06 06:47:46

您可以进行字符计数。例如,如果您有这样的 UITextField:

+--------------------+
|This is a string in |
|a text view.        |
+--------------------+

每行有 20 个字符。如果您知道该数字,则可以通过 -substringToIndex: 方法简单地截断字符串。

int maxCharacters = 40; // change it to your max
if([myString length] > maxCharacters) {
    myString = [myString substringToIndex:maxCharacters];
}

您还可以考虑UILabel。由于您只需要 2 行文本,UILabel 的 numberOfLines 属性可以解决您的问题。

You can do a character count. For example, if you have UITextField like this:

+--------------------+
|This is a string in |
|a text view.        |
+--------------------+

you have something like 20 characters per line. If you know that number you can simply truncate your string by -substringToIndex: method.

int maxCharacters = 40; // change it to your max
if([myString length] > maxCharacters) {
    myString = [myString substringToIndex:maxCharacters];
}

You can also think about UILabel. Since you need only 2 lines of text, UILabel's numberOfLines property can solve your problem.

治碍 2024-12-06 06:47:46

由于 sizeWithFont:constrainedToSize:lineBreakMode: 在 iOS 7 中已弃用,因此我做了一些更改:

- (NSString *)stringByDeletingWordsFromStringToFit:(CGRect)rect
                                     withInset:(CGFloat)inset
                                     usingFont:(UIFont *)font
{
    NSString *result = [self copy];
    CGSize maxSize = CGSizeMake(rect.size.width  - (inset * 2), FLT_MAX);
    if (!font) font = [UIFont systemFontOfSize:[UIFont systemFontSize]];
    CGRect boundingRect = [result boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: font, } context:nil];
    CGSize size = boundingRect.size;
    NSRange range;

    if (rect.size.height < size.height)
        while (rect.size.height < size.height) {

            range = [result rangeOfString:@" "
                                    options:NSBackwardsSearch];

            if (range.location != NSNotFound && range.location > 0 ) {
                result = [result substringToIndex:range.location];
            } else {
                result = [result substringToIndex:result.length - 1];
            }

            if (!font) font = [UIFont systemFontOfSize:[UIFont systemFontSize]];
            CGRect boundingRect = [result boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: font, } context:nil];
            size = boundingRect.size;
        }

    return result;

}

Because sizeWithFont:constrainedToSize:lineBreakMode: is deprecated in iOS 7, I made a few changes:

- (NSString *)stringByDeletingWordsFromStringToFit:(CGRect)rect
                                     withInset:(CGFloat)inset
                                     usingFont:(UIFont *)font
{
    NSString *result = [self copy];
    CGSize maxSize = CGSizeMake(rect.size.width  - (inset * 2), FLT_MAX);
    if (!font) font = [UIFont systemFontOfSize:[UIFont systemFontSize]];
    CGRect boundingRect = [result boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: font, } context:nil];
    CGSize size = boundingRect.size;
    NSRange range;

    if (rect.size.height < size.height)
        while (rect.size.height < size.height) {

            range = [result rangeOfString:@" "
                                    options:NSBackwardsSearch];

            if (range.location != NSNotFound && range.location > 0 ) {
                result = [result substringToIndex:range.location];
            } else {
                result = [result substringToIndex:result.length - 1];
            }

            if (!font) font = [UIFont systemFontOfSize:[UIFont systemFontSize]];
            CGRect boundingRect = [result boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: font, } context:nil];
            size = boundingRect.size;
        }

    return result;

}

信仰 2024-12-06 06:47:46

这是我编写的一段代码,用于截断字符串(按单词)以适应特定的宽度和高度:

- (NSString *)stringByTruncatingString:(NSString *)string toHeight:(CGFloat)height maxWidth:(CGFloat)width withFont: (UIFont *)font {

    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
    paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
    NSDictionary *attrDict = [NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName, paragraphStyle, NSParagraphStyleAttributeName, nil];
    NSMutableString *truncatedString = [string mutableCopy];

    if ([string sizeWithAttributes: @{NSFontAttributeName: font}].height > height) {
        // this line is optional, i wrote for better performance in case the string is too big
        if([truncatedString length] > 150) truncatedString = [[truncatedString substringToIndex:150] mutableCopy];
        // keep removing the last word until string is short enough
        while ([truncatedString boundingRectWithSize:CGSizeMake(width, CGFLOAT_MAX) options:NSStringDrawingTruncatesLastVisibleLine|NSStringDrawingUsesLineFragmentOrigin attributes:attrDict context:nil].size.height > height) {
            NSRange wordrange= [truncatedString rangeOfString: @" " options: NSBackwardsSearch];
            truncatedString = [[truncatedString substringToIndex: wordrange.location] mutableCopy];
        }
        // add elipsis to the end
        truncatedString = [NSMutableString stringWithFormat:@"%@...",truncatedString];
    }
    return truncatedString;
}

用法:

NSString *smallString = [self stringByTruncatingString:veryBigString toHeight:65 maxWidth:200 withFont:[UIFont systemFontSize:14.0f]];

Here's a peace of code i wrote to truncate a string (by words) to fit a certain width and height:

- (NSString *)stringByTruncatingString:(NSString *)string toHeight:(CGFloat)height maxWidth:(CGFloat)width withFont: (UIFont *)font {

    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
    paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
    NSDictionary *attrDict = [NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName, paragraphStyle, NSParagraphStyleAttributeName, nil];
    NSMutableString *truncatedString = [string mutableCopy];

    if ([string sizeWithAttributes: @{NSFontAttributeName: font}].height > height) {
        // this line is optional, i wrote for better performance in case the string is too big
        if([truncatedString length] > 150) truncatedString = [[truncatedString substringToIndex:150] mutableCopy];
        // keep removing the last word until string is short enough
        while ([truncatedString boundingRectWithSize:CGSizeMake(width, CGFLOAT_MAX) options:NSStringDrawingTruncatesLastVisibleLine|NSStringDrawingUsesLineFragmentOrigin attributes:attrDict context:nil].size.height > height) {
            NSRange wordrange= [truncatedString rangeOfString: @" " options: NSBackwardsSearch];
            truncatedString = [[truncatedString substringToIndex: wordrange.location] mutableCopy];
        }
        // add elipsis to the end
        truncatedString = [NSMutableString stringWithFormat:@"%@...",truncatedString];
    }
    return truncatedString;
}

Usage:

NSString *smallString = [self stringByTruncatingString:veryBigString toHeight:65 maxWidth:200 withFont:[UIFont systemFontSize:14.0f]];
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文