Pour ce que ça vaut, voici une solution générale pour positionner l'image centrée au-dessus du texte sans utiliser de nombres 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 pour 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 bon fonctionnement ou de sa rupture s'il était utilisé sous 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);
Version Swift 5.0
extension UIButton {
func alignVertical(spacing: CGFloat = 6.0) {
guard let imageSize = imageView?.image?.size,
let text = titleLabel?.text,
let font = titleLabel?.font
else { return }
titleEdgeInsets = UIEdgeInsets(
top: 0.0,
left: -imageSize.width,
bottom: -(imageSize.height + spacing),
right: 0.0
)
let titleSize = text.size(withAttributes: [.font: font])
imageEdgeInsets = UIEdgeInsets(
top: -(titleSize.height + spacing),
left: 0.0,
bottom: 0.0, right: -titleSize.width
)
let edgeOffset = abs(titleSize.height - imageSize.height) / 2.0
contentEdgeInsets = UIEdgeInsets(
top: edgeOffset,
left: 0.0,
bottom: edgeOffset,
right: 0.0
)
}
}
button.currentTitle
au lieu debutton.titleLabel.text
surtout si le texte du bouton changera un jour.currentTitle
esttitleLabel.text
rempli immédiatement, alors que le changement peut être lent, ce qui peut conduire à des inserts mal alignés.Trouvé comment.
Tout d'abord, configurez le texte de
titleLabel
(à cause des styles, c'est-à-dire gras, italique, etc.). Ensuite, utilisez ensetTitleEdgeInsets
tenant compte de la largeur de votre image:Après cela, utilisez en
setTitleEdgeInsets
tenant compte 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).
À votre santé.
la source
Vous pouvez le faire avec cette extension Swift, qui était en partie basée sur la réponse de Jesse Crossen:
Cela définit une fonction
centerLabelVerticallyWithPadding
qui définit le titre et les incrustations d'image de manière appropriée.Il définit également contentEdgeInsets, ce qui, à mon avis, est nécessaire pour garantir qu'il
intrinsicContentSize
fonctionne toujours correctement, ce qui devrait utiliser la mise en page automatique.Je crois que toutes les solutions qui sous-classent UIButton sont techniquement illégitimes, puisque vous n'êtes pas censé sous-classer les contrôles UIKit. Ie, en théorie, ils pourraient casser dans les versions futures.
la source
Edit: mis à jour pour Swift 3
Si vous recherchez une solution Swift de la réponse de Jesse Crossen, vous pouvez l'ajouter à une sous-classe de UIButton:
la source
Il y a de bons exemples ici, mais je ne pouvais pas faire fonctionner cela dans tous les cas lorsque je traitais également plusieurs lignes de texte (habillage de texte). Pour enfin le faire fonctionner, j'ai combiné quelques techniques:
J'ai utilisé l'exemple de Jesse Crossen ci-dessus. Cependant, j'ai corrigé un problème de hauteur du texte et j'ai ajouté la possibilité de spécifier une marge de texte horizontale. La marge est utile lorsque vous autorisez le texte à s'habiller afin qu'il ne touche pas le bord du bouton:
Assurez-vous que vous avez configuré l'étiquette de texte pour envelopper
Cela fonctionnera principalement maintenant. Cependant, j'avais des boutons qui ne rendaient pas correctement leur image. L'image a été déplacée vers la droite ou vers la gauche (elle n'était pas centrée). J'ai donc utilisé une technique de remplacement de disposition UIButton pour forcer l'imageView à être centrée.
la source
J'ai créé une méthode pour la réponse de @ TodCunningham
la source
Mis à jour pour Xcode 11+
Les inserts décrits dans ma réponse originale ont été déplacés vers l'inspecteur de taille dans les versions plus récentes de Xcode. Je ne suis pas sûr à 100% du moment où le changement s'est produit, mais les lecteurs devraient consulter l'inspecteur de taille si les informations en médaillon ne sont pas trouvées dans l'inspecteur d'attributs. Vous trouverez ci-dessous un exemple du nouvel écran encart (situé en haut de l'inspecteur des attributs de taille à partir de 11.5).
Réponse originale
Rien de mal avec les 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 nécessite 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 des vues d'image, de titre et de contenu d'un bouton à l'aide d'inserts de bord, vous pouvez sélectionner le bouton / contrôle et ouvrir l'inspecteur d'attributs. Faites défiler vers le milieu de l'inspecteur et recherchez la section des inserts Edge.
On peut également accéder et modifier les inserts de bord spécifiques pour la vue titre, image ou contenu.
la source
Ne combattez pas le système. Si vos mises en page deviennent trop complexes à gérer avec Interface Builder + peut-être un code de configuration simple, effectuez les mises en page manuellement de manière plus simple en utilisant
layoutSubviews
- c'est à ça que ça sert! Tout le reste équivaudra à des hacks.Créez une sous-classe UIButton et remplacez sa
layoutSubviews
méthode pour aligner votre texte et image par programmation. Ou utilisez quelque chose comme https://github.com/nickpaulson/BlockKit/blob/master/Source/UIView-BKAdditions.h afin de pouvoir implémenter layoutSubviews à l'aide d'un bloc.la source
Sous-classe UIButton
la source
Réponse mise à jour de Jesse Crossen pour Swift 4 :
Utilisez de cette façon:
la source
Avec ce morceau de code, vous obtiendrez quelque chose comme ça
la source
Extension UIButton avec syntaxe Swift 3+ :
Réponse originale: https://stackoverflow.com/a/7199529/3659227
la source
Juste un changement mineur à la réponse de Jesse Crossen qui l'a fait fonctionner parfaitement pour moi:
au lieu de:
J'ai utilisé ceci:
la source
L'utilisation ne
button.titleLabel.frame.size.width
fonctionne bien que tant que l'étiquette est suffisamment courte pour ne pas être tronquée. Cependant, lorsque le texte de l'étiquette est tronqué, le positionnement ne fonctionne pas. Prisefonctionne pour moi même lorsque le texte de l'étiquette est tronqué.
la source
J'ai regardé les 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 s'occupe de ceci:
la source
Ou vous pouvez simplement utiliser cette catégorie:
la source
CGSize titleSize = [button.titleLabel.text sizeWithAttributes: @{NSFontAttributeName: button.titleLabel.font}];
Mon cas d'utilisation a rendu les inserts ingérables:
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éclarez un UIImageView dans ma classe:
Créez une instance de vue d'image sur init:
Dans viewDidLoad, ajoutez un nouveau calque au bouton de notre vue d'image et définissez l'alignement du texte:
Dans la méthode du clic sur le bouton, ajoutez l'image de superposition choisie à la vue de l'image, redimensionnez-la pour l'adapter à l'image et centrez-la dans le bouton, mais déplacez-la vers le haut de 15 afin que je puisse mettre le décalage de texte en dessous:
Remarque: ceilf () est important pour s'assurer qu'il est sur une limite de pixels pour la qualité d'image.
la source
En supposant que vous souhaitiez que le texte et l'image soient centrés horizontalement, image au-dessus du texte: Centrez le texte du générateur d'interface et ajoutez un encart supérieur (faisant de la place pour l'image). (laissez l'encart gauche à 0). Utilisez le générateur d'interface pour choisir l'image - sa position réelle sera définie à partir du code, alors ne vous inquiétez pas que les choses ne vont pas bien dans IB. Contrairement aux autres réponses ci-dessus, cela fonctionne sur toutes les versions iOS actuellement prises en charge (5, 6 et 7).
Dans le code, supprimez simplement le ImageView du bouton (en définissant l'image du bouton sur null) après avoir saisi l'image (cela centrera également automatiquement le texte, enveloppé si nécessaire). Ensuite, instanciez votre propre ImageView avec la même taille de cadre et la même image et positionnez-la 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 le simulateur, mais là encore, les autres solutions ne sont pas compatibles avec toutes les versions ios prises en charge)
la source
J'avais du mal à faire cela car je ne pouvais pas obtenir la taille de l'image et la largeur du texte sur le constructeur de ma vue. Deux changements mineurs sur la réponse de Jesse ont fonctionné pour moi:
Les changements sont:
[NSString sizeWithAttributes]
pour obtenir la largeur du texte;UIImage
lieu deUIImageView
la source
Cela fonctionne bien pour moi, pour plusieurs boutons, avec une largeur d'image différente et une longueur de titre différente:
Sous-classe
UIButton
la source
Fonctionne bien pour la taille du bouton 80x80 pixels.
la source
J'ai fait quelques ajustements pour que l'image soit alignée au centre horizontal:
la source
est-il obligatoire d'utiliser des inserts de bord? Sinon, vous pouvez essayer de positionner par rapport à la vue parent centrale
la source
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.
Ajustez ensuite les inserts supérieur et inférieur pour ajuster l'axe Y. Cela peut également être fait par programme, mais doit être constant pour la taille de votre image. Alors que les inserts de l'axe X devront changer en fonction de la taille de l'étiquette de texte dans chaque bouton.
la source
Ajoutez ce code dans l'extension Swift 4.2
la source
Juste pour jeter mes 2 cents, cela a fonctionné pour moi:
la source