Je me demandais comment limiter la quantité de LINES (pas les caractères comme demandé dans d’autres questions) qu’un utilisateur peut entrer lors de l’édition d’un UITextField.
Idéalement, je voudrais limiter l’entrée à max. 10 lignes.
Où devrais-je commencer? Est-ce que je le fais avec une méthode? Dans
- (BOOL)textViewShouldBeginEditing:(UITextView *)aTextView
Vous avez la bonne idée, mais la mauvaise méthode. textView:shouldChangeTextInRange:replacementText:
est appelé chaque fois que le texte doit être modifié. Vous pouvez accéder au contenu actuel de la vue texte en utilisant sa propriété text
et vous pouvez créer le nouveau contenu à partir de la plage et du texte de remplacement avec [textView.text ssortingngByReplacingCharactersInRange:range withSsortingng:replacementText]
. Vous pouvez alors compter le nombre de lignes et retourner OUI pour autoriser le changement ou NON pour le rejeter.
Maciek Czarnik répond que ça n’a pas marché pour moi, mais ça m’a donné un aperçu de ce qu’il faut faire.
iOS 7+
Rapide
textView.textContainer.maximumNumberOfLines = 10 textView.textContainer.lineBreakMode = .byTruncatingTail
ObjC
textView.textContainer.maximumNumberOfLines = 10; textView.textContainer.lineBreakMode = NSLineBreakByTruncatingTail;
Peut-être que cela peut aider (iOS 7+):
textView.textContainer.maximumNumberOfLines = 10; [textView.layoutManager textContainerChangedGeometry:textView.textContainer];
Même la première ligne devrait faire l’affaire, mais ce n’est pas … Peut-être que c’est un bogue dans le SDK
La réponse de Maciek Czarnik ne semble pas fonctionner pour moi, même dans iOS7. Cela me donne un comportement étrange, je ne sais pas pourquoi.
Ce que je fais pour limiter le nombre de lignes dans UITextView est simplement:
(testé uniquement sur iOS7) Dans la méthode UITextViewDelegate suivante:
- (void)textViewDidChange:(UITextView *)textView { NSUInteger maxNumberOfLines = 5; NSUInteger numLines = textView.contentSize.height/textView.font.lineHeight; if (numLines > maxNumberOfLines) { textView.text = [textView.text subssortingngToIndex:textView.text.length - 1]; } }
dans la version Swift 3.0
:
self.textView.textContainer.maximumNumberOfLines = self.textViewNumberOflines self.textView.textContainer.lineBreakMode = .byTruncatingTail
Voici une version améliorée de la réponse de Numereyes dans Swift 4
J’ai fait une petite extension pour pouvoir réutiliser le code. J’utilise une boucle While pour vérifier si la taille correspond. Cela fonctionne également lorsque l’utilisateur colle beaucoup de texte à la fois.
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 = Ssortingng(text.dropLast()) layoutIfNeeded() } } } // Use it in UITextView's delegate method: func textViewDidChange(_ textView: UITextView) { textView.removeTextUntilSatisfying(maxNumberOfLines: 10) }
Les autres solutions proposées ne résolvent pas un problème lié à la création d’une dernière ligne à la fin (une 11ème ligne dans le cas de la question).
Voici une solution de travail avec Swift 4.0
& Xcode 9.0 beta (disponible sur ce billet de blog )
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: Ssortingng) -> 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: Cette solution ne gère pas le scénario où la dernière ligne est trop longue à afficher (le texte sera caché à l'extrême droite de UITextView).
Similaire aux autres réponses, mais utilisable directement depuis Storyboard et sans sous-classement:
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 } } }