Обмежте кількість рядків для UITextview


76

Мені було цікаво, як обмежити кількість ЛІНІЙ (а не символів, як задається в інших питаннях), які користувач може вводити під час редагування UITextField.

В ідеалі я хотів би обмежити вхід до макс. 10 рядків

З чого мені потрібно почати? Чи роблю я це методом? В

 - (BOOL)textViewShouldBeginEditing:(UITextView *)aTextView

Ви можете знайти свою відповідь у цьому дописі .
Закарія

Відповіді:


15

Ви маєте правильну ідею, але неправильний метод. textView:shouldChangeTextInRange:replacementText:викликається, коли текст буде змінюватися; Ви можете отримати доступ до поточного вмісту подання тексту за допомогою його textвластивості, а також можете створити новий вміст із переданого діапазону та тексту заміщення за допомогою [textView.text stringByReplacingCharactersInRange:range withString:replacementText]. Потім можна порахувати кількість рядків і повернути ТАК, щоб дозволити зміну, або НІ відхилити її.


Або ви мали на увазі екранні рядки, а не логічні рядки тексту?
Anomie

Насправді так, я хочу знати екранні рядки. Я хочу завантажити файл txt у UITextView та обмежити рядки, показані на екрані, до 10 або 15, а потім залишити на наступному екрані. Це справді як маленький текстовий процесор, який має окремі сторінки. Ось чому я хочу обмежити рядки (на екрані), що відображаються в UITextView. Але, можливо, існує простіший спосіб зробити це? Можливо, скористатися UIWebView?
n.evermind

1
Якщо все, що вам потрібно - це поведінка на сторінках, зверніть увагу, що UITextViewце підклас UIScrollViewі, таким чином, має pagingEnabledвластивість.
Anomie

Я не думаю, що це працює належним чиномChangeTextInRange може підрахувати лише кількість рядків до нового введення. Додавання рядка для кожного разу, коли новий текст "\ n", також не працює, оскільки користувач може природно дійти до кінця рядка.
Declan McKenna

239

Відповідь Маціека Чарніка не спрацював для мене, але він зрозумів, що мені робити.

iOS 7+

Стрімкий

textView.textContainer.maximumNumberOfLines = 10
textView.textContainer.lineBreakMode = .byTruncatingTail

ObjC

textView.textContainer.maximumNumberOfLines = 10;
textView.textContainer.lineBreakMode = NSLineBreakByTruncatingTail;

3
Це має бути прийнятою відповіддю зараз, навіть якщо це запізнилося на кілька років, це працює!
Зігфулт

34
Це глючить. Це дозволяє натиснути кнопку повернення після кінця подання тексту, а потім курсор зникає, і вам потрібно натиснути кнопку видалення, щоб знайти його знову.
Ерік Коннер,

Свіфт 2:textView.textContainer.lineBreakMode = .ByTruncatingTail
App Dev Guy,

55

Можливо, це може допомогти (iOS 7+):

textView.textContainer.maximumNumberOfLines = 10;
[textView.layoutManager textContainerChangedGeometry:textView.textContainer];

Навіть перший рядок повинен зробити трюк, я думаю, але ні ... Можливо, це помилка в SDK


12

Відповідь Мацієка Чарніка, здається, не працює для мене навіть у iOS7. Це дає мені дивну поведінку, я не знаю чому.

Що я роблю, щоб обмежити кількість рядків у UITextView, це просто:

(протестовано лише в iOS7) У наступному методі UITextViewDelegate:

- (void)textViewDidChange:(UITextView *)textView
{
    NSUInteger maxNumberOfLines = 5;
    NSUInteger numLines = textView.contentSize.height/textView.font.lineHeight;
    if (numLines > maxNumberOfLines)
    {
        textView.text = [textView.text substringToIndex:textView.text.length - 1];
    }
}

Розмір CGSize = [textView sizeThatFits: CGSizeMake (textView.width, MAXFLOAT)]; для мене мені довелося розрахувати нову висоту, це буде для того, щоб це працювало
тетофанзивна

приємне рішення просте і досконале
aftab muhammed khan

