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!

War es hilfreich?

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!

  1. Die Lösung funktioniert in Storyboard

  2. 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 ...

Screenshot von IB mit UITextView

Hier ist UITextViewFixed:

Screenshot von IB mit 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:

eingeben Bild Beschreibung hier

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}} image description treten Sie hier eingeben Bild Beschreibung hier

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];
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top