限制UITextView中的行数

4

我知道这个问题被问过,但我找不到一个有效的答案。结合之前的解决方案,我想出了这段代码:

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)string
{
    int numLines = notesTextView.contentSize.height / notesTextView.font.lineHeight;
        if (numLines <= 8)
        {
            return true;
        }
        return false;
}

这种方法不起作用,因为在添加文本之前已经计算了行数,所以我们仍然会超出我们想要的一行,并且被困在那里,无法进行进一步编辑。

我还尝试过检测"\n"输入的解决方案,但这也不起作用,因为我们可以通过自然换行而达到新的行。


我不明白你的评论,我的回答有帮助还是没有解决你的问题? - Adrian P
对我来说没有起作用。当我按下返回键时,它要么会关闭文本视图,要么当我删除了代码中的一部分后,将光标移到第10行的开头,然后不允许任何进一步的输入(我希望这在第8行的结尾发生)。 - Declan McKenna
刚刚编辑了我的答案。检查一下新的方法,看看是否适用于你。 - Adrian P
@CodeMonkey 我尝试过使用“\n”的解决方案。它们在你没有按回车键换行时有效。 - Declan McKenna
3个回答

6

我也遇到了这个问题。之前的解决方案都不太适用于我。这是我的解决方案,希望能帮到你:(仅适用于iOS 7+!)

- (void)textViewDidChange:(UITextView *)textView
{
    NSLayoutManager *layoutManager = [textView layoutManager];
    NSUInteger numberOfLines, index, numberOfGlyphs = [layoutManager numberOfGlyphs];
    NSRange lineRange;
    for (numberOfLines = 0, index = 0; index < numberOfGlyphs; numberOfLines++)
    {
            (void) [layoutManager lineFragmentRectForGlyphAtIndex:index
                                               effectiveRange:&lineRange];
        index = NSMaxRange(lineRange);
    }

    if (numberOfLines > 3)
    {
        // roll back
        _labelField.text = _text;
    }
    else
    {
        // change accepted
        _text = _labelField.text;
    }
}

它使用一个NSString实例变量_text,以便在文本被更改后能够回滚。这不会导致任何闪烁。
numberOfLines参考:https://developer.apple.com/library/mac/documentation/cocoa/conceptual/TextLayout/Tasks/CountLines.html#//apple_ref/doc/uid/20001810-CJBGBIBB

5
这个怎么样:
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)string
{
    NSString *temp = [textView.text stringByReplacingCharactersInRange:range withString:string]
    CGSize size = [temp sizeWithFont:textView.font constrainedToSize:CGSizeMake(textView.frame.size.width,999) lineBreakMode:UILineBreakModeWordWrap];
    int numLines = size.height / textView.font.lineHeight;
    if (numLines <= 8)
    {
        return true;
    }
    return false;
}

解析新文本,然后使用textView的信息检查新文本的大小。


这似乎不起作用。单独的“\n”字符似乎无法改变“size”的高度,因此我们面临着与我的解决方案相同的问题。 - Declan McKenna
有趣。我以为它会默认换行模式,但显然不是这样。请查看编辑,将 lineBreakMode 选项添加到 size 方法中。 - Putz1103
与换行模式有相同的问题。无论我尝试什么,我们都会被带到第9行,然后被困在那里。 - Declan McKenna
在这些情况下,numLines的值是多少?它是正确的吗?如果不正确,可能是因为font.lineHeight不正确吗?创建另一个尺寸结构并获取单个字符的size.height(类似于 [@"a" sizeWithFont...)。 - Putz1103
临时字符串应该是正确的,我认为/n字符不被视为新行,而是被视为前一行的结尾。 - Declan McKenna
显示剩余3条评论

0

这是我过去的做法,希望能为您提供一些帮助。

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text 
{

// limit the number of lines in textview
NSString* newText = [mytextView.text stringByReplacingCharactersInRange:range withString:text];

// pretend there's more vertical space to get that extra line to check on
CGSize tallerSize = CGSizeMake(mytextView.frame.size.width-15, mytextView.frame.size.height*2); 

CGSize newSize = [newText sizeWithFont:mytextView.font constrainedToSize:tallerSize lineBreakMode:UILineBreakModeWordWrap];

if (newSize.height > mytextView.frame.size.height)
{
    NSLog(@"two lines are full");
    return NO;
}


// dismiss keyboard and send comment
if([text isEqualToString:@"\n"]) {
    [mytextView resignFirstResponder];

    return NO;
}

return YES;
}

祝你好运。

编辑:

好的,尝试以下方法,看看是否适用于您。只需将行数更改为您想要的任何数字即可。

 (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
    if([text isEqualToString:@"n"]) {
        rows++;
    if(rows >= maxNumberOfLines){
        //Exit textview
         return NO;
        }
   }
  return YES;

请告诉我这是否可行。


除去键盘消失功能,这使我无法按回车键来开始新的一行,这让我到了第10行后就无法再输入任何内容。还是谢谢大家。 - Declan McKenna

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接