Ограничить количество строк для UITextview
Мне было интересно, как ограничить количество LINES (не символов, как задано в других вопросах), которые пользователь может ввести при редактировании UITextField.
В идеале я хотел бы ограничить ввод до макс. 10 строк.
Где мне нужно начинать? Я делаю это с помощью метода? В
- (BOOL)textViewShouldBeginEditing:(UITextView *)aTextView
Ответы
Ответ 1
У вас есть правильная идея, но неправильный метод. textView:shouldChangeTextInRange:replacementText:
вызывается всякий раз, когда текст будет изменяться; вы можете получить доступ к текущему содержимому текстового представления, используя его свойство text
, и вы можете создать новое содержимое из пройденного диапазона и заменить текст [textView.text stringByReplacingCharactersInRange:range withString:replacementText]
. Затем вы можете подсчитать количество строк и вернуть YES, чтобы разрешить изменение, или NO, чтобы отклонить его.
Ответ 2
Maciek Czarnik ответ не сработал у меня, но он дал мне понять, что делать.
iOS 7 +
Свифта
textView.textContainer.maximumNumberOfLines = 10
textView.textContainer.lineBreakMode = .byTruncatingTail
ObjC
textView.textContainer.maximumNumberOfLines = 10;
textView.textContainer.lineBreakMode = NSLineBreakByTruncatingTail;
Ответ 3
Возможно, это может помочь (iOS 7 +):
textView.textContainer.maximumNumberOfLines = 10;
[textView.layoutManager textContainerChangedGeometry:textView.textContainer];
Даже первая строка должна делать трюк, я думаю, но не... Может быть, его ошибка в SDK
Ответ 4
Maciek Czarnik ответ, похоже, не работает для меня, даже в 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];
}
}
Ответ 5
в Swift 3.0
версии:
self.textView.textContainer.maximumNumberOfLines = self.textViewNumberOflines
self.textView.textContainer.lineBreakMode = .byTruncatingTail
Ответ 6
Здесь улучшенная версия ответа Numereyes в Swift 4
Я сделал небольшое расширение, чтобы я мог повторно использовать код. Я использую цикл while, чтобы проверить, подходит ли размер. Это также работает, когда пользователь вставляет много текста одновременно.
extension UITextView {
var numberOfCurrentlyDisplayedLines: Int {
let size = systemLayoutSizeFitting(UILayoutFittingCompressedSize)
//for Swift 4.2, replace with next line:
//let size = systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
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 delegate method:
func textViewDidChange(_ textView: UITextView) {
textView.removeTextUntilSatisfying(maxNumberOfLines: 10)
}
Ответ 7
Другие приведенные решения не решают проблему, связанную с последней строкой, созданной в конце (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).
Ответ 8
Как и другие ответы, но можно использовать непосредственно из Storyboard и без подкласса:
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
}
}
}