it-swarm.com.ru

Подсчет количества строк в UITextView, строк, обернутых по размеру кадра

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

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

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

Мой код:

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

Этот вариант учитывает способ переноса строк и максимальный размер 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;
27
Jano

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

Objective-C

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

Свифт

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

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

18
Himanshu padia

Свифт 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)
13
castillejoale

Я нашел идеальное решение этой проблемы в Apple Text Layout 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

9
Luke Chase

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

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

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

8
Juan Boero

Необходимо учитывать 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
Jacky
   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
Softlabsindia

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

-(NSInteger) linesCount {
    return _text_v.contentSize.height/_text_v.font.lineHeight;
}
4
Max

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
}
1
Yeesha

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

0
Franc