web-dev-qa-db-fra.com

UIButton: comment centrer une image et un texte en utilisant imageEdgeInsets et titleEdgeInsets?

Si je mets uniquement une image dans un bouton et que je positionne l'imageEdgeInsets plus près du haut, l'image reste centrée et tout fonctionne comme prévu:

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

Si je ne mets qu'un texte dans un bouton et que je place titleEdgeInsets plus près du bas, le texte reste centré et tout fonctionne comme prévu:

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

Mais, si je combine les 4 lignes, le texte interfère avec l'image et les deux perdent l'alignement du centre.

Toutes mes images ont une largeur de 30 pixels et si je mets 30 dans le paramètre gauche de UIEdgeInsetMake pour setTitleEdgeInsets, le texte est à nouveau centré. Le problème est que l'image n'est jamais centrée car il apparaît qu'elle dépend de la taille de button.titleLabel. J'ai déjà essayé de nombreux calculs avec la taille du bouton, la taille de l'image, la taille de titleLabel et ne jamais obtenir les deux parfaitement centrés.

Quelqu'un a déjà eu le même problème?

148
reinaldoluckman

Voici une solution générale pour positionner l'image centrée au-dessus du texte sans utiliser de chiffres magiques. Notez que le code suivant est obsolète et que vous devriez probablement utiliser l'une des versions mises à jour ci-dessous :

// 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);

La version suivante contient des modifications à prendre en charge iOS 7+ qui ont été recommandées dans les commentaires ci-dessous. Je n'ai pas testé ce code moi-même, donc je ne suis pas sûr de son efficacité ni de la possibilité qu'il ne fonctionne pas correctement s'il était utilisé dans les versions précédentes d'iOS.

// 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

Trouvé comment.

Commencez par configurer le texte de titleLabel (en raison des styles, par exemple gras, italique, etc.) Ensuite, utilisez setTitleEdgeInsets en considérant la largeur de votre image:

[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)]; 

Après cela, utilisez setTitleEdgeInsets en considérant la largeur des limites du texte:

[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)];

Maintenant, l'image et le texte seront centrés (dans cet exemple, l'image apparaît au-dessus du texte).

À votre santé.

59
reinaldoluckman

Vous pouvez le faire avec cette extension Swift, basée en partie sur la réponse de Jesse Crossen:

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)
  }
}

Ceci définit une fonction centerLabelVerticallyWithPadding qui définit correctement les encarts titre et image.

Il définit également les contentEdgeInsets, qui, à mon avis, sont nécessaires pour garantir que intrinsicContentSize fonctionne toujours correctement, ce qui nécessiterait l'utilisation de la mise en forme automatique.

Je crois que toutes les solutions qui classent la sous-classe UIButton sont techniquement illégitimes, car vous n'êtes pas censé sous-classer les contrôles UIKit. En d’autres termes, ils pourraient en théorie se briser dans les versions futures.

20
algal

Edit: mis à jour pour Swift 3

Si vous recherchez une solution rapide de la réponse de Jesse Crossen, vous pouvez l'ajouter à une sous-classe d'UIButton:

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

Il y a d'excellents exemples ici, mais je n'ai pas réussi à faire en sorte que cela fonctionne dans tous les cas lorsqu'il s'agit également de plusieurs lignes de texte (habillage du texte). Pour enfin le faire fonctionner, j'ai combiné plusieurs techniques:

  1. J'ai utilisé l'exemple de Jesse Crossen ci-dessus. Cependant, j'ai corrigé un problème de hauteur de texte Et j'ai ajouté la possibilité de spécifier une marge de texte horizontale. La marge est utile pour permettre au texte d’être mis en forme afin qu’il ne touche pas Le bord du bouton:

    // 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. Assurez-vous de configurer l’étiquette de texte pour envelopper

    button.titleLabel.numberOfLines = 2; 
    button.titleLabel.lineBreakMode = UILineBreakModeWordWrap;
    button.titleLabel.textAlignment = UITextAlignmentCenter;
    
  3. Cela fonctionnera surtout maintenant. Cependant, certains boutons ne rendaient pas leur image correctement. L'image était soit décalée trop à droite ou à gauche (elle n'était pas centrée). J'ai donc utilisé une technique de substitution de mise en page UIButton pour forcer l'imageView à être centré.

    @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

J'ai fait une méthode pour la réponse de @ TodCunningham

 -(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

Ne combattez pas le système. Si vos présentations deviennent trop complexes pour être gérées à l'aide d'Interface Builder +, peut-être un code de configuration simple, effectuez-les manuellement d'une manière plus simple en utilisant layoutSubviews - c'est le but que vous employez! Tout le reste sera assimilé à des bidouilles.

Créez une sous-classe UIButton et substituez sa méthode layoutSubviews pour aligner votre texte et votre image par programme. Ou utilisez quelque chose comme https://github.com/nickpaulson/BlockKit/blob/master/Source/UIView-BKAdditions.h pour pouvoir implémenter layoutSubviews à l'aide d'un bloc.

6
Steven Kramer

Sous-classe 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

Rien à redire des autres réponses, mais je voulais juste noter que le même comportement peut être accompli visuellement dans Xcode en utilisant zéro ligne de code. Cette solution est utile si vous n'avez pas besoin d'une valeur calculée ou si vous construisez avec un storyboard/xib (sinon, d'autres solutions s'appliquent). 

Remarque - Je comprends que la question du PO est une question nécessitant un code. Je ne fais que fournir cette réponse par souci d’exhaustivité et comme alternative logique pour ceux qui utilisent des storyboards/xibs.

Pour modifier l'espacement sur les vues d'image, de titre et de contenu d'un bouton à l'aide d'encarts Edge, vous pouvez sélectionner le bouton/contrôle et ouvrir l'inspecteur d'attributs. Faites défiler l'écran vers le centre de l'inspecteur et trouvez la section relative aux encarts de bord.

Edge-insets

Il est également possible d'accéder et de modifier les encarts Edge spécifiques pour l'affichage du titre, de l'image ou du contenu.

menu-options

5
Tommie C.

Avec ce morceau de code, vous obtiendrez quelque chose comme ceci  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

Extension UIButton avec la syntaxe Swift 3+:

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)
    }
}

