J'aimerais placer une icône à gauche des deux lignes de texte, de sorte qu'il y ait environ 2 ou 3 pixels d'espace entre l'image et le début du texte. Le contrôle lui-même est aligné horizontalement au centre (défini via Interface Builder)
Le bouton ressemblerait à quelque chose comme ça:
| |
|[Image] Add To |
| Favorites |
J'essaie de configurer cela avec contentEdgeInset, imageEdgeInsets et titleEdgeInsets, mais en vain. Je comprends qu’une valeur négative élargit l’Edge, tandis qu’une valeur positive le réduit pour le rapprocher du centre.
J'ai essayé:
[button setTitleEdgeInsets:UIEdgeInsetsMake(0, -image.size.width, 0, 0)];
[button setImageEdgeInsets:UIEdgeInsetsMake(0, button.titleLabel.bounds.size.width, 0, 0)];
mais cela ne l'affiche pas correctement. J'ai peaufiné les valeurs, mais passer de -5 à -10 sur la valeur insérée à gauche ne semble pas le déplacer de la manière attendue. -10 scootera le texte tout à fait à gauche, alors je m'attendais à -5 à le scoot à mi-chemin depuis le côté gauche, mais ce n'est pas le cas.
Quelle est la logique derrière les encarts? Je ne suis pas familier avec les placements d'image et la terminologie associée.
J'ai utilisé cette question SO comme référence mais quelque chose à propos de mes valeurs n'est pas correct . UIButton: comment centrer une image et un texte à l'aide de imageEdgeInsets et titleEdgeInsets?
Je conviens que la documentation sur imageEdgeInsets
et titleEdgeInsets
devrait être meilleure, mais j’ai bien compris comment obtenir le bon positionnement sans recourir à des essais et à des erreurs.
L'idée générale est ici à cette question , mais c'était si vous vouliez centrer le texte et l'image. Nous ne voulons pas que l'image et le texte soient centrés individuellement, nous voulons que l'image et le texte soient centrés ensemble comme une seule entité. C’est en fait ce que fait déjà UIButton, nous devons donc simplement ajuster l’espacement.
CGFloat spacing = 10; // the amount of spacing to appear between image and title
tabBtn.imageEdgeInsets = UIEdgeInsetsMake(0, 0, 0, spacing);
tabBtn.titleEdgeInsets = UIEdgeInsetsMake(0, spacing, 0, 0);
J'ai aussi transformé cela en une catégorie pour UIButton, donc ce sera facile à utiliser:
UIButton + Position.h
@interface UIButton(ImageTitleCentering)
-(void) centerButtonAndImageWithSpacing:(CGFloat)spacing;
@end
UIButton + Position.m
@implementation UIButton(ImageTitleCentering)
-(void) centerButtonAndImageWithSpacing:(CGFloat)spacing {
self.imageEdgeInsets = UIEdgeInsetsMake(0, 0, 0, spacing);
self.titleEdgeInsets = UIEdgeInsetsMake(0, spacing, 0, 0);
}
@end
Alors maintenant, tout ce que je dois faire, c'est:
[button centerButtonAndImageWithSpacing:10];
Et je reçois ce dont j'ai besoin à chaque fois. Plus besoin de jouer avec les incrustations Edge manuellement.
EDIT: Permuter l'image et le texte
En réponse à @Javal dans les commentaires
En utilisant ce même mécanisme, nous pouvons échanger l'image et le texte. Pour effectuer l'échange, utilisez simplement un espacement négatif, mais incluez également la largeur du texte et de l'image. Cela nécessitera de connaître les images et d'effectuer la mise en page déjà.
[self.view layoutIfNeeded];
CGFloat flippedSpacing = -(desiredSpacing + button.currentImage.size.width + button.titleLabel.frame.size.width);
[button centerButtonAndImageWithSpacing:flippedSpacing];
Bien sûr, vous voudrez probablement faire une méthode Nice pour cela, en ajoutant potentiellement une méthode de deuxième catégorie, ceci est laissé comme exercice au lecteur.
Je suis un peu en retard à cette fête, mais je pense avoir quelque chose d'utile à ajouter.
La réponse de Kekoa est excellente, mais, comme le mentionne RonLugge, le bouton peut ne plus être respecté par sizeToFit
ou, ce qui est plus important, le contenu du bouton doit être coupé lorsqu'il est de taille intrinsèque. Beurk!
D'abord, cependant
Une brève explication de la façon dont je crois que imageEdgeInsets
et titleEdgeInsets
fonctionnent:
Les docs pour imageEdgeInsets
ont notamment les éléments suivants:
Utilisez cette propriété pour redimensionner et repositionner le rectangle de dessin effectif pour l'image du bouton. Vous pouvez spécifier une valeur différente pour chacune des quatre encarts (haut, gauche, bas, droite). Une valeur positive réduit ou insère ce bord, le rapprochant du centre du bouton. Une valeur négative développe ou confine ce bord.
Je crois que cette documentation a été écrite en imaginant que le bouton n’a pas de titre, mais seulement une image. C’est beaucoup plus logique de cette façon, et se comporte comme UIEdgeInsets
le font habituellement. Fondamentalement, le cadre de l'image (ou le titre, avec titleEdgeInsets
) est déplacé vers l'intérieur pour les incrustations positives et vers l'extérieur pour les incrustations négatives.
Okay, alors quoi?
J'y arrive! Voici ce que vous avez par défaut, en définissant une image et un titre (la bordure du bouton est verte pour montrer où elle se trouve):
Lorsque vous souhaitez espacer une image et un titre, sans que cela soit écrasé, vous devez définir quatre encarts différents, deux sur chaque image et chaque titre. C'est parce que vous ne voulez pas changer les tailles des cadres de ces éléments, mais seulement leur position. Lorsque vous commencez à penser de cette façon, le changement nécessaire dans l'excellente catégorie de Kekoa devient évident:
@implementation UIButton(ImageTitleCentering)
- (void)centerButtonAndImageWithSpacing:(CGFloat)spacing {
CGFloat insetAmount = spacing / 2.0;
self.imageEdgeInsets = UIEdgeInsetsMake(0, -insetAmount, 0, insetAmount);
self.titleEdgeInsets = UIEdgeInsetsMake(0, insetAmount, 0, -insetAmount);
}
@end
Mais attendez, vous dites, quand je fais cela, je comprends ceci:
Oh oui! J'ai oublié, les docs m'ont prévenu à ce sujet. Ils disent en partie:
Cette propriété est utilisée uniquement pour positionner l'image lors de la mise en page. Le bouton n'utilise pas cette propriété pour déterminer
intrinsicContentSize
etsizeThatFits:
.
Mais il y a est une propriété qui peut aider, et c'est contentEdgeInsets
. Les docs pour cela dire en partie:
Le bouton utilise cette propriété pour déterminer
intrinsicContentSize
etsizeThatFits:
.
Ça sonne bien. Alors, peaufinons encore une fois la catégorie:
@implementation UIButton(ImageTitleCentering)
- (void)centerButtonAndImageWithSpacing:(CGFloat)spacing {
CGFloat insetAmount = spacing / 2.0;
self.imageEdgeInsets = UIEdgeInsetsMake(0, -insetAmount, 0, insetAmount);
self.titleEdgeInsets = UIEdgeInsetsMake(0, insetAmount, 0, -insetAmount);
self.contentEdgeInsets = UIEdgeInsetsMake(0, insetAmount, 0, insetAmount);
}
@end
Et vous obtenez quoi?
On dirait un gagnant pour moi.
Travailler à Swift et ne pas penser du tout? Voici la version finale de l'extension dans Swift:
extension UIButton {
func centerTextAndImage(spacing: CGFloat) {
let insetAmount = spacing / 2
imageEdgeInsets = UIEdgeInsets(top: 0, left: -insetAmount, bottom: 0, right: insetAmount)
titleEdgeInsets = UIEdgeInsets(top: 0, left: insetAmount, bottom: 0, right: -insetAmount)
contentEdgeInsets = UIEdgeInsets(top: 0, left: insetAmount, bottom: 0, right: insetAmount)
}
}
Dans l'interface Builder. Sélectionnez UIButton -> Inspecteur d'attributs -> Edge = Titre et modifiez les incrustations Edge
Aussi, si vous voulez faire quelque chose de similaire à
Vous avez besoin
1. Réglez l'alignement horizontal et vertical du bouton sur
Recherchez toutes les valeurs requises et définissez UIImageEdgeInsets
CGSize buttonSize = button.frame.size;
NSString *buttonTitle = button.titleLabel.text;
CGSize titleSize = [buttonTitle sizeWithAttributes:@{ NSFontAttributeName : [UIFont camFontZonaProBoldWithSize:12.f] }];
UIImage *buttonImage = button.imageView.image;
CGSize buttonImageSize = buttonImage.size;
CGFloat offsetBetweenImageAndText = 10; //vertical space between image and text
[button setImageEdgeInsets:UIEdgeInsetsMake((buttonSize.height - (titleSize.height + buttonImageSize.height)) / 2 - offsetBetweenImageAndText,
(buttonSize.width - buttonImageSize.width) / 2,
0,0)];
[button setTitleEdgeInsets:UIEdgeInsetsMake((buttonSize.height - (titleSize.height + buttonImageSize.height)) / 2 + buttonImageSize.height + offsetBetweenImageAndText,
titleSize.width + [button imageEdgeInsets].left > buttonSize.width ? -buttonImage.size.width + (buttonSize.width - titleSize.width) / 2 : (buttonSize.width - titleSize.width) / 2 - buttonImage.size.width,
0,0)];
Cela organisera votre titre et votre image sur le bouton.
Veuillez également noter la mise à jour à chaque relais
Rapide
import UIKit
extension UIButton {
// MARK: - UIButton+Aligment
func alignContentVerticallyByCenter(offset:CGFloat = 10) {
let buttonSize = frame.size
if let titleLabel = titleLabel,
let imageView = imageView {
if let buttonTitle = titleLabel.text,
let image = imageView.image {
let titleString:NSString = NSString(string: buttonTitle)
let titleSize = titleString.sizeWithAttributes([
NSFontAttributeName : titleLabel.font
])
let buttonImageSize = image.size
let topImageOffset = (buttonSize.height - (titleSize.height + buttonImageSize.height + offset)) / 2
let leftImageOffset = (buttonSize.width - buttonImageSize.width) / 2
imageEdgeInsets = UIEdgeInsetsMake(topImageOffset,
leftImageOffset,
0,0)
let titleTopOffset = topImageOffset + offset + buttonImageSize.height
let leftTitleOffset = (buttonSize.width - titleSize.width) / 2 - image.size.width
titleEdgeInsets = UIEdgeInsetsMake(titleTopOffset,
leftTitleOffset,
0,0)
}
}
}
}
Vous pouvez éviter beaucoup de problèmes en utilisant ceci -
myButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
myButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
Cela alignera tout votre contenu automatiquement à gauche (ou où vous le souhaitez)
Swift 3:
myButton.contentHorizontalAlignment = UIControlContentHorizontalAlignment.left;
myButton.contentVerticalAlignment = UIControlContentVerticalAlignment.center;
Dans Xcode 8.0, vous pouvez simplement le faire en modifiant insets
dans l'inspecteur de taille.
Sélectionnez l'onglet UIButton -> Inspecteur d'attributs -> allez dans l'inspecteur de taille et modifiez le contenu, les images et le titre.
Et si vous souhaitez modifier l'image sur le côté droit, vous pouvez simplement modifier la propriété sémantique en Force Right-to-left
dans l'inspecteur d'attributs.
Je suis un peu en retard à cette fête aussi, mais je pense avoir quelque chose d’utile à ajouter: o).
J'ai créé une sous-classe UIButton
dont le but est de pouvoir choisir l'emplacement de l'image du bouton, verticalement ou horizontalement.
Cela signifie que vous pouvez créer ce type de boutons:
Voici les détails sur la façon de créer ces boutons avec ma classe:
func makeButton (imageVerticalAlignment:LayoutableButton.VerticalAlignment, imageHorizontalAlignment:LayoutableButton.HorizontalAlignment, title:String) -> LayoutableButton {
let button = LayoutableButton ()
button.imageVerticalAlignment = imageVerticalAlignment
button.imageHorizontalAlignment = imageHorizontalAlignment
button.setTitle(title, for: .normal)
// add image, border, ...
return button
}
let button1 = makeButton(imageVerticalAlignment: .center, imageHorizontalAlignment: .left, title: "button1")
let button2 = makeButton(imageVerticalAlignment: .center, imageHorizontalAlignment: .right, title: "button2")
let button3 = makeButton(imageVerticalAlignment: .top, imageHorizontalAlignment: .center, title: "button3")
let button4 = makeButton(imageVerticalAlignment: .bottom, imageHorizontalAlignment: .center, title: "button4")
let button5 = makeButton(imageVerticalAlignment: .bottom, imageHorizontalAlignment: .center, title: "button5")
button5.contentEdgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
Pour ce faire, j'ai ajouté 2 attributs: imageVerticalAlignment
et imageHorizontalAlignment
. Bien sûr, si votre bouton n'a qu'une image ou un titre ... n'utilisez pas cette classe du tout!
J'ai également ajouté un attribut nommé imageToTitleSpacing
qui vous permet d'ajuster l'espace entre le titre et l'image.
Cette classe fait de son mieux pour être compatible si vous souhaitez utiliser imageEdgeInsets
, titleEdgeInsets
et contentEdgeInsets
directement ou en combinaison avec les nouveaux attributs de présentation.
Comme @ravron nous l'explique, je fais de mon mieux pour corriger le contenu du bouton Edge (comme vous pouvez le voir avec les bordures rouges).
Vous pouvez également l'utiliser dans Interface Builder:
Voici le code ( Gist ):
@IBDesignable
class LayoutableButton: UIButton {
enum VerticalAlignment : String {
case center, top, bottom, unset
}
enum HorizontalAlignment : String {
case center, left, right, unset
}
@IBInspectable
var imageToTitleSpacing: CGFloat = 8.0 {
didSet {
setNeedsLayout()
}
}
var imageVerticalAlignment: VerticalAlignment = .unset {
didSet {
setNeedsLayout()
}
}
var imageHorizontalAlignment: HorizontalAlignment = .unset {
didSet {
setNeedsLayout()
}
}
@available(*, unavailable, message: "This property is reserved for Interface Builder. Use 'imageVerticalAlignment' instead.")
@IBInspectable
var imageVerticalAlignmentName: String {
get {
return imageVerticalAlignment.rawValue
}
set {
if let value = VerticalAlignment(rawValue: newValue) {
imageVerticalAlignment = value
} else {
imageVerticalAlignment = .unset
}
}
}
@available(*, unavailable, message: "This property is reserved for Interface Builder. Use 'imageHorizontalAlignment' instead.")
@IBInspectable
var imageHorizontalAlignmentName: String {
get {
return imageHorizontalAlignment.rawValue
}
set {
if let value = HorizontalAlignment(rawValue: newValue) {
imageHorizontalAlignment = value
} else {
imageHorizontalAlignment = .unset
}
}
}
var extraContentEdgeInsets:UIEdgeInsets = UIEdgeInsets.zero
override var contentEdgeInsets: UIEdgeInsets {
get {
return super.contentEdgeInsets
}
set {
super.contentEdgeInsets = newValue
self.extraContentEdgeInsets = newValue
}
}
var extraImageEdgeInsets:UIEdgeInsets = UIEdgeInsets.zero
override var imageEdgeInsets: UIEdgeInsets {
get {
return super.imageEdgeInsets
}
set {
super.imageEdgeInsets = newValue
self.extraImageEdgeInsets = newValue
}
}
var extraTitleEdgeInsets:UIEdgeInsets = UIEdgeInsets.zero
override var titleEdgeInsets: UIEdgeInsets {
get {
return super.titleEdgeInsets
}
set {
super.titleEdgeInsets = newValue
self.extraTitleEdgeInsets = newValue
}
}
//Needed to avoid IB crash during autolayout
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.imageEdgeInsets = super.imageEdgeInsets
self.titleEdgeInsets = super.titleEdgeInsets
self.contentEdgeInsets = super.contentEdgeInsets
}
override func layoutSubviews() {
if let imageSize = self.imageView?.image?.size,
let font = self.titleLabel?.font,
let textSize = self.titleLabel?.attributedText?.size() ?? self.titleLabel?.text?.size(attributes: [NSFontAttributeName: font]) {
var _imageEdgeInsets = UIEdgeInsets.zero
var _titleEdgeInsets = UIEdgeInsets.zero
var _contentEdgeInsets = UIEdgeInsets.zero
let halfImageToTitleSpacing = imageToTitleSpacing / 2.0
switch imageVerticalAlignment {
case .bottom:
_imageEdgeInsets.top = (textSize.height + imageToTitleSpacing) / 2.0
_imageEdgeInsets.bottom = (-textSize.height - imageToTitleSpacing) / 2.0
_titleEdgeInsets.top = (-imageSize.height - imageToTitleSpacing) / 2.0
_titleEdgeInsets.bottom = (imageSize.height + imageToTitleSpacing) / 2.0
_contentEdgeInsets.top = (min (imageSize.height, textSize.height) + imageToTitleSpacing) / 2.0
_contentEdgeInsets.bottom = (min (imageSize.height, textSize.height) + imageToTitleSpacing) / 2.0
//only works with contentVerticalAlignment = .center
contentVerticalAlignment = .center
case .top:
_imageEdgeInsets.top = (-textSize.height - imageToTitleSpacing) / 2.0
_imageEdgeInsets.bottom = (textSize.height + imageToTitleSpacing) / 2.0
_titleEdgeInsets.top = (imageSize.height + imageToTitleSpacing) / 2.0
_titleEdgeInsets.bottom = (-imageSize.height - imageToTitleSpacing) / 2.0
_contentEdgeInsets.top = (min (imageSize.height, textSize.height) + imageToTitleSpacing) / 2.0
_contentEdgeInsets.bottom = (min (imageSize.height, textSize.height) + imageToTitleSpacing) / 2.0
//only works with contentVerticalAlignment = .center
contentVerticalAlignment = .center
case .center:
//only works with contentVerticalAlignment = .center
contentVerticalAlignment = .center
break
case .unset:
break
}
switch imageHorizontalAlignment {
case .left:
_imageEdgeInsets.left = -halfImageToTitleSpacing
_imageEdgeInsets.right = halfImageToTitleSpacing
_titleEdgeInsets.left = halfImageToTitleSpacing
_titleEdgeInsets.right = -halfImageToTitleSpacing
_contentEdgeInsets.left = halfImageToTitleSpacing
_contentEdgeInsets.right = halfImageToTitleSpacing
case .right:
_imageEdgeInsets.left = textSize.width + halfImageToTitleSpacing
_imageEdgeInsets.right = -textSize.width - halfImageToTitleSpacing
_titleEdgeInsets.left = -imageSize.width - halfImageToTitleSpacing
_titleEdgeInsets.right = imageSize.width + halfImageToTitleSpacing
_contentEdgeInsets.left = halfImageToTitleSpacing
_contentEdgeInsets.right = halfImageToTitleSpacing
case .center:
_imageEdgeInsets.left = textSize.width / 2.0
_imageEdgeInsets.right = -textSize.width / 2.0
_titleEdgeInsets.left = -imageSize.width / 2.0
_titleEdgeInsets.right = imageSize.width / 2.0
_contentEdgeInsets.left = -((imageSize.width + textSize.width) - max (imageSize.width, textSize.width)) / 2.0
_contentEdgeInsets.right = -((imageSize.width + textSize.width) - max (imageSize.width, textSize.width)) / 2.0
case .unset:
break
}
_contentEdgeInsets.top += extraContentEdgeInsets.top
_contentEdgeInsets.bottom += extraContentEdgeInsets.bottom
_contentEdgeInsets.left += extraContentEdgeInsets.left
_contentEdgeInsets.right += extraContentEdgeInsets.right
_imageEdgeInsets.top += extraImageEdgeInsets.top
_imageEdgeInsets.bottom += extraImageEdgeInsets.bottom
_imageEdgeInsets.left += extraImageEdgeInsets.left
_imageEdgeInsets.right += extraImageEdgeInsets.right
_titleEdgeInsets.top += extraTitleEdgeInsets.top
_titleEdgeInsets.bottom += extraTitleEdgeInsets.bottom
_titleEdgeInsets.left += extraTitleEdgeInsets.left
_titleEdgeInsets.right += extraTitleEdgeInsets.right
super.imageEdgeInsets = _imageEdgeInsets
super.titleEdgeInsets = _titleEdgeInsets
super.contentEdgeInsets = _contentEdgeInsets
} else {
super.imageEdgeInsets = extraImageEdgeInsets
super.titleEdgeInsets = extraTitleEdgeInsets
super.contentEdgeInsets = extraContentEdgeInsets
}
super.layoutSubviews()
}
}
Un petit ajout à la réponse de Riley Avron aux modifications des paramètres régionaux du compte:
extension UIButton {
func centerTextAndImage(spacing: CGFloat) {
let insetAmount = spacing / 2
let writingDirection = UIApplication.sharedApplication().userInterfaceLayoutDirection
let factor: CGFloat = writingDirection == .LeftToRight ? 1 : -1
self.imageEdgeInsets = UIEdgeInsets(top: 0, left: -insetAmount*factor, bottom: 0, right: insetAmount*factor)
self.titleEdgeInsets = UIEdgeInsets(top: 0, left: insetAmount*factor, bottom: 0, right: -insetAmount*factor)
self.contentEdgeInsets = UIEdgeInsets(top: 0, left: insetAmount, bottom: 0, right: insetAmount)
}
}
Swift 4.x
extension UIButton {
func centerTextAndImage(spacing: CGFloat) {
let insetAmount = spacing / 2
let writingDirection = UIApplication.shared.userInterfaceLayoutDirection
let factor: CGFloat = writingDirection == .leftToRight ? 1 : -1
self.imageEdgeInsets = UIEdgeInsets(top: 0, left: -insetAmount*factor, bottom: 0, right: insetAmount*factor)
self.titleEdgeInsets = UIEdgeInsets(top: 0, left: insetAmount*factor, bottom: 0, right: -insetAmount*factor)
self.contentEdgeInsets = UIEdgeInsets(top: 0, left: insetAmount, bottom: 0, right: insetAmount)
}
}
Utilisation :
button.centerTextAndImage(spacing: 10.0)
Voici un exemple simple d'utilisation de imageEdgeInsets Un bouton 30x30 avec une zone masquable agrandie de 10 pixels tout autour (50x50)
var expandHittableAreaAmt : CGFloat = 10
var buttonWidth : CGFloat = 30
var button = UIButton.buttonWithType(UIButtonType.Custom) as UIButton
button.frame = CGRectMake(0, 0, buttonWidth+expandHittableAreaAmt, buttonWidth+expandHittableAreaAmt)
button.imageEdgeInsets = UIEdgeInsetsMake(expandHittableAreaAmt, expandHittableAreaAmt, expandHittableAreaAmt, expandHittableAreaAmt)
button.setImage(UIImage(named: "buttonImage"), forState: .Normal)
button.addTarget(self, action: "didTouchButton:", forControlEvents:.TouchUpInside)
J'écris le code ci-dessous. Cela fonctionne bien dans la version du produit. Supportez Swift 4.2 +
extension UIButton{
enum ImageTitleRelativeLocation {
case imageUpTitleDown
case imageDownTitleUp
case imageLeftTitleRight
case imageRightTitleLeft
}
func centerContentRelativeLocation(_ relativeLocation:
ImageTitleRelativeLocation,
spacing: CGFloat = 0) {
assert(contentVerticalAlignment == .center,
"only works with contentVerticalAlignment = .center !!!")
guard (title(for: .normal) != nil) || (attributedTitle(for: .normal) != nil) else {
assert(false, "TITLE IS NIL! SET TITTLE FIRST!")
return
}
guard let imageSize = self.currentImage?.size else {
assert(false, "IMGAGE IS NIL! SET IMAGE FIRST!!!")
return
}
guard let titleSize = titleLabel?
.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize) else {
assert(false, "TITLELABEL IS NIL!")
return
}
let horizontalResistent: CGFloat
// extend contenArea in case of title is shrink
if frame.width < titleSize.width + imageSize.width {
horizontalResistent = titleSize.width + imageSize.width - frame.width
print("horizontalResistent", horizontalResistent)
} else {
horizontalResistent = 0
}
var adjustImageEdgeInsets: UIEdgeInsets = .zero
var adjustTitleEdgeInsets: UIEdgeInsets = .zero
var adjustContentEdgeInsets: UIEdgeInsets = .zero
let verticalImageAbsOffset = abs((titleSize.height + spacing) / 2)
let verticalTitleAbsOffset = abs((imageSize.height + spacing) / 2)
switch relativeLocation {
case .imageUpTitleDown:
adjustImageEdgeInsets.top = -verticalImageAbsOffset
adjustImageEdgeInsets.bottom = verticalImageAbsOffset
adjustImageEdgeInsets.left = titleSize.width / 2 + horizontalResistent / 2
adjustImageEdgeInsets.right = -titleSize.width / 2 - horizontalResistent / 2
adjustTitleEdgeInsets.top = verticalTitleAbsOffset
adjustTitleEdgeInsets.bottom = -verticalTitleAbsOffset
adjustTitleEdgeInsets.left = -imageSize.width / 2 + horizontalResistent / 2
adjustTitleEdgeInsets.right = imageSize.width / 2 - horizontalResistent / 2
adjustContentEdgeInsets.top = spacing
adjustContentEdgeInsets.bottom = spacing
adjustContentEdgeInsets.left = -horizontalResistent
adjustContentEdgeInsets.right = -horizontalResistent
case .imageDownTitleUp:
adjustImageEdgeInsets.top = verticalImageAbsOffset
adjustImageEdgeInsets.bottom = -verticalImageAbsOffset
adjustImageEdgeInsets.left = titleSize.width / 2 + horizontalResistent / 2
adjustImageEdgeInsets.right = -titleSize.width / 2 - horizontalResistent / 2
adjustTitleEdgeInsets.top = -verticalTitleAbsOffset
adjustTitleEdgeInsets.bottom = verticalTitleAbsOffset
adjustTitleEdgeInsets.left = -imageSize.width / 2 + horizontalResistent / 2
adjustTitleEdgeInsets.right = imageSize.width / 2 - horizontalResistent / 2
adjustContentEdgeInsets.top = spacing
adjustContentEdgeInsets.bottom = spacing
adjustContentEdgeInsets.left = -horizontalResistent
adjustContentEdgeInsets.right = -horizontalResistent
case .imageLeftTitleRight:
adjustImageEdgeInsets.left = -spacing / 2
adjustImageEdgeInsets.right = spacing / 2
adjustTitleEdgeInsets.left = spacing / 2
adjustTitleEdgeInsets.right = -spacing / 2
adjustContentEdgeInsets.left = spacing
adjustContentEdgeInsets.right = spacing
case .imageRightTitleLeft:
adjustImageEdgeInsets.left = titleSize.width + spacing / 2
adjustImageEdgeInsets.right = -titleSize.width - spacing / 2
adjustTitleEdgeInsets.left = -imageSize.width - spacing / 2
adjustTitleEdgeInsets.right = imageSize.width + spacing / 2
adjustContentEdgeInsets.left = spacing
adjustContentEdgeInsets.right = spacing
}
imageEdgeInsets = adjustImageEdgeInsets
titleEdgeInsets = adjustTitleEdgeInsets
contentEdgeInsets = adjustContentEdgeInsets
setNeedsLayout()
}
}
Une manière élégante dans Swift 3 et mieux à comprendre:
override func imageRect(forContentRect contentRect: CGRect) -> CGRect {
let leftMargin:CGFloat = 40
let imgWidth:CGFloat = 24
let imgHeight:CGFloat = 24
return CGRect(x: leftMargin, y: (contentRect.size.height-imgHeight) * 0.5, width: imgWidth, height: imgHeight)
}
override func titleRect(forContentRect contentRect: CGRect) -> CGRect {
let leftMargin:CGFloat = 80
let rightMargin:CGFloat = 80
return CGRect(x: leftMargin, y: 0, width: contentRect.size.width-leftMargin-rightMargin, height: contentRect.size.height)
}
override func backgroundRect(forBounds bounds: CGRect) -> CGRect {
let leftMargin:CGFloat = 10
let rightMargin:CGFloat = 10
let topMargin:CGFloat = 10
let bottomMargin:CGFloat = 10
return CGRect(x: leftMargin, y: topMargin, width: bounds.size.width-leftMargin-rightMargin, height: bounds.size.height-topMargin-bottomMargin)
}
override func contentRect(forBounds bounds: CGRect) -> CGRect {
let leftMargin:CGFloat = 5
let rightMargin:CGFloat = 5
let topMargin:CGFloat = 5
let bottomMargin:CGFloat = 5
return CGRect(x: leftMargin, y: topMargin, width: bounds.size.width-leftMargin-rightMargin, height: bounds.size.height-topMargin-bottomMargin)
}
La version 4.2 de la solution Swift serait la suivante:
let spacing: CGFloat = 10 // the amount of spacing to appear between image and title
self.button?.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: spacing)
self.button?.titleEdgeInsets = UIEdgeInsets(top: 0, left: spacing, bottom: 0, right: 0)