计算UITextView中的行数,按帧大小包装的行

Abh*_*nav 25 cocoa-touch objective-c uitextview ios

我想知道文本视图的框架包装文本的时间是否有任何分隔符,我们可以使用它来识别文本是否被包装.

例如,如果我的文本视图的宽度为50像素且文本超出该宽度,则会将文本包装到下一行.

我想计算文本视图中的行数.现在"\n"和"\ r"对我没有帮助.

我的代码是:

NSCharacterSet *aCharacterSet = [NSCharacterSet characterSetWithCharactersInString:@"\n\r"];
    NSArray *myArray = [textViewText componentsSeparatedByCharactersInSet:aCharacterSet];
    NSLog(@"%d",[myArray count]);
Run Code Online (Sandbox Code Playgroud)

Jan*_*ano 27

此变化考虑了如何包裹线条和最大尺寸UITextView,并可能输出更精确的高度.例如,如果文本不适合它将截断为可见大小,如果您包装整个单词(这是默认值),它可能会产生比其他情况更多的行.

UIFont *font = [UIFont boldSystemFontOfSize:11.0];
CGSize size = [string sizeWithFont:font 
                      constrainedToSize:myUITextView.frame.size 
                      lineBreakMode:UILineBreakModeWordWrap]; // default mode
float numberOfLines = size.height / font.lineHeight;
Run Code Online (Sandbox Code Playgroud)


Him*_*dia 24

你需要使用lineHeight属性和字体lineHeight:

Objective-C的

int numLines = txtview.contentSize.height / txtview.font.lineHeight;
Run Code Online (Sandbox Code Playgroud)

迅速

let numLines = (txtview.contentSize.height / txtview.font.lineHeight) as? Int
Run Code Online (Sandbox Code Playgroud)

我得到正确的行数,希望它也能帮到你.

  • 这对我来说非常有用,但是,答案中没有提到的一点是,它没有考虑具有不同字体的属性文本。具体来说,是具有变化的行高的字体。对于那些情况,您可能必须使用[boundingRectWithSize:options:attributes:context:](https://developer.apple.com/documentation/foundation/nsstring/1524729-boundingrectwithsize),因为[sizeWithFont:constrainedToSize:](https现在不建议使用://developer.apple.com/documentation/foundation/nsstring/1619910-sizewithfont)。 (2认同)

小智 15

斯威夫特3:

let layoutManager:NSLayoutManager = textView.layoutManager
let numberOfGlyphs = layoutManager.numberOfGlyphs
var numberOfLines = 0
var index = 0
var lineRange:NSRange = NSRange()

while (index < numberOfGlyphs) {
    layoutManager.lineFragmentRect(forGlyphAt: index, effectiveRange: &lineRange)
    index = NSMaxRange(lineRange);
    numberOfLines = numberOfLines + 1
}

print(numberOfLines)
Run Code Online (Sandbox Code Playgroud)

  • 方法 numberOfLines() 不计算新行,然后它有第一个 \n 符号。这个方法不正确 (3认同)

小智 11

Swift 4版本的Luke Chase 的 答案

let numberOfGlyphs = textView.layoutManager.numberOfGlyphs
var index = 0, numberOfLines = 0
var lineRange = NSRange(location: NSNotFound, length: 0)

while index < numberOfGlyphs {
  textView.layoutManager.lineFragmentRect(forGlyphAt: index, effectiveRange: &lineRange)
  index = NSMaxRange(lineRange)
  numberOfLines += 1
}
Run Code Online (Sandbox Code Playgroud)


Jua*_*ero 10

Swift扩展:

用@himanshu padia回答

//MARK: - UITextView
extension UITextView{

    func numberOfLines() -> Int{
        if let fontUnwrapped = self.font{
            return Int(self.contentSize.height / fontUnwrapped.lineHeight)
        }
        return 0
    }

}
Run Code Online (Sandbox Code Playgroud)

用法: yourTextView.numberOfLines()

请注意,如果由于某种原因,文本视图的字体为nil,则返回值为零.


小智 9

我在Apple的Text Layout Programming Guide中找到了解决这个问题的完美解决方案.以下是Apple提供的解决方案:

NSLayoutManager *layoutManager = [textView layoutManager];
unsigned numberOfLines, index;
unsigned numberOfGlyphs = [layoutManager numberOfGlyphs];
NSRange lineRange;

for (numberOfLines = 0, index = 0; index < numberOfGlyphs; numberOfLines++){
    (void) [layoutManager lineFragmentRectForGlyphAtIndex:index effectiveRange:&lineRange];
    index = NSMaxRange(lineRange);
}
Run Code Online (Sandbox Code Playgroud)

这可以很容易地写入UITextView的扩展,或作为一个独立的方法,将UITextView对象作为参数


Doc*_*oca 8

改进并更新了Luke Chase 对 Swift 5、XCode 11、iOS 13 的 回答,以获取文本视图行数并自动调整表格视图单元格高度。

  1. 您可以使用具有静态单元高度的故事板来根据需要进行设计。使 UITextView滚动启用: false(禁用滚动)。

  2. 在 viewDidLoad 中添加您的估计行高和 textView 委托。

override func viewDidLoad() {
        super.viewDidLoad()

        quoteTextView.delegate = self
        tableView.estimatedRowHeight = 142

    }
Run Code Online (Sandbox Code Playgroud)
  1. 为 heightForRowAt 添加表视图委托:
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableView.automaticDimension
}
Run Code Online (Sandbox Code Playgroud)
  1. 符合 UITextViewDelegate 在用户输入文本时监听。