Réponse originale: https://stackoverflow.com/a/7199529/3659227

4
Maverick

L'utilisation de button.titleLabel.frame.size.width ne fonctionne que si le libellé est suffisamment court pour ne pas être tronqué. Lorsque le texte de l'étiquette est tronqué, le positionnement ne fonctionne pas. Prise 

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

fonctionne pour moi même lorsque le texte de l'étiquette est tronqué.

3
dezember

Réponse mise à jour de Jesse Crossen pour 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)
    }
}

Utilisez cette manière:

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

Un changement mineur à la réponse de Jesse Crossen qui a parfaitement fonctionné pour moi:

au lieu de:

CGSize titleSize = button.titleLabel.frame.size;

J'ai utilisé ceci:

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

J'ai jeté un coup d'œil aux réponses existantes, mais j'ai également constaté que le réglage du cadre du bouton est une première étape importante.

Voici une fonction que j'utilise qui prend en charge ceci:

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

Ou vous pouvez simplement utiliser cette catégorie:

@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

Mon cas d'utilisation insère ingérable:

  1. l'image de fond sur le bouton reste cohérente
  2. texte dynamique et modifications d'image lorsque la longueur de la chaîne et la taille de l'image varient

C'est ce que j'ai fini par faire et j'en suis plutôt content:

  • Créez le bouton sur le storyboard avec une image d’arrière-plan (cercle rond avec flou et couleur).

  • Déclarer un UIImageView dans ma classe:

    @implementation BlahViewController {
        UIImageView *_imageView;
    }
    
  • Créer une instance de vue d'image sur init:

    -(id)initWithCoder:(NSCoder *)aDecoder {
        self = [super initWithCoder:aDecoder];
        if (self) {
            _imageView = [[UIImageView alloc] initWithCoder:aDecoder];
         }
         return self;
     }
    
  • Dans viewDidLoad, ajoutez un nouveau calque au bouton pour notre vue d'image et définissez l'alignement du texte:

    [self.btn addSubview:_imageView];
    [self.btn.titleLabel setTextAlignment:NSTextAlignmentCenter];
    
  • Dans la méthode du clic sur le bouton, ajoutez l'image de surimpression que vous avez choisie à la vue d'image, redimensionnez-la pour l'adapter à l'image et centrez-la sur le bouton, puis déplacez-la vers le haut de manière à pouvoir placer le décalage de texte en dessous:

    [_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];
    

Remarque: ceilf () est important pour garantir la qualité de l’image.

1
Oliver Dungey

Juste pour jeter mes 2 cents, cela a fonctionné pour moi:

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

Fonctionne bien pour la taille du bouton 80x80 pixels.

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

Cela fonctionne bien pour moi, pour plusieurs boutons, avec une largeur d'image et une longueur de titre différentes: 

Sous-classe 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

J'avais du mal à faire cela car je ne pouvais pas obtenir la taille de l'image et la largeur du texte du constructeur de ma vue. Deux changements mineurs sur la réponse de Jesse a fonctionné pour moi:

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);

Les changements sont:

  • Utiliser [NSString sizeWithAttributes] pour obtenir la largeur du texte;
  • Obtenir la taille de l'image directement sur la UIImage au lieu de UIImageView
0
saulobrito

En supposant que vous souhaitiez centrer le texte et l'image horizontalement, l'image au-dessus du texte: Centrez le texte à partir du générateur d'interface et ajoutez une insertion supérieure (laissant de la place à l'image). (laissez l'encart à gauche à 0). Utilisez le constructeur d’interface pour choisir l’image. Sa position réelle sera définie à partir du code. Ne vous inquiétez donc pas, les choses ne se passeront pas bien dans IB. Contrairement aux autres réponses ci-dessus, cela fonctionne réellement sur toutes les versions actuellement prises en charge par ios (5,6 et 7).

En code, il suffit de supprimer l'image du bouton (en définissant l'image du bouton sur null) après avoir saisi l'image (le centre sera automatiquement centré sur le texte, si nécessaire). Puis instancier votre propre ImageView avec la même taille de cadre et image et le positionner au milieu.

De cette façon, vous pouvez toujours choisir l'image dans le générateur d'interface (bien qu'elle ne soit pas alignée dans IB comme dans simulateur, mais encore une fois, d'autres solutions ne sont pas compatibles avec toutes les versions d'ios prises en charge).

0
Radu Simionescu

est-il obligatoire d'utiliser des incrustations Edge? Sinon, vous pouvez essayer de positionner le respect par rapport à la vue parent centrale

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

J'ai fait quelques ajustements pour rendre l'image alignée au centre horizontal

// 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));
0

Ajoutez ce code dans l'extension Swift 4.2

 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
Shahzaib Maqbool

Vous devez déplacer l'image vers la droite de la largeur du texte. Déplacez ensuite le texte vers la gauche de la largeur de l'image.

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;

Ensuite, ajustez les encarts supérieur et inférieur pour ajuster l’axe Y. Cela pourrait probablement aussi être fait par programme, mais devrait être constant pour la taille de votre image. Tandis que les incrustations de l'axe des X devront changer en fonction de la taille de l'étiquette de texte de chaque bouton.

0
pkamb