我想知道文本视图的框架包装文本的时间是否有任何分隔符,我们可以使用它来识别文本是否被包装。
例如,如果我的文本视图的宽度为50像素且文本超出该宽度,则会将文本包装到下一行。
我想计算文字视图中的行数。现在“\ n”和“\ r”对我没有帮助。
我的代码是:
NSCharacterSet *aCharacterSet = [NSCharacterSet characterSetWithCharactersInString:@"\n\r"];
NSArray *myArray = [textViewText componentsSeparatedByCharactersInSet:aCharacterSet];
NSLog(@"%d",[myArray count]);
答案 0 :(得分: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;
答案 1 :(得分:21)
您需要使用lineHeight
属性和字体lineHeight
:
<强>目标C 强>
int numLines = txtview.contentSize.height / txtview.font.lineHeight;
<强>夫特强>
let numLines = (txtview.contentSize.height / txtview.font.lineHeight) as? Int
我获得了正确的行数,希望它也能为您提供帮助。
答案 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)
答案 3 :(得分: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);
}
这可以很容易地写入UITextView的扩展,或作为一个独立的方法,将UITextView对象作为参数
答案 4 :(得分:8)
快速扩展:
使用@himanshu padia回答
//MARK: - UITextView
extension UITextView{
func numberOfLines() -> Int{
if let fontUnwrapped = self.font{
return Int(self.contentSize.height / fontUnwrapped.lineHeight)
}
return 0
}
}
用法:yourTextView.numberOfLines()
请注意,如果由于某种原因,文本视图的字体为nil,则返回值为零。
答案 5 :(得分:7)
您需要考虑textView.textContainerInset,还需要舍入计算值,因为行号肯定是一个整数
float rawLineNumber = (textView.contentSize.height - textView.textContainerInset.top - textView.textContainerInset.bottom) / textView.font.lineHeight;
int finalLineNumber = round(rawLineNumber)
在实际情况中,您可能会看到以下结果 rawLineNumber = 3.008099 finalLineNumber = 3(3行)
答案 6 :(得分:4)
使用此(其中_text_v是您的文本视图):
-(NSInteger) linesCount {
return _text_v.contentSize.height/_text_v.font.lineHeight;
}
答案 7 :(得分:4)
func numberOfLines(textView: UITextView) -> Int {
let layoutManager = textView.layoutManager
let numberOfGlyphs = layoutManager.numberOfGlyphs
var lineRange: NSRange = NSMakeRange(0, 1)
var index = 0
var numberOfLines = 0
while index < numberOfGlyphs {
layoutManager.lineFragmentRect(forGlyphAt: index, effectiveRange: &lineRange)
index = NSMaxRange(lineRange)
numberOfLines += 1
}
return numberOfLines
}
为我工作
答案 8 :(得分:3)
Swift 4 版本的 Luke Chase的 answer
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
}
答案 9 :(得分:3)
改进了 Luke Chase's answer并将其更新为Swift 5,XCode 11,iOS 13以获取文本视图行数和自动调整表格视图单元格高度。
您可以使用具有静态单元格高度的情节提要来进行设计。使UITextView 滚动启用:false (禁用滚动)。
在viewDidLoad中添加您的估计行高和textView委托。
override func viewDidLoad() {
super.viewDidLoad()
quoteTextView.delegate = self
tableView.estimatedRowHeight = 142
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
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()
}
}
}
}
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
}
}
->不要忘记禁用uitextview滚动。干杯!<-
预览
答案 10 :(得分:3)
对于那些具有动态字体大小,或混合或不同字体大小以进行丰富消息传递的用户。您可以使用 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
}
}
答案 11 :(得分:1)
我花了很多时间试图实时计算输入TextView的行数(例如聊天文本输入框),并且在这种情况下唯一可行的解决方案是Luke Chase的解决方案(出于某种原因,该框架.height方法似乎只会更新键入到textView中的第三个或第四个字母,因此不准确)。
但是,正如评论者所提到的,存在一个小错误,其中没有正确考虑用户生成的换行符(“ \ n”或键盘回车键)。甚至更陌生,它只会“错过”第一个这样的换行符,任何后续的换行符都会被正确捕获(例如,您进入该行4次,它将仅返回明显缺少第一个换行符的3行)。
为解决该错误,我简单地记录了第一个这样的换行符(字符“ \ n”),并在gliph方法返回的#行中手动添加了一行。
代码中提供:
func offSetTableViewIfNeeded() {
let numberOfGlyphs = textView.layoutManager.numberOfGlyphs
var index : Int = 0
var lineRange = NSRange(location: NSNotFound, length: 0)
var currentNumOfLines : Int = 0
var numberOfParagraphJump : Int = 0
while index < numberOfGlyphs {
textView.layoutManager.lineFragmentRect(forGlyphAt: index, effectiveRange: &lineRange)
index = NSMaxRange(lineRange)
currentNumOfLines += 1
// Observing whether user went to line and if it's the first such line break, accounting for it.
if textView.text.last == "\n", numberOfParagraphJump == 0 {
numberOfParagraphJump = 1
}
}
currentNumOfLines += numberOfParagraphJump
print("Number of lines is:", currentNumOfLines)
希望这可以帮助那些一直在努力应对输入textView的超奇怪行为的人(无法理解为什么Apple不提供开箱即用的方法!)。
答案 12 :(得分:1)
Swift 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
}
}
答案 13 :(得分:0)
我认为您可以尝试使用NSLayoutManager
:
NSLayoutManager *layoutManager = [textView layoutManager];
unsigned numberOfLines, index, numberOfGlyphs =
[layoutManager numberOfGlyphs];
NSRange lineRange;
for (numberOfLines = 0, index = 0; index < numberOfGlyphs; numberOfLines++){
(void) [layoutManager lineFragmentRectForGlyphAtIndex:index
effectiveRange:&lineRange];
index = NSMaxRange(lineRange);
}