Wie Marge / padding in UITextView zu verlieren?
-
09-09-2019 - |
Frage
Ich habe eine UITextView
in meiner iOS-Anwendung, die eine große Menge an Text angezeigt wird.
ich dann bin Paging diesen Text durch den Offset-Margin-Parameter des UITextView
verwendet wird.
Mein Problem ist, dass die Polsterung des UITextView
meine Berechnungen ist verwirrend, da sie abhängig von der Schriftgröße und Schriftart, anders zu sein scheinen, die ich benutze.
Deshalb stelle ich die Frage: Ist es möglich, die Polsterung rund um den Inhalt des UITextView
entfernen
freuen uns auf Ihre Antworten zu hören!
Lösung
Up-to-date für 2019
Es ist eines der dümmsten Fehler in iOS.
Die Klasse unten ist UITextViewFixed
eine in der Regel eine vernünftige Lösung.
Hier ist die Klasse:
@IBDesignable class UITextViewFixed: UITextView {
override func layoutSubviews() {
super.layoutSubviews()
setup()
}
func setup() {
textContainerInset = UIEdgeInsets.zero
textContainer.lineFragmentPadding = 0
}
}
Vergessen Sie nicht scrollEnabled im Inspektor auszuschalten!
-
Die Lösung funktioniert in Storyboard
-
Die Lösung funktioniert zur Laufzeit
Das ist es, sind Sie fertig.
In der Regel das sollte alles, was Sie in den meisten Fällen müssen sein .
Auch wenn Sie im Fluge die Höhe der Textansicht ändern sich, dies in der Regel tut alles, was Sie brauchen.
(Ein gängiges Beispiel die Höhe im laufenden Betrieb zu ändern, wird es als der Benutzer tippt ändern.)
Hier ist die gebrochene UITextView von Apple ...
Hier ist UITextViewFixed
:
Beachten Sie, dass natürlich müssen Sie
ausschalten scrollEnabled im Inspektor!
Vergessen Sie nicht deaktivieren scrollEnabled! :)
Einige weitere Fragen
(1) In einigen seltenen Fällen - beispielsweise einige Fälle von flexiblen Zellenhöhe Tabellenansichten mit der Höhe dynamisch ändernden - Apfel hat eine bizarre Sache: Sie fügen hinzu, besonders viel Platz am Boden . Nicht wirklich! Dies hätte eine der ärgerlichen Dinge in iOS sein.
Hier ist eine „schnelle Lösung“ hinzuzufügen, die in der Regel mit diesem Wahnsinn hilft.
...
textContainerInset = UIEdgeInsets.zero
textContainer.lineFragmentPadding = 0
// this is not ideal, but you can sometimes use this
// to fix the "extra space at the bottom" insanity
var b = bounds
let h = sizeThatFits(CGSize(
width: bounds.size.width,
height: CGFloat.greatestFiniteMagnitude)
).height
b.size.height = h
bounds = b
...
(2) Manchmal beheben noch ein anderes subtiles Apple-Chaos-up, müssen Sie diese hinzufügen:
override func setContentOffset(_ contentOffset: CGPoint, animated: Bool) {
super.setContentOffset(contentOffset, animated: false)
}
(3) Argumentieren, we sollte sein und fügte hinzu:
contentInset = UIEdgeInsets.zero
kurz nach .lineFragmentPadding = 0
in UITextViewFixed
.
Allerdings ... glauben oder nicht ... es funktioniert einfach nicht in der aktuellen iOS! (Karo in 2019) Es kann notwendig sein, diese Linie in der Zukunft hinzuzufügen.
Die Tatsache, dass UITextView
in iOS gebrochen wird, ist einer der seltsamsten Dinge in allen Mobile Computing. Zehn Jahre Jahrestag dieser Frage und es ist noch nicht festgelegt!
Schließlich ist hier eine etwas ähnliche Spitze für Text : https://stackoverflow.com/a / 43099816/294884
Andere Tipps
Für iOS 7.0, Ich habe festgestellt, dass der contentInset Trick funktioniert nicht mehr. Dies ist der Code, den ich die Marge / padding in iOS 7 loszuwerden verwendet.
Dies bringt den linken Rand des Textes an den linken Rand des Behälters:
textView.textContainer.lineFragmentPadding = 0
Dies bewirkt, dass der obere Teil des Textes mit dem oberen Ende des Behälters auszurichten
textView.textContainerInset = .zero
Die beiden Linien werden benötigt, um vollständig die Marge / padding zu entfernen.
Diese Problemumgehung wurde 2009 geschrieben, wenn IOS 3.0 veröffentlicht wurde. Es gilt nicht mehr.
Ich lief in das exakt gleiche Problem, am Ende musste ich aufzuwickeln mit
nameField.contentInset = UIEdgeInsetsMake(-4,-8,0,0);
Dabei ist ein namefield UITextView
. Die Schrift ich zufällig zu verwenden war 16 Punkt Helvetica. Es ist nur eine individuelle Lösung für die jeweilige Feldgröße ich zeichne. Dies macht die linke mit der linken Seite versetzt bündig, und die oben versetzt, wo ich es für die Box seine Auslosung in möchten.
Darüber hinaus scheint dies nur gelten UITextViews
wo Sie den Standard aligment verwenden, dh.
nameField.textAlignment = NSTextAlignmentLeft;
Richten Sie auf der rechten Seite zum Beispiel und die UIEdgeInsetsMake
scheint überhaupt keine Auswirkungen auf den rechten Rand zu haben.
Am allerwenigsten die .contentInset Eigenschaft ermöglicht es Ihnen, Ihre Felder mit den „richtigen“ Positionen zu platzieren, und die Abweichungen aufzunehmen, ohne Ihre UITextViews
zu kompensieren.
Gebäude einige der guten Antworten schon gegeben, hier ist eine rein Interface Builder-basierte Lösung, die Verwendung von benutzerdefinierten Runtime Attributen und arbeitet in iOS 7.0 + macht aus:
Auf iOS 5 UIEdgeInsetsMake(-8,-8,-8,-8);
scheint sehr gut zu funktionieren.
Ich würde auf jeden Fall keine Antworten vermeiden hartcodierte Werte umfassen, da die tatsächlichen Ränder mit Benutzern font-size-Einstellungen ändern können, etc.
Hier @ user1687195 Antwort, geschrieben, ohne die textContainer.lineFragmentPadding
Modifizierung (weil die docs Zustand dies nicht der bestimmungsgemäßen Gebrauch ist).
Dies funktioniert gut für iOS 7 und höher.
self.textView.textContainerInset = UIEdgeInsetsMake(
0,
-self.textView.textContainer.lineFragmentPadding,
0,
-self.textView.textContainer.lineFragmentPadding);
Dies ist effektiv das gleiche Ergebnis, nur ein bisschen saubere, dass es Missbrauch nicht die lineFragmentPadding Eigenschaft.
oder Storyboard-Interface Builder Lösung, Benutzerdefinierte Laufzeit Attribute verwenden. Aktualisieren. Added iOS7.1 & iOS6.1 Screenshots mit contentInset = {{-10, -5}, {0, 0}}
All diese Antworten adressieren die Titel Frage, aber ich wollte ein paar Lösungen für die Probleme in dem Körper der OP Frage vorgelegt vorzuschlagen.
Größe von Text Content
Eine schnelle Möglichkeit, die Größe des Textes innerhalb des UITextView
zu berechnen, ist den NSLayoutManager
zu verwenden:
UITextView *textView;
CGSize textSize = [textView usedRectForTextContainer:textView.textContainer].size;
Das gibt den Gesamt scrollbaren Inhalte, die als die UITextView
des Rahmens größer sein können. Ich fand das viel genauer als textView.contentSize
sein, da es tatsächlich berechnet, wie viel Platz der Text in Anspruch nimmt. Zum Beispiel eine leere UITextView
gegeben:
textView.frame.size = (width=246, height=50)
textSize = (width=10, height=16.701999999999998)
textView.contentSize = (width=246, height=33)
textView.textContainerInset = (top=8, left=0, bottom=8, right=0)
Zeilenhöhe
UIFont
hat eine Eigenschaft, die Sie schnell die Zeilenhöhe für die gegebene Schriftart erhalten kann. So können Sie schnell die Zeilenhöhe des Textes in Ihrem UITextView
finden mit:
UITextView *textView;
CGFloat lineHeight = textView.font.lineHeight;
Berechnung Visible Textgröße
Die Ermittlung der Textmenge, die für den Umgang mit einem „Paging“ Effekt tatsächlich sichtbar ist wichtig. UITextView
hat eine Eigenschaft textContainerInset
genannt, die tatsächlich eine Spanne zwischen dem tatsächlichen UITextView.frame
ist und der Text selbst. Um die wirkliche Höhe des sichtbaren Rahmens berechnen Sie die folgenden Berechnungen durchführen können:
UITextView *textView;
CGFloat textViewHeight = textView.frame.size.height;
UIEdgeInsets textInsets = textView.textContainerInset;
CGFloat textHeight = textViewHeight - textInsets.top - textInsets.bottom;
Die Bestimmung Paging Größe
Schließlich jetzt, dass Sie die sichtbaren Textgröße und den Inhalt haben, können Sie schnell feststellen, was Ihre Offsets durch Subtraktion der textHeight
vom textSize
sein sollte:
// where n is the page number you want
CGFloat pageOffsetY = textSize - textHeight * (n - 1);
textView.contentOffset = CGPointMake(textView.contentOffset.x, pageOffsetY);
// examples
CGFloat page1Offset = 0;
CGFloat page2Offset = textSize - textHeight
CGFloat page3Offset = textSize - textHeight * 2
all diese Methoden verwenden, ich habe nicht meine Einsätze berühren, und ich war auf den caret oder wo auch immer im Text der Lage zu gehen, was ich will.
Sie können textContainerInset
Eigenschaft UITextView
verwenden:
= textView.textContainerInset UIEdgeInsetsMake (10, 10, 10, 10);
(oben, links, unten, rechts)
Für iOS 10 die folgende Zeile arbeitet für die obere und untere Polsterung zu entfernen.
captionTextView.textContainerInset = UIEdgeInsetsMake(0, 0, 0, 0)
Hier ist eine aktualisierte Version von Fattie ist sehr hilfreiche Antwort.
Es fügt 2 sehr wichtige Linien, die mich auf iOS arbeiten perfekt Layout bekommen geholfen 10 und 11 (und wahrscheinlich auch auf niedrigeren, auch).
d
@IBDesignable class UITextViewFixed: UITextView {
override func layoutSubviews() {
super.layoutSubviews()
setup()
}
func setup() {
translatesAutoresizingMaskIntoConstraints = true
textContainerInset = UIEdgeInsets.zero
textContainer.lineFragmentPadding = 0
translatesAutoresizingMaskIntoConstraints = false
}
}
Die wichtigsten Linien sind die beiden translatesAutoresizingMaskIntoConstraints = <true/false>
Aussagen!
Diese überraschend entfernt alle Ränder in allen meinen Verhältnissen!
Während die textView
nicht Ersthelfer ist, könnte es passieren, dass es einige seltsame unteren Rand ist das nicht gelöst werden, um die sizeThatFits
Methode, die in der akzeptierte Antwort erwähnt wird.
Wenn sie in die Textview Klopfen plötzlich der seltsame unteren Rand verschwunden und alles sah aus wie es sollte, aber nur, sobald der Textview firstResponder
bekam.
Also ich hier auf SO , daß das Aktivieren und deaktivieren von translatesAutoresizingMaskIntoConstraints
nicht helfen, wenn die Rahmen- / Grenzen manuell zwischen den Gesprächen einstellen.
Glücklicherweise ist dieser arbeitet nicht nur mit Rahmeneinstellung, aber mit den zwei Linien von setup()
zwischen den beiden translatesAutoresizingMaskIntoConstraints
Anrufe eingeschlossen!
Das ist zum Beispiel sehr hilfreich , wenn der Rahmen einer Ansicht mit systemLayoutSizeFitting
auf einem UIView
Berechnung . Gibt zurück, um die richtige Größe (die es vorher nicht)!
Wie in der ursprünglichen Antwort erwähnt:
Vergessen Sie nicht scrollEnabled im Inspektor auszuschalten!
Diese Lösung funktioniert richtig in Storyboard sowie zur Laufzeit.
Das ist es, jetzt bist du wirklich fertig!
Aktuelle Swift:
self.textView.textContainerInset = .init(top: -2, left: 0, bottom: 0, right: 0)
self.textView.textContainer.lineFragmentPadding = 0
Für das schnelle 4, Xcode 9
Verwenden Sie die folgende Funktion kann die Marge / padding des Textes in UITextView ändern
öffentliche func UIEdgeInsetsMake (_ top: CGFloat, _ links: CGFloat, _ unten: CGFloat, _ rechts: CGFloat) -> UIEdgeInsets
so ist in diesem Fall
self.textView?.textContainerInset = UIEdgeInsetsMake(0, 0, 0, 0)
die eingesetzte Lösung tun hatte ich noch Polsterung auf der rechten Seite und die Unterseite. Auch Textausrichtung wurde verursacht Probleme. Der einzig sichere Weg, ich fand, war die Text-Ansicht in einer anderen Ansicht zu setzen, den Grenzen abgeschnitten wird.
Hier ist eine einfache kleine Erweiterung, die Apples Standard-Marge von jeder Textansicht in Ihrer Anwendung entfernen.
Hinweis: Interface Builder wird noch die alte Marge zeigen, aber Ihre App wird wie erwartet.
extension UITextView {
open override func awakeFromNib() {
super.awakeFromNib();
removeMargins();
}
/** Removes the Apple textview margins. */
public func removeMargins() {
self.contentInset = UIEdgeInsetsMake(
0, -textContainer.lineFragmentPadding,
0, -textContainer.lineFragmentPadding);
}
}
Für mich (iOS 11 & Xcode 9.4.1), was magisch gearbeitet wurde die Einrichtung textView.font Eigenschaft Stil UIFont.preferred(forTextStyle:UIFontTextStyle)
und auch die erste Antwort, wie durch @Fattie erwähnt. Aber die @Fattie Antwort hat nicht funktioniert, bis ich die textView.font Eigenschaft sonst UITextView gesetzt hält unberechenbar verhält.
Falls sie jemand für die neueste Swift-Version dann unter Code Suche funktioniert gut mit Xcode 10.2 und Swift 4.2
yourTextView.textContainerInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
Ich habe noch einen Ansatz gefunden, mit Text von UITextView der Subviews bekommt Aussicht und es bis in layoutSubview Methode einer Unterklasse festlegen:
- (void)layoutSubviews {
[super layoutSubviews];
const int textViewIndex = 1;
UIView *textView = [self.subviews objectAtIndex:textViewIndex];
textView.frame = CGRectMake(
kStatusViewContentOffset,
0.0f,
self.bounds.size.width - (2.0f * kStatusViewContentOffset),
self.bounds.size.height - kStatusViewContentOffset);
}
Die Textview Scrollen auch Auswirkungen auf die Position des Textes und es wie nicht vertikal zentriert aussehen. Ich schaffte es, den Text in der Ansicht zentriert durch Deaktivieren der Bildlauf und die Einstellung der oberen Versatz auf 0:
textView.scrollEnabled = NO;
textView.textContainerInset = UIEdgeInsetsMake(0, textView.textContainerInset.left, textView.textContainerInset.bottom, textView.textContainerInset.right);
Aus irgendeinem Grund habe ich es noch nicht herausgefunden, wird der Cursor noch nicht zentriert, bevor die Eingabe beginnt, aber die Textstellen sofort, wie ich zu schreiben beginnen.
[firstNameTextField setContentVerticalAlignment:UIControlContentVerticalAlignmentCenter];