web-dev-qa-db-ger.com

UIButton: Wie zentriert man ein Bild und einen Text mit imageEdgeInsets und titleEdgeInsets?

Wenn ich nur ein Bild in eine Schaltfläche setze und die imageEdgeInsets näher an den oberen Rand setze, bleibt das Bild zentriert und alles funktioniert wie erwartet:

[button setImage:image forState:UIControlStateNormal];
[button setImageEdgeInsets:UIEdgeInsetsMake(-15.0, 0.0, 0.0, 0.0)];

Wenn ich nur einen Text in eine Schaltfläche setze und titleEdgeInsets näher an den unteren Rand setze, bleibt der Text zentriert und alles funktioniert wie erwartet:

[button setTitle:title forState:UIControlStateNormal];
[button setTitleEdgeInsets:UIEdgeInsetsMake(0.0, 0.0, -30, 0.0)];

Wenn ich jedoch die vier Zeilen zusammenstelle, stört der Text das Bild und beide haben die Ausrichtung der Mitte verloren.

Alle meine Bilder haben eine Breite von 30 Pixeln, und wenn ich für setTitleEdgeInsets den linken Parameter von UIEdgeInsetMake eingebe, wird der Text wieder zentriert. Das Problem ist, dass das Bild niemals zentriert wird, da es so aussieht, als sei es von der Größe der button.titleLabel abhängig. Ich habe schon viele Berechnungen mit Tastengröße, Bildgröße und titleLabel-Größe ausprobiert und habe nie beides perfekt zentriert.

Jemand hatte schon das gleiche Problem?

148
reinaldoluckman

Hier ist eine generelle Lösung, um das Bild zentriert über dem Text zu positionieren, ohne magische Zahlen zu verwenden. Beachten Sie, dass der folgende Code veraltet ist und Sie wahrscheinlich eine der aktualisierten Versionen verwenden sollten :

// the space between the image and text
CGFloat spacing = 6.0;

// lower the text and Push it left so it appears centered 
//  below the image
CGSize imageSize = button.imageView.frame.size;
button.titleEdgeInsets = UIEdgeInsetsMake(
  0.0, - imageSize.width, - (imageSize.height + spacing), 0.0);

// raise the image and Push it right so it appears centered
//  above the text
CGSize titleSize = button.titleLabel.frame.size;
button.imageEdgeInsets = UIEdgeInsetsMake(
  - (titleSize.height + spacing), 0.0, 0.0, - titleSize.width);

Die folgende Version enthält Änderungen an Support iOS 7+ , die in den folgenden Kommentaren empfohlen wurden. Ich habe diesen Code nicht selbst getestet, daher bin ich nicht sicher, wie gut er funktioniert oder ob er unter früheren Versionen von iOS kaputt gehen würde.

// the space between the image and text
CGFloat spacing = 6.0;

// lower the text and Push it left so it appears centered 
//  below the image
CGSize imageSize = button.imageView.image.size;
button.titleEdgeInsets = UIEdgeInsetsMake(
  0.0, - imageSize.width, - (imageSize.height + spacing), 0.0);

// raise the image and Push it right so it appears centered
//  above the text
CGSize titleSize = [button.titleLabel.text sizeWithAttributes:@{NSFontAttributeName: button.titleLabel.font}];
button.imageEdgeInsets = UIEdgeInsetsMake(
  - (titleSize.height + spacing), 0.0, 0.0, - titleSize.width);

// increase the content height to avoid clipping
CGFloat edgeOffset = fabsf(titleSize.height - imageSize.height) / 2.0;
button.contentEdgeInsets = UIEdgeInsetsMake(edgeOffset, 0.0, edgeOffset, 0.0);

Swift Version

