it-swarm.com.de

Autolayout - Die intrinsische Größe von UIButton enthält keine Titelinsets

Wenn ich ein UIButton-Gerät mit Autolayout eingerichtet habe, passt sich seine Größe gut an den Inhalt an.

Wenn ich ein Bild als button.image eingestellt habe, scheint dies wieder die maßgebliche Größe zu berücksichtigen.

Wenn ich jedoch die Variable titleEdgeInsets der Schaltfläche ändere, berücksichtigt das Layout dies nicht und schneidet stattdessen den Schaltflächentitel ab.

Wie kann ich sicherstellen, dass die innere Breite der Schaltfläche für die Einfügung gilt?

enter image description here

Bearbeiten:

Ich verwende folgendes:

[self.backButton setTitleEdgeInsets:UIEdgeInsetsMake(0, 5, 0, 0)];

Das Ziel besteht darin, eine gewisse Trennung zwischen dem Bild und dem Text hinzuzufügen.

156
Ben Packard

Sie können dieses Problem lösen, ohne Methoden überschreiben zu müssen oder eine beliebige Breitenbeschränkung festzulegen. Sie können dies im Interface Builder wie folgt tun.

  • Die intrinsische Tastenbreite ergibt sich aus der Titelbreite plus der Symbolbreite plus den linken und rechten content Edge-Einfügungen.

  • Wenn eine Schaltfläche sowohl ein Bild als auch einen Text enthält, werden sie als Gruppe zentriert, ohne Zwischenraum.

  • Wenn Sie einen linken Inhaltseinsatz hinzufügen, wird dieser relativ zum Text berechnet, nicht das Text + -Symbol.

  • Wenn Sie einen negativen linken Bildausschnitt festlegen, wird das Bild nach links herausgezogen, aber die Gesamtbreite der Schaltflächen bleibt davon unberührt.

  • Wenn Sie einen negativen linken Bildausschnitt festlegen, verwendet das tatsächliche Layout die Hälfte dieses Werts. Um einen linken Einfügepunkt von -20 zu erhalten, müssen Sie im Interface Builder einen linken Einfügewert von -40 Punkten verwenden.

Sie haben also einen ausreichend großen linken Einfügeinhalt, um Platz für die gewünschte linke Einfügung und für die innere Auffüllung zwischen dem Symbol und dem Text zu schaffen, und verschieben Sie dann das linke Symbol, indem Sie die gewünschte Auffüllung zwischen den Symbolen verdoppeln und der Text. Das Ergebnis ist eine Schaltfläche mit gleichen linken und rechten Inhaltseinsätzen sowie ein Text- und Symbolpaar, die als Gruppe zentriert sind und zwischen denen ein bestimmter Füllungsabstand besteht.

Einige Beispielwerte:

// Produces a button with the layout:
// |-20-icon-10-text-20-|
// AutoLayout intrinsic width works as you'd desire.
button.contentEdgeInsets = UIEdgeInsetsMake(10, 30, 10, 20)
button.imageEdgeInsets = UIEdgeInsetsMake(0, -20, 0, 0)
151
jaredsinclair

Sie können dies mit dem Interface Builder (ohne Code schreiben) zu erreichen, indem Sie eine Kombination aus negativen und positiven Titel- und Inhaltseinsätzen verwenden. 

enter image description here

Update : Xcode 7 hat einen Fehler, bei dem Sie keine negativen Werte in das Feld Right Inset eingeben können. Sie können jedoch den nebenstehenden Stepper verwenden, um den Wert zu verringern. (Danke, Stuart)

Dadurch wird ein Abstand von 8pt zwischen dem Bild und dem Titel hinzugefügt, und die intrinsische Breite der Schaltfläche wird um denselben Betrag erhöht. So was:

enter image description here

177
n.Drake

Warum überschreiben Sie nicht die intrinsicContentSize-Methode in UIView? Zum Beispiel:

- (CGSize) intrinsicContentSize
{
    CGSize s = [super intrinsicContentSize];

    return CGSizeMake(s.width + self.titleEdgeInsets.left + self.titleEdgeInsets.right,
                      s.height + self.titleEdgeInsets.top + self.titleEdgeInsets.bottom);
}

Dies sollte dem Autolayout-System mitteilen, dass die Schaltfläche vergrößert werden muss, um die Einfügungen zu berücksichtigen und den vollständigen Text anzuzeigen. Ich bin nicht an meinem eigenen Computer und habe das nicht getestet.

91
Maarten

Sie haben nicht angegeben, wie Sie die Insets festlegen. Ich nehme an, dass Sie titleEdgeInsets verwenden, da ich den gleichen Effekt sehe, den Sie erzielen. Wenn ich stattdessen contentEdgeInsets verwende, funktioniert es einwandfrei.

- (IBAction)ChangeTitle:(UIButton *)sender {
    self.button.contentEdgeInsets = UIEdgeInsetsMake(0,20,0,20);
    [self.button setTitle:@"Long Long Title" forState:UIControlStateNormal];
}
83
rdelmar

