J'ai vu des articles sur l'alignement à droite, mais je ne parviens pas à obtenir l'alignement à gauche. Je veux que le bouton occupe la largeur de l'écran, avec l'image à gauche et le titre/texte au centre.
Cela ne fonctionne pas (du moins de manière fiable):
button.titleLabel.textAlignment = UITextAlignmentCenter;
[button setImageEdgeInsets:UIEdgeInsetsMake(0, -60.0, 0, 0)];
button.frame = CGRectMake((self.view.frame.size.width - w ) / 2, self.view.frame.size.height - 140.0, self.view.frame.size.width - 10.0, 40.0);
Cette solution fonctionne avec Swift 3 et respecte le contenu d'origine et les incrustations d'image tout en maintenant l'étiquette du titre toujours centrée sur l'espace disponible, ce qui facilite beaucoup l'ajustement des marges.
Il écrase la méthode titleRect(forContentRect:)
et renvoie le cadre correct:
@IBDesignable
class LeftAlignedIconButton: UIButton {
override func titleRect(forContentRect contentRect: CGRect) -> CGRect {
let titleRect = super.titleRect(forContentRect: contentRect)
let imageSize = currentImage?.size ?? .zero
let availableWidth = contentRect.width - imageEdgeInsets.right - imageSize.width - titleRect.width
return titleRect.offsetBy(dx: round(availableWidth / 2), dy: 0)
}
}
Les encarts suivants:
Aboutirait à ceci:
Obsolète réponse précédente
Cela fonctionne dans la plupart des scénarios, mais certaines mises en forme amènent layoutSubviews
à s’appeler de manière récursive dans une boucle infinie, donc use avec prudence.
@IBDesignable
class LeftAlignedIconButton: UIButton {
override func layoutSubviews() {
super.layoutSubviews()
contentHorizontalAlignment = .left
let availableSpace = UIEdgeInsetsInsetRect(bounds, contentEdgeInsets)
let availableWidth = availableSpace.width - imageEdgeInsets.right - (imageView?.frame.width ?? 0) - (titleLabel?.frame.width ?? 0)
titleEdgeInsets = UIEdgeInsets(top: 0, left: availableWidth / 2, bottom: 0, right: 0)
}
}
Ce code ferait la même chose, mais en alignant l'icône sur le bord droit:
@IBDesignable
class RightAlignedIconButton: UIButton {
override func layoutSubviews() {
super.layoutSubviews()
semanticContentAttribute = .forceRightToLeft
contentHorizontalAlignment = .right
let availableSpace = UIEdgeInsetsInsetRect(bounds, contentEdgeInsets)
let availableWidth = availableSpace.width - imageEdgeInsets.left - (imageView?.frame.width ?? 0) - (titleLabel?.frame.width ?? 0)
titleEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: availableWidth / 2)
}
}
La bonne version de l'allocation utilise semanticContentAttribute
et nécessite donc iOS 9+.
De mon côté, je l'ai fait en utilisant UIEdgeInsetsMake dont le coin gauche est calculé pour le rendre au centre. Je ne suis pas sûr qu'il y ait quelque chose de vraiment qui puisse aligner le texte au centre mais cela fonctionne pour moi. Assurez-vous que vous réglez le coin gauche à la position souhaitée en calculant la largeur. par exemple. UIEdgeInsetsMake(0.0f, 42.0f, 0.0f, 0.0f)
UIButton *scanBarCodeButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
scanBarCodeButton.frame = CGRectMake(center, 10.0f, fieldWidth, 40.0f);
[scanBarCodeButton setImage:[UIImage imageNamed:@"BarCodeIcon.png"] forState:UIControlStateNormal];
[scanBarCodeButton setTitle:@"Scan the Barcode" forState:UIControlStateNormal];
scanBarCodeButton.titleEdgeInsets = UIEdgeInsetsMake(0.0f, 42.0f, 0.0f, 0.0f);
[scanBarCodeButton setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft];
[scanBarCodeButton addTarget:self action:@selector(scanBarCode:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:scanBarCodeButton];
La sortie ressemble à,
texte centré avec l'image http://i43.tinypic.com/33mbxxi.png
En Swift :
var scanBarCodeButton: UIButton = UIButton(type: .roundedRect)
scanBarCodeButton.frame = CGRectMake(center, 10.0, fieldWidth, 40.0)
scanBarCodeButton.setImage(UIImage(named: "BarCodeIcon.png"), for: UIControlStateNormal)
scanBarCodeButton.setTitle("Scan the Barcode", for: UIControlStateNormal)
scanBarCodeButton.titleEdgeInsets = UIEdgeInsetsMake(0.0, 42.0, 0.0, 0.0)
scanBarCodeButton.contentHorizontalAlignment = .left
scanBarCodeButton.addTarget(self, action: "scanBarCode:", for: UIControlEventTouchUpInside)
self.view.addSubview(scanBarCodeButton)
Créez votre bouton et définissez l'alignement du texte au centre, puis ajoutez:
UIImage *image = [UIImage imageNamed:@"..."];
CGSize imageSize = image.size;
CGFloat offsetY = floor((self.layer.bounds.size.height - imageSize.height) / 2.0);
CALayer *imageLayer = [CALayer layer];
imageLayer.contents = (__bridge id) image.CGImage;
imageLayer.contentsGravity = kCAGravityBottom;
imageLayer.contentsScale = [UIScreen mainScreen].scale;
imageLayer.frame = CGRectMake(offsetY, offsetY, imageSize.width, imageSize.height);
[self.layer addSublayer:imageLayer];
Comme je le pense, la bonne solution doit être utile pour tout texte, sans valeurs codées en dur pour les incrustations (il s'agit de la solution fournie par toytoy). J'utilise le code similaire à ceci:
NSString *sometitle = @"blabla button title";
NSString *someimage = @"blablaimage";
UIImage *image = [[UIImage imageNamed:someimage];
int buttonWidth = A;
int buttonHeight = B;
int imageWidth =image.size.width;
int imageHeight = image.size.height;
int titleWidth = buttonWidth - imageWidth;
// create button and set image and title
buttonView = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, buttonWidth, buttonHeight)];
[buttonView setImage:image forState:UIControlStateNormal];
[buttonView setTitle:sometitle forState:UIControlStateNormal];
// make button all content to be left aligned
[buttonView setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft];
// set title font
[buttonView.titleLabel setFont:[UIFont fontWithName:@"HelveticaNeue" size:14]];
// calculate font text width with selected font
CGSize stringBoundingBox = [number sizeWithFont:[buttonView.titleLabel font]];
// make title inset with some value from left
// it place the title right on the center of space for the title
int titleLeft = (titleWidth - stringBoundingBox.width) / 2;
[buttonView setTitleEdgeInsets:UIEdgeInsetsMake(0, titleLeft, 0, 0)];
Après la chaîne avec stringBoundingBox init, j'ajoute également certaines chaînes comme ceci:
if (stringBoundingBox.width > titleWidth)
{
[_backgroundView.titleLabel setFont:[UIFont fontWithName:@"HelveticaNeue" size:13]];
stringBoundingBox = [number sizeWithFont:[_backgroundView.titleLabel font]];
}
if (stringBoundingBox.width > titleWidth)
{
[_backgroundView.titleLabel setFont:[UIFont fontWithName:@"HelveticaNeue" size:12]];
stringBoundingBox = [number sizeWithFont:[_backgroundView.titleLabel font]];
}
cela me permet de définir des titres plus longs que l'espace disponible, en sélectionnant des polices plus petites. Je fais cela à cause d'une autre façon pour cela:
[buttonView.titleLabel setAdjustsFontSizeToFitWidth:YES];
fonctionne pas très bien, on dirait qu'il faut la taille de la police pour 3-4 points plus petit à la fois, de sorte que certaines lignes pas si longues deviennent trop petites, que cela doit être.
Ce code nous permet de placer n'importe quel texte dans l'espace de titre du bouton exactement au centre.
Pour Swift 4.0, voici une extension qui fonctionne.
extension UIButton {
func leftImage(image: UIImage, renderMode: UIImageRenderingMode) {
self.setImage(image.withRenderingMode(renderMode), for: .normal)
self.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: image.size.width / 2)
self.contentHorizontalAlignment = .left
self.imageView?.contentMode = .scaleAspectFit
}
func rightImage(image: UIImage, renderMode: UIImageRenderingMode){
self.setImage(image.withRenderingMode(renderMode), for: .normal)
self.imageEdgeInsets = UIEdgeInsets(top: 0, left:image.size.width / 2, bottom: 0, right: 0)
self.contentHorizontalAlignment = .right
self.imageView?.contentMode = .scaleAspectFit
}
}
Usage:
myButton.rightImage(image: UIImage(named: "image_name")!, renderMode: .alwaysOriginal)
myButton.leftImage(image: UIImage(named: "image_name")!, renderMode: .alwaysOriginal)
renderMode
peut être .alwaysTemplate
ou .alwaysOriginal
. De plus, myButton
devrait être un custom
type UIButton
.
leftImage
et rightImage
de cette extension peuvent également être utilisés dans UIButton
dans UIBarButtonItem
pour UINavigationBar
(Remarque: à partir de iOS 11, la barre de navigation suit l'autolayout. Vous devrez donc ajouter des contraintes de largeur/hauteur à UIBarButtonItem
. Pour une utilisation sur la barre de navigation, veillez à respecter les tailles d'image recommandées par Apple @ 2x et @ 3x (c'est-à-dire 50x50, 75x75) et une meilleure accessibilité sur iPhone 6, 7, 8, 6, 7, 8, 8, les versions Plus et iPhone. x la largeur et la hauteur de la variable UIBarButton
pourraient être hauteur - 25 et largeur - 55 (ou ce que votre application requiert, ces chiffres sont quelques chiffres de base qui devraient fonctionner dans la plupart des cas).
UPDATE: Dans Swift 4.2, UIImageRenderingMode
a été renommé en UIImage.RenderingMode
extension UIButton {
func leftImage(image: UIImage, renderMode: UIImage.RenderingMode) {
self.setImage(image.withRenderingMode(renderMode), for: .normal)
self.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: image.size.width / 2)
self.contentHorizontalAlignment = .left
self.imageView?.contentMode = .scaleAspectFit
}
func rightImage(image: UIImage, renderMode: UIImage.RenderingMode){
self.setImage(image.withRenderingMode(renderMode), for: .normal)
self.imageEdgeInsets = UIEdgeInsets(top: 0, left:image.size.width / 2, bottom: 0, right: 0)
self.contentHorizontalAlignment = .right
self.imageView?.contentMode = .scaleAspectFit
}
}
[self.button setImage:[UIImage imageNamed:@"image.png"] forState:UIControlStateNormal];
[self.button setTitleEdgeInsets:UIEdgeInsetsMake(0.0, self.button.center.x/2 , 0.0, 0.0)];
[self.button setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft];
Faites-moi savoir si cela ne fonctionne pas.
J'ai écrit une extension UIButton.
extension UIButton {
/// Add image on left view
func leftImage(image: UIImage) {
self.setImage(image, for: .normal)
self.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: image.size.width)
}
}
Et vous pourriez utiliser comme ceci:
yourButton.leftImage(image: yourImage)
Voila!
Cela fonctionne bien pour moi, pour plusieurs boutons, avec une largeur d'image et une longueur de titre différentes:
Sous-classe UIButton
et ajoutez la méthode suivante:
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)
}
}
Je sais que cette réponse est un peu tardive ... Mais j'ai une solution très simple pour ceux qui veulent ajouter une image, en utilisant UIImageView, dans la partie gauche d'un bouton UIB avec un texte centré. Tous par programmation
class RandomVC: UIViewController{
var imageDemo: UIImageView = {
let img = UIImageView()
img.translatesAutoresizingMaskIntoConstraints = false
img.image = UIImage(named: "someImgFromAssets")
return img
}()
lazy var someButton: UIButton = { //lazy var: so button can have access to self class
let button = UIButton(type: .system)
button.setTitle("This is your title", for: UIControlState.normal)
button.translatesAutoresizingMaskIntoConstraints = false
button.setTitleColor(UIColor.white, for: UIControlState.normal)
button.addTarget(self, action: #selector(handleButtonClick), for: .touchUpInside) //make sure you write function "handleButtonClick" inside your class
button.titleLabel?.textAlignment = .center
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubView(someButton)
someButton.addSubview(imageDemo)
imageDemo.centerYAnchor.constraint(equalTo: someButton.centerYAnchor).isActive = true
imageDemo.leftAnchor.constraint(equalTo: someButton.leftAnchor, constant: 10).isActive = true
imageDemo.heightAnchor.constraint(equalToConstant: 25).isActive = true
imageDemo.widthAnchor.constraint(equalToConstant: 25).isActive = true
}
}
Je vois beaucoup de solutions ici qui mettent l’accent sur le réglage de l’icône à gauche. Je pense qu'il est beaucoup plus facile d'ajouter simplement un UIImageView, d'aligner les côtés gauche du bouton et de l'image et de les centrer ensemble. Ensuite, vous pouvez jouer un peu avec le décalage pour le rendre agréable.
Aucun code, tout dans Interface Builder.
1) button.frame = self.view.bounds;
2) setImageEdgeInsets
avec des valeurs négatives, lorsque votre bouton remplit l'écran, est de la folie. Reconsidérer ce que vous essayez de faire ici?
3) UITextAlignmentCenter
est maintenant NSTextAlignmentCenter
4) button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
J'ai écrit une extension UIButton dans Swift -
extension UIButton {
func setLeftImage(imageName:String, padding:CGFloat) {
//Set left image
let image = UIImage(named: imageName)
self.setImage(image, forState: .Normal)
//Calculate and set image inset to keep it left aligned
let imageWidth = image?.size.width
let textWidth = self.titleLabel?.intrinsicContentSize().width
let buttonWidth = CGRectGetWidth(self.bounds)
let padding:CGFloat = 30.0
let rightInset = buttonWidth - imageWidth! - textWidth! - padding
self.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: rightInset)
}
}
Je voudrais styler le texte de mon bouton comme je le veux, le garder dans l'alignement du centre ..__ puis appeler cette méthode sur mon bouton comme -
myButton.setLeftImage("image_name", 30.0)
Cela aurait pour effet d'aligner à gauche mon image avec un remplissage du bord gauche.
ce code permet d'aligner à gauche l'image du bouton et le titre se déplace au centre du bouton. b est le bouton :)
b.contentHorizontalAlignment = .Left
let left = (b.frameWidth() - b.titleLabel!.frameWidth()) / 2 - CGRectGetMaxX(b.imageView!.frame)
b.titleEdgeInsets = UIEdgeInsetsMake(0, left, 0, 0)
Vous pouvez utiliser le code ci-dessous pour aligner à gauche l'image sur UIButton: -
Étape 1:
//create your UIButton
UIButton *post_bNeeds_BTN= [UIButton buttonWithType:UIButtonTypeRoundedRect];
post_bNeeds_BTN.frame= CGRectMake(160 ,5 ,150 ,40);
[post_bNeeds_BTN addTarget:self action:@selector(post_Buying_Needs_BTN_Pressed:) forControlEvents:UIControlEventTouchUpInside];
[post_bNeeds_BTN setBackgroundColor:[UIColor colorWithRed:243/255.0 green:131/255.0 blue:26/255.0 alpha:1.0f]];//230
[self.view addSubview:post_bNeeds_BTN];
post_bNeeds_BTN.autoresizingMask= UIViewAutoresizingFlexibleWidth;
Étape 2:
//Add UIImageView on right side the button
UIImageView *bNeedsIVw= [[UIImageView alloc] initWithFrame:CGRectMake(5,5,30,30)];
bNeedsIVw.image= [UIImage imageNamed:@"postRequir_30.png"];
bNeedsIVw.image= [bNeedsIVw.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
bNeedsIVw.tintColor= [UIColor whiteColor];
[post_bNeeds_BTN addSubview:bNeedsIVw];
Étape 3:
//also set UILable on UIButton
UILabel *bNeedsLbl= [[UILabel alloc] initWithFrame:CGRectMake(40 ,0 ,post_Prod_BTN.frame.size.width-40 ,post_Prod_BTN.frame.size.height)];
bNeedsLbl.text= @"Requirements";
bNeedsLbl.font= [UIFont systemFontOfSize:16];
bNeedsLbl.textColor= [UIColor whiteColor];
bNeedsLbl.textAlignment= NSTextAlignmentLeft;
[post_bNeeds_BTN addSubview:bNeedsLbl];
Étape 4:
-(void)post_Buying_Needs_BTN_Pressed:(id)sender{
//write your code action here,,
}
merci,
J'ai essayé presque toutes les solutions ci-dessus et aucune d'entre elles n'a fonctionné comme prévu (j'avais deux boutons, chacun avec un titre différent et une largeur d'image différente). J'ai donc écrit ma propre extension pour UIButton, qui fonctionne parfaitement avec différentes largeurs d'image et différents titres.
extension UIButton {
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)
}
}
Usage: myButton.moveImageLeftTextCenter()
Une astuce consiste à:
titleRectForContentRect
pour que le bouton titleLabel
soit frame
égal à ses limitestitleLabel
's textAlignment
sur .Center
remplace imageRectForContentRect
pour spécifier le Origin.x
de la imageView
du bouton
import UIKit
class ButtonWithLeftAlignedImageAndCenteredText: UIButton {
override init(frame: CGRect) {
super.init(frame: frame)
titleLabel?.textAlignment = .Center
}
override func imageRectForContentRect(contentRect: CGRect) -> CGRect {
var imageFrame = super.imageRectForContentRect(contentRect)
imageFrame.Origin.x = 20 //offset from left Edge
return imageFrame
}
override func titleRectForContentRect(contentRect:CGRect) -> CGRect {
var titleFrame = super.titleRectForContentRect(contentRect)
titleFrame = self.bounds
return titleFrame
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
L'extension suivante fonctionne pour moi dans Swift 4.2
func leftImage(image: UIImage, padding: CGFloat, renderMode: UIImage.RenderingMode) {
self.setImage(image.withRenderingMode(renderMode), for: .normal)
contentHorizontalAlignment = .left
let availableSpace = bounds.inset(by: contentEdgeInsets)
let availableWidth = availableSpace.width - imageEdgeInsets.right - (imageView?.frame.width ?? 0) - (titleLabel?.frame.width ?? 0)
titleEdgeInsets = UIEdgeInsets(top: 0, left: availableWidth / 2, bottom: 0, right: 0)
imageEdgeInsets = UIEdgeInsets(top: 0, left: padding, bottom: 0, right: 0)
}
func rightImage(image: UIImage, padding: CGFloat, renderMode: UIImage.RenderingMode){
self.setImage(image.withRenderingMode(renderMode), for: .normal)
semanticContentAttribute = .forceRightToLeft
contentHorizontalAlignment = .right
let availableSpace = bounds.inset(by: contentEdgeInsets)
let availableWidth = availableSpace.width - imageEdgeInsets.left - (imageView?.frame.width ?? 0) - (titleLabel?.frame.width ?? 0)
titleEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: availableWidth / 2)
imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: padding)
}
J'ai essayé la plupart des réponses sans succès. J'obtenais une image bleue la plupart du temps, ou le titre n'était pas au centre. Utilisé le code de quelques-unes des réponses et écrit cette extension, fonctionne comme un charme.
Swift 4.2:
import UIKit
extension UIButton {
func moveImageLeftTextCenter(image : UIImage, imagePadding: CGFloat, renderingMode: UIImage.RenderingMode){
self.setImage(image.withRenderingMode(renderingMode), for: .normal)
guard let imageViewWidth = self.imageView?.frame.width else{return}
guard let titleLabelWidth = self.titleLabel?.intrinsicContentSize.width else{return}
self.contentHorizontalAlignment = .left
let imageLeft = imagePadding - imageViewWidth / 2
let titleLeft = (bounds.width - titleLabelWidth) / 2 - imageViewWidth
imageEdgeInsets = UIEdgeInsets(top: 0.0, left: imageLeft, bottom: 0.0, right: 0.0)
titleEdgeInsets = UIEdgeInsets(top: 0.0, left: titleLeft , bottom: 0.0, right: 0.0)
}
}
J'espère que ça aide pour certains!
Cette solution peut être appliquée à l'aide d'une extension. Pas besoin de sous-classe.
Attention: ceci doit être appelé à chaque mise à jour du texte/image.
let width = frame.width
guard let imageWidth = imageView?.frame.width, let labelWidth = titleLabel?.frame.width else {
return
}
titleEdgeInsets = UIEdgeInsets(top: 0, left: (width - labelWidth)/2.0 - imageWidth, bottom: 0, right: 0)