extension ViewController: UITextViewDelegate {
    func textViewDidChange(_ textView: UITextView) {
        // Refresh tableView cell
        if textView.numberOfLines > 2 { // textView in storyboard has two lines, so we match the design
            // Animated height update
            DispatchQueue.main.async {
                self.tableView?.beginUpdates()
                self.tableView?.endUpdates()
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)
  1. 添加 UITextView 扩展,这样您就可以避免冗余代码并在整个应用程序中使用。
extension UITextView {
    var numberOfLines: Int {
        // Get number of lines
        let numberOfGlyphs = self.layoutManager.numberOfGlyphs
        var index = 0, numberOfLines = 0
        var lineRange = NSRange(location: NSNotFound, length: 0)

        while index < numberOfGlyphs {
            self.layoutManager.lineFragmentRect(forGlyphAt: index, effectiveRange: &lineRange)
          index = NSMaxRange(lineRange)
          numberOfLines += 1
        }

        return numberOfLines
    }
}
Run Code Online (Sandbox Code Playgroud)

-> 不要忘记禁用 uitextview 滚动。干杯!<-

预览

在此输入图像描述


Jac*_*cky 7

您需要考虑textView.textContainerInset,还需要舍入计算值,因为行号肯定是一个整数

float rawLineNumber = (textView.contentSize.height - textView.textContainerInset.top - textView.textContainerInset.bottom) / textView.font.lineHeight;
int finalLineNumber = round(rawLineNumber)
Run Code Online (Sandbox Code Playgroud)

在实际情况中,您可能会看到以下结果rawLineNumber = 3.008099 finalLineNumber = 3(3行)


Tà *_*ada 7

斯威夫特 5.0

extension UITextView {
    func sizeFit(width: CGFloat) -> CGSize {
        let fixedWidth = width
        let newSize = sizeThatFits(CGSize(width: fixedWidth, height: .greatestFiniteMagnitude))
        return CGSize(width: fixedWidth, height: newSize.height)
    }

    func numberOfLine() -> Int {
        let size = self.sizeFit(width: self.bounds.width)
        let numLines = Int(size.height / (self.font?.lineHeight ?? 1.0))
        return numLines
    }
}
Run Code Online (Sandbox Code Playgroud)


Max*_*Max 5

使用它(其中 _text_v 是您的文本视图):

-(NSInteger) linesCount {
    return _text_v.contentSize.height/_text_v.font.lineHeight;
}
Run Code Online (Sandbox Code Playgroud)


rev*_*ilo 5

对于那些拥有动态字体大小或混合或不同字体大小以实现丰富消息传递的用户。您可以使用 NSLayoutManager 来准确计算行高,正如其他人正确指出的那样。

正如 Dmitry Petukhov 指出的那样,一个额外的问题是简单的实现没有考虑新行。layoutManager.extraLineFragmentRect您可以使用布局管理器通过检查文档NSLayoutManager#extraLineFragmentRect来解决此问题

包围额外线片段矩形中插入点的矩形

该矩形是在其 NSTextContainer 的坐标系中定义的。NSZeroRect 如果没有多余的线片段矩形。

因此,我们只需要检测何时extraLineFragmentUsedRect 填充 ( != CGRect.zero) - 这意味着有一个换行符作为结尾,并相应地更正行数。

完整示例如下。

extension UITextView {
    public var lineCount: Int {
        let numberOfGlyphs = layoutManager.numberOfGlyphs
        var index = 0, numberOfLines = 0
        var lineRange = NSRange(location: NSNotFound, length: 0)

        while index < numberOfGlyphs {
            layoutManager.lineFragmentRect(forGlyphAt: index, effectiveRange: &lineRange)
            index = NSMaxRange(lineRange)
            numberOfLines += 1
        }
        // Take into account newlines at the bottom.
        if layoutManager.extraLineFragmentUsedRect != CGRect.zero {
            numberOfLines += 1
        }
        return numberOfLines
    }
}
Run Code Online (Sandbox Code Playgroud)