Dieser Thread ist ein bisschen alt, aber ich bin einfach selbst darauf gestoßen und konnte ihn mit einem negativen Inset lösen. Ersetzen Sie beispielsweise Ihre gewünschten Auffüllwerte hier:

UIButton* myButton = [[UIButton alloc] init];
// setup some autolayout constraints here
myButton.titleEdgeInsets = UIEdgeInsetsMake(-desiredBottomPadding,
                                            -desiredRightPadding,
                                            -desiredTopPadding,
                                            -desiredLeftPadding);

In Kombination mit den richtigen Einschränkungen für das automatische Auslagern erhalten Sie eine Schaltfläche zur automatischen Größenänderung, die ein Bild und einen Text enthält! Unten mit desiredLeftPadding auf 10 gesetzt.

Button with image and short text

Button with image and long text

Sie können sehen, dass der tatsächliche Rahmen der Schaltfläche nicht die Beschriftung umfasst (da die Beschriftung um 10 Punkte nach rechts außerhalb der Grenzen verschoben wird), aber wir haben 10 Punkte zwischen Text und Bild aufgefüllt.

18
Brian Gerstle

Und für Swift arbeitete das:

extension UIButton {
    override open var intrinsicContentSize: CGSize {
        let intrinsicContentSize = super.intrinsicContentSize

        let adjustedWidth = intrinsicContentSize.width + titleEdgeInsets.left + titleEdgeInsets.right
        let adjustedHeight = intrinsicContentSize.height + titleEdgeInsets.top + titleEdgeInsets.bottom

        return CGSize(width: adjustedWidth, height: adjustedHeight)
    }
}

Liebe U Swift

18
pegpeg

Für Swift 3 basierend auf der Antwort von pegpeg :

extension UIButton {

    override open var intrinsicContentSize: CGSize {

        let intrinsicContentSize = super.intrinsicContentSize

        let adjustedWidth = intrinsicContentSize.width + titleEdgeInsets.left + titleEdgeInsets.right
        let adjustedHeight = intrinsicContentSize.height + titleEdgeInsets.top + titleEdgeInsets.bottom

        return CGSize(width: adjustedWidth, height: adjustedHeight)

    }

}
7
TheoK

Alles oben funktionierte nicht für iOS 9+. Was ich getan habe, ist:

  • Fügen Sie eine Breitenbeschränkung hinzu (für eine Mindestbreite, wenn die Schaltfläche keinen Text enthält. Die Schaltfläche wird automatisch skaliert, wenn Text bereitgestellt wird).
  • legen Sie die Relation auf Größer als oder Gleich fest

 enter image description here

Um einen Rahmen um die Schaltfläche hinzuzufügen, verwenden Sie einfach die Methode:

button.contentEdgeInsets = UIEdgeInsetsMake(0,20,0,20);
6
Oritm

Ich wollte zwischen meinem UIButton-Symbol und dem Label ein Leerzeichen von 5 pt einfügen. So habe ich es erreicht:

UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeCustom];
// more button config etc
infoButton.contentEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 5);
infoButton.titleEdgeInsets = UIEdgeInsetsMake(0, 5, 0, -5);

Die Art und Weise, in der contentEdgeInsets, titleEdgeInsets und imageEdgeInsets miteinander in Beziehung stehen, erfordert von jedem Einschub ein kleines Nachgeben und Nehmen. Wenn Sie also einige Einfügungen zur linken Seite des Titels hinzufügen, müssen Sie rechts eine negative Einfügung hinzufügen und etwas mehr Platz (über eine positive Einfügung) auf dem rechten Inhalt bereitstellen.

Durch Hinzufügen eines rechten Inhalts-Insets, der der Verschiebung der Titel-Insets entspricht, geht mein Text nicht über die Schaltfläche hinaus.

3
orj

Die Option ist auch im Interface Builder verfügbar. Siehe den Inset. Ich habe links und rechts auf 3 gesetzt. Funktioniert wie ein Zauber. 

Interface builder screenshot

3
zeiteisen

Die Lösung, die ich verwende, ist das Hinzufügen einer Breitenbeschränkung für die Schaltfläche. Aktualisieren Sie dann die Breitenbeschränkung an einem beliebigen Ort in der Initialisierung, nachdem Ihr Text festgelegt wurde:

self.buttonWidthConstraint.constant = self.shareButton.intrinsicContentSize.width + 8;

Wo 8 ist, was auch immer Ihr Inset ist.

1
Bob Spryn

durch Aufrufen von sizeToFit () wird sichergestellt, dass contentEdgeInset wirksam wird

 extension UIButton {

              open override func draw(_ rect: CGRect) { 
                    self.contentEdgeInsets = UIEdgeInsets(top: 10,left: 40,bottom: 10,right: 40)
                    self.sizeToFit()
              }
           }
0
Ali