限制UITextview的行数


76

我想知道如何限制用户在编辑UITextField时可以输入的LINES数量(不是其他问题中询问的字符)。

理想情况下,我想将输入限制为最大。10行。

我需要从哪里开始?我可以用一种方法吗?在

 - (BOOL)textViewShouldBeginEditing:(UITextView *)aTextView

您可以在这篇文章中找到答案。
Zakaria

Answers:


15

您有正确的想法,但有错误的方法。textView:shouldChangeTextInRange:replacementText:每当文本更改时都会被调用;您可以使用其text属性访问文本视图的当前内容,还可以根据传递的范围和替换文本来构造新内容[textView.text stringByReplacingCharactersInRange:range withString:replacementText]。然后,您可以计算行数并返回YES允许更改,或者返回NO拒绝更改。


还是您说的是屏幕上的行,而不是文本的逻辑行?
失范

其实,是的,我想知道屏幕上的线条。我想将一个txt文件加载到UITextView中,并将屏幕上显示的行数限制为10或15,然后将其余的内容保留在下一个屏幕上。确实就像一个带有单个页面的小文字处理器。这就是为什么我要限制UITextView中显示的行(在屏幕上)。但是也许有更简单的方法可以做到这一点?也许使用UIWebView?
n.evermind 2011年

1
如果您只需要分页行为,请注意,它UITextView是的子类,UIScrollView并且具有pagingEnabled属性。
Anomie

我不认为这可以工作,因为ChangeChangeInInRange只能计算新输入之前的行数。每次新文本为“ \ n”时都添加一行也不起作用,因为用户自然可以到达该行的末尾。
Declan McKenna 2013年

236

Maciek Czarnik的答案对我不起作用,但是它使我了解到该怎么做。

iOS 7以上

迅速

textView.textContainer.maximumNumberOfLines = 10
textView.textContainer.lineBreakMode = .byTruncatingTail

对象

textView.textContainer.maximumNumberOfLines = 10;
textView.textContainer.lineBreakMode = NSLineBreakByTruncatingTail;

3
这应该是现在公认的答案,即使迟到了几年也可以!
齐格福特2015年

34
这是越野车。它允许您在文本视图的结尾处按回车键,然后光标消失,必须按Delete键才能再次找到它。
埃里克·康纳

雨燕2:textView.textContainer.lineBreakMode = .ByTruncatingTail
应用开发人员2016年

55

也许可以帮上忙(iOS 7+):

textView.textContainer.maximumNumberOfLines = 10;
[textView.layoutManager textContainerChangedGeometry:textView.textContainer];

我猜连第一行都可以解决,但不行。。。也许这是SDK中的错误


12

Maciek Czarnik的答案似乎对我不起作用,即使在iOS7中也是如此。它给了我奇怪的行为,我不知道为什么。

我要限制UITextView中的行数的方法很简单:

(仅在iOS7中经过测试)在以下UITextViewDelegate方法中:

- (void)textViewDidChange:(UITextView *)textView
{
    NSUInteger maxNumberOfLines = 5;
    NSUInteger numLines = textView.contentSize.height/textView.font.lineHeight;
    if (numLines > maxNumberOfLines)
    {
        textView.text = [textView.text substringToIndex:textView.text.length - 1];
    }
}

CGSize size = [textView sizeThatFits:CGSizeMake(textView.width,MAXFLOAT)]; 对我来说,我必须计算新的高度才能使它工作
tettoffensive 16-4-8

简单而完美的解决方案
阿法塔·穆罕默德·汗

11

Swift 3.0版本中:

self.textView.textContainer.maximumNumberOfLines = self.textViewNumberOflines
self.textView.textContainer.lineBreakMode = .byTruncatingTail

6

这是Swift 4.2 / Swift 5中Numereyes答案的改进版本

我做了一些扩展,以便可以重用代码。我正在使用While-Loop检查尺寸是否合适。当用户一次粘贴很多文本时,这也适用。

extension UITextView {        
    var numberOfCurrentlyDisplayedLines: Int {
        let size = systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
        //for Swift <=4.0, replace with next line:
        //let size = systemLayoutSizeFitting(UILayoutFittingCompressedSize)

        return Int(((size.height - layoutMargins.top - layoutMargins.bottom) / font!.lineHeight))
    }

    /// Removes last characters until the given max. number of lines is reached
    func removeTextUntilSatisfying(maxNumberOfLines: Int) {
        while numberOfCurrentlyDisplayedLines > (maxNumberOfLines) {
            text = String(text.dropLast())
            layoutIfNeeded()
        }
    }
}

// Use it in UITextView's delegate method:
func textViewDidChange(_ textView: UITextView) {        
    textView.removeTextUntilSatisfying(maxNumberOfLines: 10)
}        

4

斯威夫特4

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    let existingLines = textView.text.components(separatedBy: CharacterSet.newlines)
    let newLines = text.components(separatedBy: CharacterSet.newlines)
    let linesAfterChange = existingLines.count + newLines.count - 1
    return linesAfterChange <= textView.textContainer.maximumNumberOfLines
}

如果您还想限制字符:

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
        let existingLines = textView.text.components(separatedBy: CharacterSet.newlines)
        let newLines = text.components(separatedBy: CharacterSet.newlines)
        let linesAfterChange = existingLines.count + newLines.count - 1
        if(text == "\n") {
            return linesAfterChange <= textView.textContainer.maximumNumberOfLines
        }

        let newText = (textView.text as NSString).replacingCharacters(in: range, with: text)
        let numberOfChars = newText.count
        return numberOfChars <= 30 // 30 characters limit
    }
}

不要忘记添加您希望限制的行数viewDidLoad

txtView.textContainer.maximumNumberOfLines = 2

3

给出的其他解决方案不能解决与在末尾创建最后一行有关的问题(在问题的情况下为第11行)。

这是Swift 4.0&Xcode 9.0 beta的有效解决方案(可在此博客文章中找到)

   class ViewController: UIViewController, UITextViewDelegate {

      @IBOutlet weak var textView: UITextView!

    override func viewDidLoad() {
        super.viewDidLoad()
        textView.delegate = self
        textView.textContainer.maximumNumberOfLines = 10
        textView.textContainer.lineBreakMode = .byWordWrapping
      }

    func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {

        let existingLines = textView.text.components(separatedBy: CharacterSet.newlines)
        let newLines = text.components(separatedBy: CharacterSet.newlines)
        let linesAfterChange = existingLines.count + newLines.count - 1

        return linesAfterChange <= textView.textContainer.maximumNumberOfLines
    }

注意:此解决方案无法处理最后一行太长而无法显示的情况(文本将隐藏在UITextView的最右侧)。


1

与其他答案类似,但可以直接从Storyboard使用,而无需子类化:

extension UITextView {
    @IBInspectable var maxNumberOfLines: NSInteger {
        set {
            textContainer.maximumNumberOfLines = maxNumberOfLines
        }
        get {
            return textContainer.maximumNumberOfLines
        }
    }
    @IBInspectable var lineBreakByTruncatingTail: Bool {
        set {
            if lineBreakByTruncatingTail {
                textContainer.lineBreakMode = .byTruncatingTail
            }
        }
        get {
            return textContainer.lineBreakMode == .byTruncatingTail
        }
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.