Ограничить количество строк для UITextview



мне было интересно, как ограничить количество строк (а не символов, как задано в других вопросах), которые пользователь может ввести при редактировании UITextField.



В идеале, я хотел бы ограничить вход до макс. 10 линий.



С чего бы мне начать? Я делаю это с помощью метода? В



 - (BOOL)textViewShouldBeginEditing:(UITextView *)aTextView
743   8  

8 ответов:

у вас есть правильная идея, но неправильный метод. textView:shouldChangeTextInRange:replacementText: вызывается каждый раз, когда текст будет меняться; вы можете получить доступ к текущему содержимому представления текста, используя text свойство, и вы можете построить новое содержимое из переданного диапазона и заменить текст на [textView.text stringByReplacingCharactersInRange:range withString:replacementText]. Затем вы можете подсчитать количество строк и вернуть да, чтобы разрешить изменение или нет, чтобы отклонить его.

Maciek Czarnik ответ не работал для меня, но это дало мне понимание, что делать.

iOS 7+

Свифт

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

ObjC

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

возможно, это может помочь (iOS 7+):

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

даже первая строка должна сделать трюк, я думаю, но не... Может быть, это ошибка в SDK

ответ Мацека Чарника, похоже, не работает для меня, даже в 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];
    }
}

на Swift 3.0 версия:

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

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

вот рабочее решение с Swift 4.0 & Xcode 9.0 beta (найдено на этот блог)

   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
    }

Nota bene: это решение не обрабатывает сценарий, в котором последняя строка слишком длинна для отображения (текст будет скрыт в дальней правой части UITextView).

похоже на другие ответы, но можно использовать непосредственно из раскадровки и без подклассов:

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

вот улучшенная версия ответа Numereyes в Swift 4

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

extension UITextView {        
    var numberOfCurrentlyDisplayedLines: Int {
        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)
}        

Comments

    Ничего не найдено.