J'ai un UITextView
dans mon application iOS, qui affiche une grande quantité de texte.
Je recherche ensuite ce texte en utilisant le paramètre de marge de décalage du UITextView
.
Mon problème est que le remplissage du UITextView
est déroutant mes calculs car il semble être différent selon la taille de police et la police que j'utilise.
Par conséquent, je pose la question: est-il possible de supprimer le rembourrage entourant le contenu du UITextView
?
Au plaisir d'entendre vos réponses!
ios
iphone
cocoa-touch
uikit
uitextview
sniurkst
la source
la source
Réponses:
À jour pour 2019
C'est l'un des bogues les plus stupides d'iOS.
La classe donnée ici
UITextViewFixed
est généralement la solution la plus raisonnable.Voici la classe:
N'oubliez pas de désactiver scrollEnabled dans l'inspecteur!
La solution fonctionne correctement dans le storyboard
La solution fonctionne correctement lors de l'exécution
Voilà, vous avez terminé.
En général, cela devrait être tout ce dont vous avez besoin dans la plupart des cas .
Même si vous modifiez la hauteur de la vue texte à la volée , fait
UITextViewFixed
généralement tout ce dont vous avez besoin.(Un exemple courant de modification de la hauteur à la volée est de la modifier au fur et à mesure que l'utilisateur tape.)
Voici le UITextView cassé d'Apple ...
Voici
UITextViewFixed
:Notez bien sûr que vous devez
désactiver scrollEnabled dans l'inspecteur!
N'oubliez pas de désactiver scrollEnabled! :)
Quelques autres problèmes
(1) Dans certains cas inhabituels - par exemple, certains cas de tables avec des hauteurs de cellule flexibles et changeantes dynamiquement - Apple fait une chose bizarre: ils ajoutent de l'espace supplémentaire en bas . Pas vraiment! Cela devrait être l'une des choses les plus exaspérantes d'iOS.
Voici une "solution miracle" à ajouter à ce qui précède qui aide généralement à cette folie.
(2) Parfois, pour corriger un autre subtil désordre d'Apple, vous devez ajouter ceci:
(3) Sans doute, nous devrions ajouter:
juste après
.lineFragmentPadding = 0
dansUITextViewFixed
.Cependant ... croyez ou non ... cela ne fonctionne tout simplement pas dans iOS actuel! (Vérifié en 2019.) Il peut être nécessaire d'ajouter cette ligne à l'avenir.
Le fait que cela
UITextView
soit cassé dans iOS est l'une des choses les plus étranges de tout l'informatique mobile. Dixième anniversaire de cette question et ce n'est toujours pas résolu!Enfin, voici une astuce quelque peu similaire pour Text Field : https://stackoverflow.com/a/43099816/294884
Astuce complètement aléatoire: comment ajouter le "..." à la fin
Souvent, vous utilisez un UITextView "comme un UILabel". Vous voulez donc qu'il tronque le texte en utilisant des points de suspension "..."
Si oui, ajoutez une troisième ligne de code dans le "setup":
Astuce pratique si vous voulez une hauteur nulle, quand, il n'y a pas de texte du tout
Souvent, vous utilisez une vue texte pour n'afficher que du texte. Ainsi, l'utilisateur ne peut rien modifier. Vous utilisez les lignes "0" pour signifier que la vue du texte changera automatiquement de hauteur en fonction du nombre de lignes de texte.
C'est super, mais s'il n'y a pas de texte du tout, malheureusement, vous obtenez la même hauteur que s'il y a une ligne de texte !! La vue texte ne "disparaît" jamais.
Si vous voulez qu'il "s'en aille", ajoutez simplement ceci
(Je l'ai fait «1» donc il est clair ce qui se passe, «0» est très bien.)
Et UILabel?
Lors de l'affichage de texte, UILabel présente de nombreux avantages par rapport à UITextView. UILabel ne souffre pas des problèmes décrits sur cette page QA. En effet, la raison pour laquelle nous «abandonnons» habituellement et utilisons simplement UITextView est qu'il est difficile de travailler avec UILabel. En particulier, il est ridiculement difficile de simplement ajouter un rembourrage , correctement, à UILabel. En fait, voici une discussion complète sur la façon d'ajouter "enfin" correctement le remplissage à UILabel: https://stackoverflow.com/a/58876988/294884 Dans certains cas, si vous effectuez une mise en page difficile avec des cellules de hauteur dynamique, il est parfois il vaut mieux le faire à la dure avec UILabel.
la source
self.textView.isScrollEnabled = false
intérieurviewDidLayoutSubviews()
et cela a fonctionné aussi. Apple aime juste nous faire sauter à travers des cerceaux :)translatesAutoresizingMaskIntoConstraints
. Avec cette seule réponse, je n'ai pas pu supprimer toutes les marges (une étrange marge inférieure a résisté à disparaître) dans une hiérarchie de vues utilisant la mise en page automatique. Il traite également du calcul des tailles de vue à l'aidesystemLayoutSizeFitting
, quiUITextView
Pour iOS 7.0, j'ai constaté que l'astuce contentInset ne fonctionne plus. C'est le code que j'ai utilisé pour me débarrasser de la marge / du remplissage dans iOS 7.
Cela amène le bord gauche du texte au bord gauche du conteneur:
Cela provoque l'alignement du haut du texte avec le haut du conteneur
Les deux lignes sont nécessaires pour supprimer complètement la marge / le rembourrage.
la source
self.descriptionTextView.textContainerInset = UIEdgeInsetsZero;
lineFragmentPadding
à 0 est la magie que je recherchais. Je ne sais pas pourquoi Apple rend si difficile d'aligner le contenu UITextView avec d'autres contrôles.lineFragmentPadding
n'est pas destiné à modifier les marges. À partir de la documentation, le remplissage du fragment de ligne n'est pas conçu pour exprimer des marges de texte. Au lieu de cela, vous devez utiliser des encarts sur votre affichage de texte, ajuster les attributs de marge de paragraphe ou modifier la position de l'affichage de texte dans sa vue d'ensemble.Cette solution de contournement a été écrite en 2009 lors de la sortie d'IOS 3.0. Cela ne s'applique plus.
J'ai rencontré exactement le même problème, à la fin j'ai dû finir par utiliser
où nameField est un
UITextView
. La police que j'utilisais était Helvetica 16 points. Ce n'est qu'une solution personnalisée pour la taille de champ particulière que je dessinais. Cela fait que le décalage gauche affleure le côté gauche et le décalage supérieur où je le veux pour la boîte son dessin.De plus, cela ne semble s'appliquer qu'à l'
UITextViews
endroit où vous utilisez l'alignement par défaut, c'est-à-dire.Alignez à droite par exemple et le
UIEdgeInsetsMake
semble ne pas avoir d'impact du tout sur le bord droit.À tout le moins, l'utilisation de la propriété .contentInset vous permet de placer vos champs avec les positions "correctes" et de tenir compte des écarts sans compenser votre
UITextViews
.la source
En s'appuyant sur certaines des bonnes réponses déjà données, voici une solution purement basée sur Storyboard / Interface Builder qui fonctionne dans iOS 7.0+
Définissez les attributs d' exécution définis par l'utilisateur de UITextView pour les clés suivantes:
la source
Sur iOS 5
UIEdgeInsetsMake(-8,-8,-8,-8);
semble très bien fonctionner.la source
J'éviterais certainement toute réponse impliquant des valeurs codées en dur, car les marges réelles peuvent changer avec les paramètres de taille de police de l'utilisateur, etc.
Voici la réponse de @ user1687195, écrite sans modifier le
textContainer.lineFragmentPadding
(car les documents indiquent que ce n'est pas l'usage prévu).Cela fonctionne très bien pour iOS 7 et versions ultérieures.
C'est effectivement le même résultat, juste un peu plus propre en ce qu'il n'utilise pas la propriété lineFragmentPadding de manière abusive.
la source
self.textView.textContainer.lineFragmentPadding = 0;
lineFragmentPadding
n'est pas censé contrôler les marges. Voilà pourquoi vous êtes censé utilisertextContainerInset
.Storyboard ou solution Interface Builder utilisant des attributs d'exécution définis par l' utilisateur :
Les captures d'écran sont d'iOS 7.1 et iOS 6.1 avec
contentInset = {{-10, -5}, {0, 0}}
.la source
Toutes ces réponses répondent à la question du titre, mais je voulais proposer des solutions aux problèmes présentés dans le corps de la question du PO.
Taille du contenu du texte
Un moyen rapide de calculer la taille du texte à l'intérieur du
UITextView
est d'utiliserNSLayoutManager
:Cela donne le contenu défilant total, qui peut être plus grand que le
UITextView
cadre du. J'ai trouvé que c'était beaucoup plus précis quetextView.contentSize
cela car il calcule réellement la place que prend le texte. Par exemple, étant donné un videUITextView
:Hauteur de la ligne
UIFont
possède une propriété qui vous permet d'obtenir rapidement la hauteur de ligne pour la police donnée. Ainsi, vous pouvez trouver rapidement la hauteur de ligne du texte dans votreUITextView
avec:Calcul de la taille du texte visible
Déterminer la quantité de texte réellement visible est important pour gérer un effet de «pagination».
UITextView
a une propriété appeléetextContainerInset
qui est en fait une marge entre le réelUITextView.frame
et le texte lui-même. Pour calculer la hauteur réelle du cadre visible, vous pouvez effectuer les calculs suivants:Détermination de la taille de la pagination
Enfin, maintenant que vous avez la taille du texte et le contenu visibles, vous pouvez rapidement déterminer quels devraient être vos décalages en soustrayant le
textHeight
dutextSize
:En utilisant toutes ces méthodes, je n'ai pas touché mes encarts et j'ai pu aller au curseur ou n'importe où dans le texte que je veux.
la source
vous pouvez utiliser la
textContainerInset
propriété deUITextView
:textView.textContainerInset = UIEdgeInsetsMake (10, 10, 10, 10);
(haut, gauche, bas, droite)
la source
textContainerInset
propriété ne fonctionne pas pour moi lorsque je souhaite la changer en une nouvelle valeur — voir stackoverflow.com/questions/19422578/… .Pour iOS 10, la ligne suivante fonctionne pour la suppression du rembourrage supérieur et inférieur.
la source
UIEdgeInset.zero
fonctionne avec XCode 8.3 et iOS 10.3 SimulatorDernier Swift:
la source
Voici une version mise à jour de la réponse très utile de Fattie. Il ajoute 2 lignes importantes qui m'ont aidé à faire fonctionner la mise en page sur iOS 10 et 11 (et probablement aussi sur les plus basses):
Les lignes importantes sont les deux
translatesAutoresizingMaskIntoConstraints = <true/false>
déclarations!Cela supprime étonnamment toutes les marges dans toutes mes circonstances!
Bien que ce
textView
ne soit pas le premier répondant, il peut arriver qu'il y ait une marge inférieure étrange qui n'a pas pu être résolue en utilisant lasizeThatFits
méthode mentionnée dans la réponse acceptée.En tapant dans le textView soudainement, l'étrange marge inférieure a disparu et tout ressemblait à ce qu'il devrait, mais seulement dès que le textView a été
firstResponder
.Je lis donc ici sur SO que l'activation et la désactivation
translatesAutoresizingMaskIntoConstraints
aident à définir manuellement le cadre / les limites entre les appels.Heureusement, cela fonctionne non seulement avec le réglage du cadre, mais avec les 2 lignes de
setup()
sandwich entre les deuxtranslatesAutoresizingMaskIntoConstraints
appels!Ceci est par exemple très utile lors du calcul du cadre d'une vue à l' aide
systemLayoutSizeFitting
d'unUIView
. Rend la bonne taille (ce qui n'était pas le cas auparavant)!Comme dans la réponse originale mentionnée:
N'oubliez pas de désactiver scrollEnabled dans l'inspecteur!
Cette solution fonctionne correctement dans le storyboard, ainsi qu'au moment de l'exécution.
Voilà, maintenant vous avez vraiment terminé!
la source
Pour swift 4, Xcode 9
Utilisez la fonction suivante peut modifier la marge / remplissage du texte dans UITextView
dans ce cas,
la source
En faisant la solution d'encart, j'avais encore un rembourrage sur le côté droit et le bas. L'alignement du texte causait également des problèmes. Le seul moyen sûr que j'ai trouvé était de mettre la vue texte dans une autre vue qui est limitée.
la source
Voici une petite extension simple qui supprimera la marge par défaut d'Apple de chaque affichage de texte dans votre application.
Remarque: Interface Builder affichera toujours l'ancienne marge, mais votre application fonctionnera comme prévu.
la source
Pour moi (iOS 11 et Xcode 9.4.1), ce qui fonctionnait comme par magie, c'était la configuration de la propriété textView.font pour le
UIFont.preferred(forTextStyle:UIFontTextStyle)
style et également la première réponse mentionnée par @Fattie. Mais la réponse @Fattie n'a pas fonctionné tant que je n'ai pas défini la propriété textView.font, sinon UITextView continue de se comporter de manière irrégulière.la source
Si quelqu'un cherche la dernière version de Swift, le code ci-dessous fonctionne correctement avec Xcode 10.2 et Swift 4.2
la source
J'ai trouvé une autre approche, obtenir la vue avec du texte des sous-vues d'UITextView et le configurer dans la méthode layoutSubview d'une sous-classe:
la source
Le défilement textView affecte également la position du texte et donne l'impression qu'il n'est pas centré verticalement. J'ai réussi à centrer le texte dans la vue en désactivant le défilement et en définissant l'encart supérieur à 0:
Pour une raison quelconque, je ne l'ai pas encore compris, le curseur n'est toujours pas centré avant le début de la frappe, mais le texte se centre immédiatement lorsque je commence à taper.
la source
Si vous souhaitez définir une chaîne HTML et éviter le remplissage inférieur, assurez-vous que vous n'utilisez pas de balises de bloc, c'est-à-dire div, p.
Dans mon cas, c'était la raison. Vous pouvez facilement le tester en remplaçant les occurrences des balises de bloc par la balise ie span.
la source
Pour SwiftUI
Si vous créez votre propre TextView en utilisant
UIViewRepresentable
et que vous souhaitez contrôler le remplissage, dans votremakeUIView
fonction, faites simplement:uiTextView.textContainerInset = UIEdgeInsets(top: 10, left: 18, bottom: 0, right: 18)
ou tout ce que vous voulez.
la source
la source