Подсчет количества строк в UITextView, строк, обернутых по размеру кадра - PullRequest
23 голосов
/ 30 апреля 2011

Я хотел знать, когда текст оборачивается рамкой текстового представления, есть ли какой-либо разделитель, с помощью которого мы можем определить, обернут ли текст или нет.

Например, если мое текстовое представление имеет ширину 50 пикселей, а текст превышает его, текст переносится на следующую строку.

Я хотел посчитать количество строк в моем текстовом представлении. Теперь "\ n" и "\ r" мне не помогают.

Мой код:

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

Ответы [ 10 ]

27 голосов
/ 30 апреля 2011

Этот вариант учитывает, как вы переносите строки, и максимальный размер 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;
21 голосов
/ 06 марта 2014

Вам необходимо использовать свойство lineHeight и шрифт lineHeight:

Objective-C

int numLines = txtview.contentSize.height / txtview.font.lineHeight;

Swift

let numLines = (txtview.contentSize.height / txtview.font.lineHeight) as? Int

Я получаю правильное количество строк, надеюсь, вам это тоже поможет.

15 голосов
/ 01 апреля 2017

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)
9 голосов
/ 03 сентября 2016

Я нашел идеальное решение этой проблемы в Apple Text Layout Руководство по программированию .Вот решение, которое предлагает 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 в качестве параметра

8 голосов
/ 14 апреля 2016

Быстрое расширение:

Использование ответа @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()

имейте в виду, что если по какой-либо причинешрифт текстового представления - ноль, возвращаемое значение будет ноль.

7 голосов
/ 07 декабря 2015

Необходимо учитывать 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 строки)

4 голосов
/ 28 ноября 2018

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
}
4 голосов
/ 11 апреля 2018
   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
}

отлично работает для меня

4 голосов
/ 30 апреля 2011

Используйте это (где _text_v - ваш текстовый просмотр):

-(NSInteger) linesCount {
    return _text_v.contentSize.height/_text_v.font.lineHeight;
}
1 голос
/ 08 января 2019

Я потратил много времени, пытаясь вычислить в реальном времени количество строк для входного TextView (скажем, в поле ввода текста чата), и единственное решение, которое работает в таком случае, это Люк Чейз (по какой-то причине кадр)Подход .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'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 не предоставляет метод # строки из коробки!).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...