Подсчитывая количество строк в UITextView, строки, обернутые размером кадра
Я хотел знать, когда текст обернут рамкой текстового представления, есть ли какой-либо разделитель, с помощью которого мы можем определить, обернут ли текст или нет.
Например, если мое текстовое представление имеет ширину 50 пикселей, а текст превышает его, текст переносится на следующую строку.
Я хотел посчитать количество строк в моем текстовом представлении. Теперь "\n" и "\ r" мне не помогают.
Мой код:
NSCharacterSet *aCharacterSet = [NSCharacterSet characterSetWithCharactersInString:@"\n\r"];
NSArray *myArray = [textViewText componentsSeparatedByCharactersInSet:aCharacterSet];
NSLog(@"%d",[myArray count]);
Ответы
Ответ 1
Этот вариант учитывает, как вы обертываете свои линии и максимальный размер 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;
Ответ 2
Вам нужно использовать свойство lineHeight
и шрифт lineHeight
:
Objective-C
int numLines = txtview.contentSize.height / txtview.font.lineHeight;
стриж
let numLines = (txtview.contentSize.height / txtview.font.lineHeight) as? Int
Я получаю правильное количество строк, надеюсь, это поможет вам тоже.
Ответ 3
Swift 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)
Ответ 4
Я нашел идеальное решение этой проблемы в Apple Руководство по программированию текстового макета. Вот решение, которое 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 в качестве параметра
Ответ 5
Быстрое расширение:
Использование ответа @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()
помните, что если по какой-либо причине шрифт текстового представления равен нулю, возврат будет равен нулю.
Ответ 6
Вам нужно рассмотреть 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 строки)
Ответ 7
Используйте это (где _text_v - это текстовое представление):
-(NSInteger) linesCount {
return _text_v.contentSize.height/_text_v.font.lineHeight;
}
Ответ 8
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
}
Работает отлично для меня
Ответ 9
Swift 4 версия ответа Люка Чейза
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
}
Ответ 10
Я потратил много времени, пытаясь вычислить в реальном времени количество строк для входного TextView (скажем, в окне ввода текста чата), и единственное решение, которое работает в таком случае, - это Luke Chase (по какой-то причине подход frame.height обновляется только когда-либо 3-я или 4-я буква, введенная в 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 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 не предоставляет метод # line из коробки!).
Ответ 11
Версия Simple Swift 4:
extension UITextView {
func numberOfLines() -> Int {
return self.text.components(separatedBy: "\n").count
}
}