限制UITextview的行数

时间:2011-03-07 21:58:05

标签: iphone cocoa-touch uitextview

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

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

我需要从哪里开始?我是用方法做的吗?在

 - (BOOL)textViewShouldBeginEditing:(UITextView *)aTextView

9 个答案:

答案 0 :(得分:191)

Maciek Czarnik的回答对我不起作用,但它让我了解了该怎么做。

iOS 7 +

夫特

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

ObjC

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

答案 1 :(得分:50)

也许这可以提供帮助(iOS 7 +):

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

即便是第一行我应该做的伎俩,但不是......也许它是SDK中的一个错误

答案 2 :(得分:15)

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

答案 3 :(得分:11)

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];
    }
}

答案 4 :(得分:11)

<{1>}版本中的

Swift 3.0

答案 5 :(得分:4)

以下是 Swift 4

中Numereyes答案的改进版本

我做了一点扩展,所以我可以重用代码。 我正在使用While-Loop来检查尺寸是否合适。当用户一次粘贴大量文本时,这也有效。

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

        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)
}        

答案 6 :(得分:2)

给出的其他解决方案没有解决与最后一行创建的问题(问题的第11行)。

这是一个有Swift 4.0&amp;的工作解决方案。 Xcode 9.0 beta(在this blog post上找到)

   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
    }

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

答案 7 :(得分:1)

与其他答案类似,但可直接从故事板中使用,无需子类化:

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
        }
    }
}

答案 8 :(得分:0)

快速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