ios - 限制 UITextView 中的行数

标签 ios objective-c ios5 uitextview

问题

有什么方法可以“准确”限制目标 iOS 5.0 的 UITextView 中的行数?

我尝试过的

因为我在堆栈溢出中进行了搜索。我发现这些问题之前在下面的链接中被问过。
In UITextView, how to get the point that next input will begin another line
Limit the number of lines for UITextview
Limit number of lines in UITextView

但是当我试图决定在 textView:shouldChangeTextInRange:replacementText: 中返回 YES 或 NO 时,我仍然无法在 UITextView 中获得准确的行数。 我曾尝试使用作为 Limiting text in a UITextView 答案的代码修改后的代码(删除答案中的-15)如下所示。

- (BOOL)textView:(UITextView *)aTextView shouldChangeTextInRange:(NSRange)aRange replacementText:(NSString*)aText
{
        NSString* newText = [aTextView.text stringByReplacingCharactersInRange:aRange withString:aText];

        // TODO - find out why the size of the string is smaller than the actual width, so that you get extra, wrapped characters unless you take something off
        CGSize tallerSize = CGSizeMake(aTextView.frame.size.width,aTextView.frame.size.height*2); // pretend there's more vertical space to get that extra line to check on
        CGSize newSize = [newText sizeWithFont:aTextView.font constrainedToSize:tallerSize lineBreakMode:UILineBreakModeWordWrap];

        if (newSize.height > aTextView.frame.size.height)
            {
            [myAppDelegate beep];
            return NO;
            }
        else
            return YES;
}

我还找到了一种方法来获取 UITextView 中的行数。方法是通过contentSize属性来计算,比如textView.contenSize.height/font.lineHeight。该方法可以获取UITextView中准确的行数。但问题是 contentSize 进入 textView:shouldChangeTextInRange:replacementText:textViewDidChange: 是旧的 contentSize。所以我仍然无法限制 UITextView 中的行数。

我用过的解决方案

这是一种解决方法,但至少有效。

第一步

首先,您需要创建一个临时的新 UITextView,它与原始 UITextView 完全相同,但将临时 UITextView 设置为隐藏在 .xib 文件中。在此示例代码中,我将临时 UITextView 命名为 tempTextInputView

第二步

向 .h 文件添加新的引用 socket
@property (retain, nonatomic) IBOutlet UITextView *tempTextInputView;//用于计算新文本在 UITextView 中的行数

第三步

在下面添加代码。

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{
    NSString *newText = [textView.text stringByReplacingCharactersInRange:range withString:text];
    _tempTextInputView.text = newText;

    // Calcualte the number of lines with new text in temporary UITextView
    CGRect endRectWithNewText = [_tempTextInputView caretRectForPosition:_tempTextInputView.endOfDocument];
    CGRect beginRectWithNewText = [_tempTextInputView caretRectForPosition:_tempTextInputView.beginningOfDocument];
    float beginOriginY = beginRectWithNewText.origin.y;
    float endOriginY = endRectWithNewText.origin.y;
    int numberOfLines = (endOriginY - beginOriginY)/textView.font.lineHeight + 1;

    if (numberOfLines > maxLinesInTextView) {// Too many lines
        return NO;
    }else{// Number of lines  will not over the limit
        return YES;
    }
}  

讨论

  1. maxLinesInTextView 是一个 int 变量,表示您想要的最大行数。
  2. 我使用一个临时的 UITextView 来设置新文本是因为当我在原始 UITextView 中简单地设置新文本时,我在输入繁体中文输入法注音键盘时遇到了一些问题。
  3. 我仍在使用 textView:shouldChangeTextInRange:replacementText: 而不是 textViewDidChange: 是因为在使用全局 NSString 修改之前缓存文本并替换 UITextView 时我遇到了一些问题.text 与 textViewDidChange: 中的全局 NSString。

最佳答案

下面是如何使用 UITextViewDelegate shouldChangeTextInRange: 方法将文本输入限制为 TextView 的高度:

func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
    // Combine the new text with the old
    let combinedText = (textView.text as NSString).stringByReplacingCharactersInRange(range, withString: text)

    // Create attributed version of the text
    let attributedText = NSMutableAttributedString(string: combinedText)
    attributedText.addAttribute(NSFontAttributeName, value: textView.font, range: NSMakeRange(0, attributedText.length))

    // Get the padding of the text container
    let padding = textView.textContainer.lineFragmentPadding

    // Create a bounding rect size by subtracting the padding
    // from both sides and allowing for unlimited length 
    let boundingSize = CGSizeMake(textView.frame.size.width - padding * 2, CGFloat.max)

    // Get the bounding rect of the attributed text in the
    // given frame
    let boundingRect = attributedText.boundingRectWithSize(boundingSize, options: NSStringDrawingOptions.UsesLineFragmentOrigin, context: nil)

    // Compare the boundingRect plus the top and bottom padding
    // to the text view height; if the new bounding height would be
    // less than or equal to the text view height, append the text
    if (boundingRect.size.height + padding * 2 <= textView.frame.size.height){
        return true
    }
    else {
        return false
    }
}

关于ios - 限制 UITextView 中的行数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21352597/

相关文章:

ios - 有没有办法从 ios 项目自动创建 UML 图?

ios - 执行 setCollectionViewLayout 时,UICollectionViewCel 中的布局看起来很奇怪

iphone - MediaPlayer MPMoviePlayerController - 不在横向播放视频

ios - iOS 上发布版本和调试版本之间的物理差异

ios - 在 SwiftUI 扩展中动态数据传递和呈现网格图像的 View

ios - 在 UIButton 下添加 UIScrollView 后失去点击识别

ios - 仅编辑 UITableView 中的第一个单元格

objective-c - 将NSString对象从UITableViewController发送到UIViewController的问题(使用 Storyboard )

ios - 导航栏上方显示的黑色空间

ios - 选项卡式 iOS 应用程序中的单个选项卡不断崩溃