11

у Swift 3.0версії:

self.textView.textContainer.maximumNumberOfLines = self.textViewNumberOflines
self.textView.textContainer.lineBreakMode = .byTruncatingTail

7

Ось покращена версія відповіді Numereyes у Swift 4.2 / Swift 5

Я зробив невелике розширення, щоб я міг повторно використовувати код. Я використовую цикл While-Loop, щоб перевірити, чи відповідає розмір. Це також працює, коли користувач вставляє багато тексту одночасно.

extension UITextView {        
    var numberOfCurrentlyDisplayedLines: Int {
        let size = systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
        //for Swift <=4.0, replace with next line:
        //let size = systemLayoutSizeFitting(UILayoutFittingCompressedSize)

        return Int(((size.height - layoutMargins.top - layoutMargins.bottom) / font!.lineHeight))
    }

    /// Removes last characters until the given max. number of lines is reached
    func removeTextUntilSatisfying(maxNumberOfLines: Int) {
        while numberOfCurrentlyDisplayedLines > (maxNumberOfLines) {
            text = String(text.dropLast())
            layoutIfNeeded()
        }
    }
}

// Use it in UITextView's delegate method:
func textViewDidChange(_ textView: UITextView) {        
    textView.removeTextUntilSatisfying(maxNumberOfLines: 10)
}        

4

Стрімкий 4

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    let existingLines = textView.text.components(separatedBy: CharacterSet.newlines)
    let newLines = text.components(separatedBy: CharacterSet.newlines)
    let linesAfterChange = existingLines.count + newLines.count - 1
    return linesAfterChange <= textView.textContainer.maximumNumberOfLines
}

І якщо ви також хочете обмежити символи:

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
        let existingLines = textView.text.components(separatedBy: CharacterSet.newlines)
        let newLines = text.components(separatedBy: CharacterSet.newlines)
        let linesAfterChange = existingLines.count + newLines.count - 1
        if(text == "\n") {
            return linesAfterChange <= textView.textContainer.maximumNumberOfLines
        }

        let newText = (textView.text as NSString).replacingCharacters(in: range, with: text)
        let numberOfChars = newText.count
        return numberOfChars <= 30 // 30 characters limit
    }
}

не забудьте додати, скільки рядків ви хочете, щоб був обмеження viewDidLoad:

txtView.textContainer.maximumNumberOfLines = 2

3

Інші наведені рішення не вирішують проблеми, пов’язані з останнім рядком, що створюється в кінці (11-й рядок у випадку запитання).

Ось робоче рішення з Swift 4.0бета-версією & Xcode 9.0 (знайдено в цьому дописі в блозі )

   class ViewController: UIViewController, UITextViewDelegate {

      @IBOutlet weak var textView: UITextView!

    override func viewDidLoad() {
        super.viewDidLoad()
        textView.delegate = self
        textView.textContainer.maximumNumberOfLines = 10
        textView.textContainer.lineBreakMode = .byWordWrapping
      }

    func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {

        let existingLines = textView.text.components(separatedBy: CharacterSet.newlines)
        let newLines = text.components(separatedBy: CharacterSet.newlines)
        let linesAfterChange = existingLines.count + newLines.count - 1

        return linesAfterChange <= textView.textContainer.maximumNumberOfLines
    }

Примітка: Це рішення не обробляє сценарій, коли останній рядок занадто довгий для відображення (текст буде приховано в крайній правій частині UITextView).


1

Подібно до інших відповідей, але можна використовувати безпосередньо з розкадровки та без підкласів:

extension UITextView {
    @IBInspectable var maxNumberOfLines: NSInteger {
        set {
            textContainer.maximumNumberOfLines = maxNumberOfLines
        }
        get {
            return textContainer.maximumNumberOfLines
        }
    }
    @IBInspectable var lineBreakByTruncatingTail: Bool {
        set {
            if lineBreakByTruncatingTail {
                textContainer.lineBreakMode = .byTruncatingTail
            }
        }
        get {
            return textContainer.lineBreakMode == .byTruncatingTail
        }
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.