extension UIButton {
  func alignVertical(spacing: CGFloat = 6.0) {
    guard let imageSize = self.imageView?.image?.size,
      let text = self.titleLabel?.text,
      let font = self.titleLabel?.font
      else { return }
    self.titleEdgeInsets = UIEdgeInsets(top: 0.0, left: -imageSize.width, bottom: -(imageSize.height + spacing), right: 0.0)
    let labelString = NSString(string: text)
    let titleSize = labelString.size(attributes: [NSFontAttributeName: font])
    self.imageEdgeInsets = UIEdgeInsets(top: -(titleSize.height + spacing), left: 0.0, bottom: 0.0, right: -titleSize.width)
    let edgeOffset = abs(titleSize.height - imageSize.height) / 2.0;
    self.contentEdgeInsets = UIEdgeInsets(top: edgeOffset, left: 0.0, bottom: edgeOffset, right: 0.0)
  }
}
398
Jesse Crossen

Gefunden wie.

Konfigurieren Sie zuerst den Text von titleLabel (aufgrund von Stilen, d. H., Fett, kursiv usw.). Verwenden Sie dann setTitleEdgeInsets unter Berücksichtigung der Breite Ihres Bildes:

[button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[button setTitle:title forState:UIControlStateNormal];
[button.titleLabel setFont:[UIFont boldSystemFontOfSize:10.0]];

// Left inset is the negative of image width.
[button setTitleEdgeInsets:UIEdgeInsetsMake(0.0, -image.size.width, -25.0, 0.0)]; 

Danach verwenden Sie setTitleEdgeInsets unter Berücksichtigung der Breite der Textgrenzen:

[button setImage:image forState:UIControlStateNormal];

// Right inset is the negative of text bounds width.
[button setImageEdgeInsets:UIEdgeInsetsMake(-15.0, 0.0, 0.0, -button.titleLabel.bounds.size.width)];

Nun werden das Bild und der Text zentriert (in diesem Beispiel erscheint das Bild über dem Text).

Prost.

59
reinaldoluckman

Sie können dies mit dieser Swift-Erweiterung tun, die zum Teil auf der Antwort von Jesse Crossen beruhte:

extension UIButton {
  func centerLabelVerticallyWithPadding(spacing:CGFloat) {
    // update positioning of image and title
    let imageSize = self.imageView.frame.size
    self.titleEdgeInsets = UIEdgeInsets(top:0,
                                        left:-imageSize.width,
                                        bottom:-(imageSize.height + spacing),
                                        right:0)
    let titleSize = self.titleLabel.frame.size
    self.imageEdgeInsets = UIEdgeInsets(top:-(titleSize.height + spacing),
                                        left:0,
                                        bottom: 0,
                                        right:-titleSize.width)

    // reset contentInset, so intrinsicContentSize() is still accurate
    let trueContentSize = CGRectUnion(self.titleLabel.frame, self.imageView.frame).size
    let oldContentSize = self.intrinsicContentSize()
    let heightDelta = trueContentSize.height - oldContentSize.height
    let widthDelta = trueContentSize.width - oldContentSize.width
    self.contentEdgeInsets = UIEdgeInsets(top:heightDelta/2.0,
                                          left:widthDelta/2.0,
                                          bottom:heightDelta/2.0,
                                          right:widthDelta/2.0)
  }
}

Dies definiert eine Funktion centerLabelVerticallyWithPadding, die den Titel und die Bildeinfügungen entsprechend setzt.

Außerdem werden die contentEdgeInsets festgelegt, die meines Erachtens notwendig sind, um sicherzustellen, dass intrinsicContentSize weiterhin ordnungsgemäß funktioniert, was Auto Layout erfordern würde.

Ich bin der Ansicht, dass alle Lösungen, die UIButton-Unterklassen enthalten, technisch unzulässig sind, da UIKit-Steuerelemente nicht als Unterklassen gelten sollen. Das heißt, theoretisch könnten sie in zukünftige Versionen einbrechen.

20
algal

Edit: Aktualisiert für Swift 3

Falls Sie nach einer schnellen Lösung der Antwort von Jesse Crossen suchen, können Sie diese einer Unterklasse von UIButton hinzufügen:

override func layoutSubviews() {

    let spacing: CGFloat = 6.0

    // lower the text and Push it left so it appears centered
    //  below the image
    var titleEdgeInsets = UIEdgeInsets.zero
    if let image = self.imageView?.image {
        titleEdgeInsets.left = -image.size.width
        titleEdgeInsets.bottom = -(image.size.height + spacing)
    }
    self.titleEdgeInsets = titleEdgeInsets

    // raise the image and Push it right so it appears centered
    //  above the text
    var imageEdgeInsets = UIEdgeInsets.zero
    if let text = self.titleLabel?.text, let font = self.titleLabel?.font {
        let attributes = [NSFontAttributeName: font]
        let titleSize = text.size(attributes: attributes)
        imageEdgeInsets.top = -(titleSize.height + spacing)
        imageEdgeInsets.right = -titleSize.width
    }
    self.imageEdgeInsets = imageEdgeInsets

    super.layoutSubviews()
}
13
Thomas Verbeek

Es gibt einige großartige Beispiele hier, aber ich konnte dies nicht in allen Fällen erreichen, wenn es sich auch um mehrere Textzeilen (Textumbruch) handelt. Um es endlich zum Laufen zu bringen, kombinierte ich einige Techniken:

  1. Ich habe oben das Beispiel von Jesse Crossen verwendet. Ich habe jedoch eine Texthöhe Korrigiert und die Möglichkeit hinzugefügt, einen horizontalen Textrand anzugeben. Der Rand ist nützlich, wenn Text umbrochen werden soll, damit er nicht auf den Rand der Schaltfläche trifft.

    // the space between the image and text
    CGFloat spacing = 10.0;
    float   textMargin = 6;
    
    // get the size of the elements here for readability
    CGSize  imageSize   = picImage.size;
    CGSize  titleSize   = button.titleLabel.frame.size;
    CGFloat totalHeight = (imageSize.height + titleSize.height + spacing);      // get the height they will take up as a unit
    
    // lower the text and Push it left to center it
    button.titleEdgeInsets = UIEdgeInsetsMake( 0.0, -imageSize.width +textMargin, - (totalHeight - titleSize.height), +textMargin );   // top, left, bottom, right
    
    // the text width might have changed (in case it was shortened before due to 
    // lack of space and isn't anymore now), so we get the frame size again
    titleSize = button.titleLabel.bounds.size;
    
    button.imageEdgeInsets = UIEdgeInsetsMake(-(titleSize.height + spacing), 0.0, 0.0, -titleSize.width );     // top, left, bottom, right        
    
  2. Stellen Sie sicher, dass Sie das Textetikett für den Umbruch einrichten

    button.titleLabel.numberOfLines = 2; 
    button.titleLabel.lineBreakMode = UILineBreakModeWordWrap;
    button.titleLabel.textAlignment = UITextAlignmentCenter;
    
  3. Das wird meistens jetzt funktionieren. Ich hatte jedoch einige Schaltflächen, die das Bild nicht richtig rendern würden. Das Bild wurde entweder weit nach rechts oder links verschoben (es war nicht zentriert). Also habe ich eine UIButton-Layout-Überschreibungstechnik verwendet, um die Zentrierung der ImageView zu erzwingen.

    @interface CategoryButton : UIButton
    @end
    
    @implementation CategoryButton
    
    - (void)layoutSubviews
    {
        // Allow default layout, then center imageView
        [super layoutSubviews];
    
        UIImageView *imageView = [self imageView];
        CGRect imageFrame = imageView.frame;
        imageFrame.Origin.x = (int)((self.frame.size.width - imageFrame.size.width)/ 2);
        imageView.frame = imageFrame;
    }
    @end
    
9
Tod Cunningham

Ich habe eine Methode für @ TodCunninghams Antwort erstellt

 -(void) AlignTextAndImageOfButton:(UIButton *)button
 {
   CGFloat spacing = 2; // the amount of spacing to appear between image and title
   button.imageView.backgroundColor=[UIColor clearColor];
   button.titleLabel.lineBreakMode = UILineBreakModeWordWrap;
   button.titleLabel.textAlignment = UITextAlignmentCenter;
   // get the size of the elements here for readability
   CGSize imageSize = button.imageView.frame.size;
   CGSize titleSize = button.titleLabel.frame.size;

  // lower the text and Push it left to center it
  button.titleEdgeInsets = UIEdgeInsetsMake(0.0, - imageSize.width, - (imageSize.height   + spacing), 0.0);

  // the text width might have changed (in case it was shortened before due to 
  // lack of space and isn't anymore now), so we get the frame size again
   titleSize = button.titleLabel.frame.size;

  // raise the image and Push it right to center it
  button.imageEdgeInsets = UIEdgeInsetsMake(- (titleSize.height + spacing), 0.0, 0.0, -     titleSize.width);
 }
9
Bekir Onat Akin

Kämpfe nicht gegen das System. Wenn Ihre Layouts zu komplex werden, um sie mit Interface Builder + und einigen einfachen Konfigurationscode verwalten zu können, müssen Sie die Layouts mit layoutSubviews einfacher manuell ausführen. Alles andere wird zu Hacks führen.

Erstellen Sie eine UIButton-Unterklasse und überschreiben Sie deren layoutSubviews-Methode, um Ihren Text und Ihr Bild programmatisch auszurichten. Oder verwenden Sie etwas wie https://github.com/nickpaulson/BlockKit/blob/master/Source/UIView-BKAdditions.h , damit Sie layoutSubviews mithilfe eines Blocks implementieren können.

6
Steven Kramer

Unterklasse UIButton

- (void)layoutSubviews {
    [super layoutSubviews];
    CGFloat spacing = 6.0;
    CGSize imageSize = self.imageView.image.size;
    CGSize titleSize = [self.titleLabel sizeThatFits:CGSizeMake(self.frame.size.width, self.frame.size.height - (imageSize.height + spacing))];
    self.imageView.frame = CGRectMake((self.frame.size.width - imageSize.width)/2, (self.frame.size.height - (imageSize.height+spacing+titleSize.height))/2, imageSize.width, imageSize.height);
    self.titleLabel.frame = CGRectMake((self.frame.size.width - titleSize.width)/2, CGRectGetMaxY(self.imageView.frame)+spacing, titleSize.width, titleSize.height);
}
6
Alex

Nichts falsch mit den anderen Antworten, aber ich wollte nur anmerken, dass das gleiche Verhalten innerhalb von Xcode mit null Codezeilen visuell ausgeführt werden kann. Diese Lösung ist nützlich, wenn Sie keinen berechneten Wert benötigen oder mit einem Storyboard/Xib erstellen (ansonsten gelten andere Lösungen). 

Hinweis - Ich verstehe, dass die Frage des OPs eine ist, die Code erfordert. Ich gebe diese Antwort nur aus Gründen der Vollständigkeit und als logische Alternative für diejenigen, die Storyboards/Xibs verwenden.

Um den Abstand zwischen Bild-, Titel- und Inhaltsansichten einer Schaltfläche mithilfe der Edge-Einfügungen zu ändern, können Sie die Schaltfläche/das Steuerelement auswählen und den Attributinspektor öffnen. Scrollen Sie nach unten in die Mitte des Inspektors und suchen Sie nach dem Abschnitt für Edge-Einsätze.

Edge-insets

Sie können auch auf die speziellen Edge-Einfügungen für die Titel-, Bild- oder Inhaltsansicht zugreifen und diese ändern.

menu-options

5
Tommie C.

Mit diesem Code bekommen Sie so etwas  title and image alignment

extension UIButton {
    func alignTextUnderImage() {
        guard let imageView = imageView else {
                return
        }
        self.contentVerticalAlignment = .Top
        self.contentHorizontalAlignment = .Center
        let imageLeftOffset = (CGRectGetWidth(self.bounds) - CGRectGetWidth(imageView.bounds)) / 2//put image in center
        let titleTopOffset = CGRectGetHeight(imageView.bounds) + 5
        self.imageEdgeInsets = UIEdgeInsetsMake(0, imageLeftOffset, 0, 0)
        self.titleEdgeInsets = UIEdgeInsetsMake(titleTopOffset, -CGRectGetWidth(imageView.bounds), 0, 0)
    }
}
4
Bohdan Savych

UIButton-Erweiterung mit Swift 3+ -Syntax:

extension UIButton {
    func alignImageAndTitleVertically(padding: CGFloat = 6.0) {
        let imageSize: CGSize = imageView!.image!.size
        titleEdgeInsets = UIEdgeInsetsMake(0.0, -imageSize.width, -(imageSize.height + padding), 0.0)
        let labelString = NSString(string: titleLabel!.text!)
        let titleSize = labelString.size(attributes: [NSFontAttributeName: titleLabel!.font])
        self.imageEdgeInsets = UIEdgeInsetsMake(-(titleSize.height + padding), 0.0, 0.0, -titleSize.width)
        let edgeOffset = abs(titleSize.height - imageSize.height) / 2.0;
        self.contentEdgeInsets = UIEdgeInsetsMake(edgeOffset, 0.0, edgeOffset, 0.0)
    }
}

Ursprüngliche Antwort: https://stackoverflow.com/a/7199529/3659227

4
Maverick

Die Verwendung von button.titleLabel.frame.size.width funktioniert nur, wenn das Etikett kurz genug ist, um nicht abgeschnitten zu werden. Wenn der Etikettentext abgeschnitten wird, funktioniert die Positionierung jedoch nicht. Nehmen 

CGSize titleSize = [[[button titleLabel] text] sizeWithFont:[[button titleLabel] font]];

funktioniert für mich auch, wenn der Etikettentext abgeschnitten ist.

3
dezember

Aktualisierte Antwort von Jesse Crossen für Swift 4:

extension UIButton {
    func alignVertical(spacing: CGFloat = 6.0) {
        guard let imageSize = self.imageView?.image?.size,
            let text = self.titleLabel?.text,
            let font = self.titleLabel?.font
            else { return }
        self.titleEdgeInsets = UIEdgeInsets(top: 0.0, left: -imageSize.width, bottom: -(imageSize.height + spacing), right: 0.0)
        let labelString = NSString(string: text)
        let titleSize = labelString.size(withAttributes: [kCTFontAttributeName as NSAttributedStringKey: font])
        self.imageEdgeInsets = UIEdgeInsets(top: -(titleSize.height + spacing), left: 0.0, bottom: 0.0, right: -titleSize.width)
        let edgeOffset = abs(titleSize.height - imageSize.height) / 2.0;
        self.contentEdgeInsets = UIEdgeInsets(top: edgeOffset, left: 0.0, bottom: edgeOffset, right: 0.0)
    }
}

Verwenden Sie diesen Weg:

override func viewDidLayoutSubviews() {
    button.alignVertical()
}
3
Doca

Nur eine kleine Änderung an der Antwort von Jesse Crossen, die es für mich perfekt funktionierte:

anstatt:

CGSize titleSize = button.titleLabel.frame.size;

Ich habe das benutzt:

CGSize titleSize = [button.titleLabel.text sizeWithAttributes: @{NSFontAttributeName:button.titleLabel.font}];
3
Cesar

Ich habe mir vorhandene Antworten angeschaut, aber auch das Festlegen des Button-Frames ist ein wichtiger erster Schritt.

Hier ist eine Funktion, die ich verwende:

const CGFloat kImageTopOffset   = -15;
const CGFloat kTextBottomOffset = -25;

+ (void) centerButtonImageTopAndTextBottom: (UIButton*)         button 
                                     frame: (CGRect)            buttonFrame
                                      text: (NSString*)         textString
                                 textColor: (UIColor*)          textColor
                                      font: (UIFont*)           textFont
                                     image: (UIImage*)          image
                                  forState: (UIControlState)    buttonState
{
    button.frame = buttonFrame;

    [button setTitleColor: (UIColor*)       textColor
                 forState: (UIControlState) buttonState];

    [button setTitle: (NSString*) textString
            forState: (UIControlState) buttonState ];


    [button.titleLabel setFont: (UIFont*) textFont ];

    [button setTitleEdgeInsets: UIEdgeInsetsMake( 0.0, -image.size.width, kTextBottomOffset,  0.0)]; 

    [button setImage: (UIImage*)       image 
            forState: (UIControlState) buttonState ];

    [button setImageEdgeInsets: UIEdgeInsetsMake( kImageTopOffset, 0.0, 0.0,- button.titleLabel.bounds.size.width)];
}
2
Bamaco

Oder Sie können diese Kategorie einfach verwenden:

@interface UIButton (VerticalLayout)  

- (void)centerVerticallyWithPadding:(float)padding;  
- (void)centerVertically;  

@end  


@implementation UIButton (VerticalLayout)  

- (void)centerVerticallyWithPadding:(float)padding 
{      
    CGSize imageSize = self.imageView.frame.size;  
    CGSize titleSize = self.titleLabel.frame.size;  

    CGFloat totalHeight = (imageSize.height + titleSize.height + padding);  

    self.imageEdgeInsets = UIEdgeInsetsMake(- (totalHeight - imageSize.height),
                                            0.0f,
                                            0.0f,
                                            - titleSize.width);

    self.titleEdgeInsets = UIEdgeInsetsMake(0.0f,
                                            - imageSize.width,
                                            - (totalHeight - titleSize.height),
                                            0.0f);

}


- (void)centerVertically
{  
    const CGFloat kDefaultPadding = 6.0f;

    [self centerVerticallyWithPadding:kDefaultPadding];  
}  


@end
2
RaffAl

Mein Use Case machte Einsätze unüberschaubar:

  1. hintergrundbild auf der Schaltfläche bleibt konsistent
  2. dynamischer Text und Bild ändert sich, wenn die Zeichenfolgenlänge und Bildgröße variiert

Das habe ich am Ende getan und ich bin ziemlich zufrieden damit:

  • Erstellen Sie die Schaltfläche auf dem Storyboard mit einem Hintergrundbild (runder Kreis mit Unschärfe und Farbe).

  • Deklarieren Sie eine UIImageView in meiner Klasse:

    @implementation BlahViewController {
        UIImageView *_imageView;
    }
    
  • Image View-Instanz unter init erstellen:

    -(id)initWithCoder:(NSCoder *)aDecoder {
        self = [super initWithCoder:aDecoder];
        if (self) {
            _imageView = [[UIImageView alloc] initWithCoder:aDecoder];
         }
         return self;
     }
    
  • Fügen Sie in viewDidLoad der Schaltfläche für unsere Bildansicht eine neue Ebene hinzu und legen Sie die Textausrichtung fest:

    [self.btn addSubview:_imageView];
    [self.btn.titleLabel setTextAlignment:NSTextAlignmentCenter];
    
  • Fügen Sie in der Button-Klick-Methode mein ausgewähltes Überlagerungsbild der Bildansicht hinzu, passen Sie die Größe an das Bild an und zentrieren Sie es in der Schaltfläche, verschieben Sie es jedoch nach oben 15, damit ich den Text darunter verschieben kann:

    [_imageView setImage:[UIImage imageNamed:@"blahImageBlah]];
    [_imageView sizeToFit];
    _imageView.center = CGPointMake(ceilf(self.btn.bounds.size.width / 2.0f),
             ceilf((self.btn.bounds.size.height / 2.0f) - 15));
    [self.btn setTitle:@"Some new text" forState:UIControlStateNormal];
    

Hinweis: ceilf () ist wichtig, um sicherzustellen, dass die Bildqualität an einer Pixelgrenze liegt.

1
Oliver Dungey

Um meine 2 Cents reinzuwerfen, hat das für mich funktioniert:

extension UIButton {
  public func centerImageAndTextVertically(spacing: CGFloat) {
    layoutIfNeeded()
    let contentFrame = contentRect(forBounds: bounds)
    let imageFrame = imageRect(forContentRect: contentFrame)
    let imageLeftInset = bounds.size.width * 0.5 - imageFrame.size.width * 0.5
    let imageTopInset = -(imageFrame.size.height + spacing * 0.5)
    let titleFrame = titleRect(forContentRect: contentFrame)
    let titleLeftInset = ((bounds.size.width - titleFrame.size.width) * 0.5) - imageFrame.size.width
    let titleTopInmset = titleFrame.size.height + spacing * 0.5
    imageEdgeInsets = UIEdgeInsets(top: imageTopInset, left: imageLeftInset, bottom: 0, right: 0)
    titleEdgeInsets = UIEdgeInsets(top: titleTopInmset, left: titleLeftInset, bottom: 0, right: 0)
  }
}
0
chrysAllwood

Funktioniert gut für die Tastengröße 80x80 Pixel.

[self.leftButton setImageEdgeInsets:UIEdgeInsetsMake(0, 10.0, 20.0, 10.0)];    
[self.leftButton setTitleEdgeInsets:UIEdgeInsetsMake(60, -75.0, 0.0, 0.0)];
0
BADRI

Dies funktioniert gut für mich, für mehrere Schaltflächen mit unterschiedlicher Bildbreite und unterschiedlicher Titellänge: 

Unterklasse UIButton

override func layoutSubviews() {
    super.layoutSubviews()

    if let image = imageView?.image {

        let margin = 30 - image.size.width / 2
        let titleRect = titleRectForContentRect(bounds)
        let titleOffset = (bounds.width - titleRect.width - image.size.width - margin) / 2


        contentHorizontalAlignment = UIControlContentHorizontalAlignment.Left
            imageEdgeInsets = UIEdgeInsetsMake(0, margin, 0, 0)
            titleEdgeInsets = UIEdgeInsetsMake(0, (bounds.width - titleRect.width -  image.size.width - margin) / 2, 0, 0)
    }

}
0
Rémy Virin

Ich hatte Schwierigkeiten, dies zu erreichen, da ich im Konstruktor meiner Ansicht keine Bildgröße und Textbreite finden konnte. Zwei kleinere Änderungen an Jesse's Antwort arbeitete für mich:

CGFloat spacing = 3;
self.titleEdgeInsets = UIEdgeInsetsMake(0.0, - image.size.width, - (image.size.height + spacing), 0.0);
CGSize titleSize = [name sizeWithAttributes:@{NSFontAttributeName:self.titleLabel.font}];
self.imageEdgeInsets = UIEdgeInsetsMake(- (titleSize.height + spacing), 0.0, 0.0, - titleSize.width);

Die Änderung sind:

  • Verwenden von [NSString sizeWithAttributes] zum Abrufen der Textbreite;
  • Rufen Sie die Bildgröße direkt auf der UIImage anstelle von UIImageView ab.
0
saulobrito

Angenommen, Sie möchten, dass sowohl Text als auch Bild horizontal zentriert werden sollen, bedeutet image über dem Text: Zentrieren Sie den Text aus dem Interface Builder und fügen Sie einen oberen Teil hinzu (um Platz für das Bild zu schaffen). (lassen Sie den linken Einschub auf 0). Verwenden Sie den Interface Builder, um das Bild auszuwählen. Die tatsächliche Position wird aus dem Code festgelegt. Machen Sie sich also keine Sorgen, dass die Dinge in IB nicht in Ordnung aussehen. Im Gegensatz zu den anderen Antworten oben, funktioniert dies tatsächlich bei allen derzeit unterstützten iOS-Versionen (5,6 und 7).

Im Code verwerfen Sie einfach die ImageView der Schaltfläche (indem Sie das Bild der Schaltfläche auf null setzen), nachdem Sie das Bild erfasst haben (dies zentriert automatisch den Text, der ggf. umbrochen wird). Dann können Sie Ihr eigenes ImageView mit derselben Bildgröße und demselben Bild erstellen und es in der Mitte positionieren.

Auf diese Weise können Sie das Image immer noch aus dem Interface Builder auswählen (obwohl es nicht wie in Simulator in IB ausgerichtet wird. Andere Lösungen sind jedoch nicht mit allen unterstützten iOS-Versionen kompatibel.)

0
Radu Simionescu

ist die Verwendung von Edge-Insets obligatorisch? Wenn nicht, können Sie versuchen, die Ansicht in Bezug auf die mittlere übergeordnete Ansicht zu positionieren

extension UIButton 
{
    func centerImageAndTextVerticaAlignment(spacing: CGFloat) 
    {
        var titlePoint : CGPoint = convertPoint(center, fromView:superview)
        var imageViewPoint : CGPoint = convertPoint(center, fromView:superview)
        titlePoint.y += ((titleLabel?.size.height)! + spacing)/2
        imageViewPoint.y -= ((imageView?.size.height)! + spacing)/2
        titleLabel?.center = titlePoint
        imageView?.center = imageViewPoint

    }
}
0
Rodrigo Birriel

Ich habe einige Anpassungen vorgenommen, um das Bild in der Mitte horizontal auszurichten:

// the space between the image and text
        let spacing = CGFloat(36.0);

        // lower the text and Push it left so it appears centered
        //  below the image
        let imageSize = tutorialButton.imageView!.frame.size;
        tutorialButton.titleEdgeInsets = UIEdgeInsetsMake(
            0, -CGFloat(imageSize.width), -CGFloat(imageSize.height + spacing), 0.0);

        // raise the image and Push it right so it appears centered
        //  above the text
        let titleSize = tutorialButton.titleLabel!.frame.size;
        tutorialButton.imageEdgeInsets = UIEdgeInsetsMake(
            -CGFloat(titleSize.height + spacing), CGFloat((tutorialButton.frame.width - imageSize.width) / 2), 0.0, -CGFloat(titleSize.width));

Fügen Sie diesen Code in der Erweiterung Swift 4.2 hinzu

 func moveImageLeftTextCenter(imagePadding: CGFloat = 30.0){
    guard let imageViewWidth = self.imageView?.frame.width else{return}
    guard let titleLabelWidth = self.titleLabel?.intrinsicContentSize.width else{return}
    self.contentHorizontalAlignment = .left
    imageEdgeInsets = UIEdgeInsets(top: 0.0, left: imagePadding - imageViewWidth / 2, bottom: 0.0, right: 0.0)
    titleEdgeInsets = UIEdgeInsets(top: 0.0, left: (bounds.width - titleLabelWidth) / 2 - imageViewWidth, bottom: 0.0, right: 0.0)
}
func moveImageRIghtTextCenter(imagePadding: CGFloat = 30.0){
    guard let imageViewWidth = self.imageView?.frame.width else{return}
    guard let titleLabelWidth = self.titleLabel?.intrinsicContentSize.width else{return}
    self.contentHorizontalAlignment = .right
    imageEdgeInsets = UIEdgeInsets(top: 0.0, left:0.0 , bottom: 0.0, right: imagePadding - imageViewWidth / 2)
    titleEdgeInsets = UIEdgeInsets(top: 0.0, left:0.0 , bottom: 0.0, right:(bounds.width - titleLabelWidth) / 2 - imageViewWidth)
}
0

Sie müssen das Bild um die Breite des Texts nach rechts verschieben. Dann verschieben Sie den Text um die Breite des Bildes nach links.

UIEdgeInsets imageEdgeInsets = self.remoteCommandsButtonLights.imageEdgeInsets;
imageEdgeInsets.left = [button.titleLabel.text sizeWithAttributes:@{NSFontAttributeName:[button.titleLabel font]}].width;
imageEdgeInsets.bottom = 14.0;
button.imageEdgeInsets = imageEdgeInsets;

UIEdgeInsets titleEdgeInsets = self.remoteCommandsButtonLights.titleEdgeInsets;
titleEdgeInsets.left = -button.currentImage.size.width;
titleEdgeInsets.top = 20.0;
button.titleEdgeInsets = titleEdgeInsets;

Passen Sie dann die oberen und unteren Einschübe an, um die Y-Achse anzupassen. Dies kann wahrscheinlich auch programmgesteuert erfolgen, sollte aber für Ihre Bildgröße konstant sein. Die X-Achsen-Einfügungen müssen sich jedoch je nach Größe der Beschriftung der einzelnen Schaltflächen ändern.

0
pkamb