【问题标题】:Limit the number of lines for UITextview限制 UITextview 的行数
【发布时间】:2011-07-10 16:36:39
【问题描述】:

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

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

我需要从哪里开始?我用方法做到这一点吗?在

 - (BOOL)textViewShouldBeginEditing:(UITextView *)aTextView

【问题讨论】:

标签: iphone cocoa-touch uitextview


【解决方案1】:

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

iOS 7+

斯威夫特

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

ObjC

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

【讨论】:

  • 这应该是现在公认的答案,即使晚了几年,它也有效!
  • 这是错误的。它允许您在文本视图结束后按回车键,然后光标消失,您必须按删除才能再次找到它。
  • 斯威夫特 2:textView.textContainer.lineBreakMode = .ByTruncatingTail
【解决方案2】:

也许这会有所帮助(iOS 7+):

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

我猜即使第一行也可以解决问题,但不是...可能是 SDK 中的错误

【讨论】:

    【解决方案3】:

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

    【讨论】:

    • 或者您的意思是屏幕上的行,而不是文本的逻辑行?
    • 其实,是的,我想知道屏幕上的台词。我想将一个 txt 文件加载到 UITextView 中,并将屏幕上显示的行数限制为 10 或 15 行,然后将其余的行放在下一个屏幕上。它真的就像一个有单独页面的小型文字处理器。这就是为什么我想限制 UITextView 中显示的行(在屏幕上)。但也许有更简单的方法可以做到这一点?也许使用 UIWebView?
    • 如果您想要的只是分页行为,请注意UITextViewUIScrollView 的子类,pagingEnabled 属性也是如此。
    • 我认为这不起作用,因为 shouldChangeTextInRange 只能计算新输入之前的行数。每次新文本为“\n”时添加一行也不起作用,因为用户可以自然地到达行尾。
    【解决方案4】:

    Swift 3.0 版本中:

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

    【讨论】:

      【解决方案5】:

      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)];对我来说,我必须计算新的高度才能使它起作用
      • 简单而完美的解决方案
      【解决方案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)
      }        
      

      【讨论】:

        【解决方案7】:

        斯威夫特 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
        

        【讨论】:

          【解决方案8】:

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

          这是一个使用 Swift 4.0 和 Xcode 9.0 测试版的有效解决方案(在 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
              }
          

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

          【讨论】:

            【解决方案9】:

            与其他答案类似,但可直接从 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
                    }
                }
            }
            

            【讨论】:

              猜你喜欢
              • 2011-12-12
              • 2023-03-27
              • 2015-10-19
              • 1970-01-01
              • 2011-01-30
              • 1970-01-01
              • 1970-01-01
              • 2011-11-12
              相关资源
              最近更新 更多