160 votes

UIButton : Comment centrer une image et un texte à l’aide d’imageEdgeInsets et titleEdgeInsets ?

Si j'ai mis une image dans un bouton et réglez la imageEdgeInsets plus proche du sommet, 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 j'ai mis un texte dans un bouton et réglez titleEdgeInsets plus près du fond, 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 j'ai mis les 4 lignes du texte interférer avec l'image et à la fois perdu l'alignement au centre.

Toutes mes images a 30 pixels de largeur, et si je mets 30, à gauche dans le paramètre de UIEdgeInsetMake pour setTitleEdgeInsets, le texte est centré à nouveau. Le problème est que l'image n'est jamais centré parce que parait que c'est dépendante de la touche.titleLabel taille. J'ai déjà essayé de nombreux calculs avec bouton à la taille, taille de l'image, titleLabel taille et de ne jamais obtenir à la fois parfaitement centré.

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

Merci à l'avance.

419voto

Jesse Crossen Points 3244

Pour ce que ça vaut, voici une solution générale au positionnement de l’image centrée au-dessus du texte sans utiliser les numéros de magie :

59voto

R31n4ld0_ Points 2187

Trouvé comment.

Tout d’abord, configurez le texte de titleLabel (en raison de styles, c’est à dire, gras, italique, etc.). Ensuite, utilisez setTitleEdgeInsets compte tenu de la largeur de votre image :

Après cela, utilisez setTitleEdgeInsets compte tenu de la largeur des limites du texte :

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

A bientôt.

20voto

algal Points 4298

Vous pouvez le faire avec ce rapide extension, qui a été fondée en partie sur Jesse Crossen de réponse:

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 le titre et l'image des encarts de façon appropriée.

Il définit également le contentEdgeInsets, je crois que c'est nécessaire pour s'assurer que intrinsicContentSize fonctionne toujours correctement, ce qui aurait besoin de Mise en page Automatique.

Je crois que toutes les solutions qui sous-classe UIButton sont techniquement illégitime, puisque vous n'êtes pas censé sous-classe UIKit contrôles. I. e., en théorie, elles pourraient se briser dans les futures versions.

9voto

Bekir Onat Akin Points 31

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

9voto

Tod Cunningham Points 702

Il y a quelques bons exemples ici, mais je ne pouvais pas obtenir que cela fonctionne dans tous les cas où il traite également avec plusieurs lignes de texte (habillage de texte). Pour enfin le faire fonctionner, j'ai combiné deux techniques:

  1. J'ai utilisé Jesse Crossen exemple ci-dessus. Cependant, je fixe une hauteur de texte question et j'ai ajouté la possibilité de spécifier un texte horizontal de la marge. La marge est utile lorsque vous autorisez le texte s'ajuste de sorte qu'il ne frappe pas le bord de la touche:

    // 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 d'installer le texte de l'étiquette pour envelopper

    button.titleLabel.numberOfLines = 2; 
    button.titleLabel.lineBreakMode = UILineBreakModeWordWrap;
    button.titleLabel.textAlignment = UITextAlignmentCenter;
    
  3. Ce sera surtout le travail maintenant. Cependant, j'ai eu quelques boutons qui ne serait pas rendre leur image correctement. L'image a été abandonné au loin vers la droite ou vers la gauche (il n'était pas centré). J'ai donc utilisé un UIButton le remplacement de la disposition technique à la force de l'imageView centrée.

    @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
    

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X