29

There are plenty of threads about aligning a button image according to the title text, but I can't find anything about just aligning the image to the right side of the button.

This has no effect:

button.imageEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 50);

How can one right-align the image for a button? Can it be done in the Storyboard?

Krunal
  • 73,857
  • 44
  • 240
  • 251
soleil
  • 11,487
  • 31
  • 105
  • 176
  • possible duplicate of [iPhone UIButton - image position](http://stackoverflow.com/questions/2515998/iphone-uibutton-image-position) – Fonix Sep 03 '15 at 02:03
  • if you are targeting iOS 9 you can [do it like this](http://stackoverflow.com/a/32014907/1219956) – Fonix Sep 03 '15 at 02:04
  • It's not a duplicate. I don't care about the title text. I just want the image to be right aligned to whatever the frame of the button is. – soleil Sep 03 '15 at 02:12
  • @Fonix I need to support iOS 8. – soleil Sep 03 '15 at 02:13

16 Answers16

63

Semantic: Force Right-to-Left on View works for me enter image description here

Gilad Brunfman
  • 3,306
  • 1
  • 28
  • 28
27

I found a tricky way Update the constrains for the UIImageView of the Button

try this

button.imageView?.trailingAnchor.constraint(equalTo: button.trailingAnchor, constant: -8.0).isActive = true
button.imageView?.centerYAnchor.constraint(equalTo: button.centerYAnchor, constant: 0.0).isActive = true

but don't forget to add this to make the constrains effective

button.translatesAutoresizingMaskIntoConstraints = false
button.imageView?.translatesAutoresizingMaskIntoConstraints = false
Simon K. Gerges
  • 2,997
  • 32
  • 34
  • EZ. Thanks. Tried checking if the imageView of the UIButton has already constraints but found none. This is the last option if you want your imageView to stick on a certain side of your button without being depended on the title. – Glenn Posadas Jun 20 '17 at 12:16
  • Nice idea simon – Marios Sep 26 '17 at 10:19
19

There are several different options to do it.

Use semanticContentAttribute

button.semanticContentAttribute = .forceRightToLeft

You can set semantic attribute from interface (storyboard) layout also.

enter image description here


or Use UIView containing UIButton and UIImage, as shown in this snapshot.

  • Set Image right side in UIView and disable user interaction, so user action/tap will be passed to button.
  • Add button with size same as UIView, in UIView, with transparent background color and covering Image.
  • Set content offset for button as shown in this snapshot.

enter image description here

This will make easy to handle button action, properties and customise image position & size according to your requirement. Try this.

Krunal
  • 73,857
  • 44
  • 240
  • 251
  • Is there a way to define a padding to complement the `semanticContentAttribute` property? Based on the text in my button, the image could be touching the text, or be far away from it. – agirault Oct 31 '19 at 13:28
17

Storyboard:

Attributes Tab > Ensure your Content Edge tab is selected for 'image':

1

Then you alter the 'Left' property not right, which is what your doing programatically. So in other words, your padding it n from the left

UIEdgeInsetsMake = TOP | LEFT | BOTTOM | RIGHT

Programmatically :

button.imageEdgeInsets = UIEdgeInsetsMake(0, 100, 0, 0);

Note: you might have to also alter your titles inset, depending on where it is in reference to your image

soulshined
  • 8,385
  • 5
  • 38
  • 73
  • Thanks for the suggestion. This indents the image from the left. In other words, with all 4 values at 0, the image is left-aligned. If I increase the "left" inset value, the image moves away from the left edge. This doesn't help because I need the image pinned to the right edge, so that no matter how wide the button stretches, it stays right-aligned. – soleil Sep 03 '15 at 03:03
  • @soleil right. As far as I know that can't be down with a system button, but what do I know really. I just used that because that's what you gave as an example as something you've tried. You are right, not a good workaround for various widths, but fine for static widths. – soulshined Sep 03 '15 at 03:07
  • Well actually. @soleil just make the left inset `self.button.frame.size.width - widthOfImage` or something. – soulshined Sep 03 '15 at 03:09
  • @soleil nope. Disregard. Wishful thinking. That will probably only work for left aligned content. Yours is most likely centered like everyone else. – soulshined Sep 03 '15 at 03:10
  • @soleil. Yeah try that. I'm bout to go to bed but try aligning the content to left in storyboard then set the left inset to the one mentioned above. Sounds right – soulshined Sep 03 '15 at 03:16
14

Try below code:

btn.contentHorizontalAlignment = .right
Dhaval H. Nena
  • 3,814
  • 1
  • 32
  • 47
  • It was down voted because the OP is asking how to have the image come after the text, that's what they mean by aligning the image to the right edge of the button. This only aligns the image and text towards the right, but it doesn't have the effect the OP wanted. If you look at the other answers you'll understand what they're trying to do – derickito May 13 '21 at 16:05
  • @derickito If you see this answer has helped many users here. Though it isn't 100% relevant at the same it isn't 100% useless. Kindly suggest changes instead of downvoting! – Dhaval H. Nena Sep 20 '21 at 15:35
  • While it is helpful and is something you could use, it’s out of place. Just because is a useful answer doesn’t mean it belongs in the answers of this question. People who are looking for an answer to the actual question will be misled thinking this will solve the issue when it won’t. Not sure if you understand that. There’s nothing I can suggest other than removing this answer. – derickito Sep 21 '21 at 16:06
  • We may sometime not be clear on our exact requirement OR may be asking for related help which the question may not clearly speak for, based on experiences I can clearly say that new users might not be able to ask for the clear requirement and this answer would have helped them. Otherwise no one would have upvoted this answer and would have commented for better answer or reported for misleading. – Dhaval H. Nena Sep 23 '21 at 14:32
  • I don't think you understand how StackOverflow works. Off topic answers are never valid. If you think this is an answer that would help people you should create it's own question and then put this answer there. Your answer doesn't help me fix the original problem. That's why you're getting downvoted. – derickito Sep 27 '21 at 15:32
13

Clean way to do this in Swift

button.semanticContentAttribute = .forceRightToLeft

Hope this helps

Md. Ibrahim Hassan
  • 5,074
  • 1
  • 20
  • 44
10

Simple way

Using extension to set image on the right side with custom offset

   extension UIButton {
    func addRightImage(image: UIImage, offset: CGFloat) {
        self.setImage(image, for: .normal)
        self.imageView?.translatesAutoresizingMaskIntoConstraints = false
        self.imageView?.centerYAnchor.constraint(equalTo: self.centerYAnchor, constant: 0.0).isActive = true
        self.imageView?.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -offset).isActive = true
    }
}
Musa almatri
  • 5,101
  • 1
  • 32
  • 31
  • Code did not work for me as is. Needed to add `self.imageView?.contentMode = .right` to prevent image from being stretched. – rmp Feb 10 '22 at 19:52
5

make it as default semantic i.e unspecified or force left to right

and in button.imageEdgeInsets set it as

UIEdgeInsets(top: 0, left: self.view.frame.size.width - (the image size + the alignment space ) , bottom: 0, right: 0)

this will make ensure that no matter what the view size is ,it will always align the image from right side of the button

Tharzeez
  • 1,126
  • 13
  • 15
4

It's working for me:

self.acceptButton.setImage(UIImage(named: image), for: UIControl.State.normal)
self.acceptButton.semanticContentAttribute = .forceRightToLeft
self.acceptButton.imageEdgeInsets = UIEdgeInsets(top: 0, left: 9, bottom: 0, right: 0)
1

Just like this:

btn.imageView?.translatesAutoresizingMaskIntoConstraints = false
btn.imageView?.centerYAnchor.constraint(equalTo: btn.centerYAnchor, constant: 0.0).isActive = true
btn.imageView?.trailingAnchor.constraint(equalTo: btn.trailingAnchor, constant: 0.0).isActive = true
btn.imageView?.contentMode = .right
Charly berthet
  • 1,073
  • 5
  • 15
  • 30
1

To align an image to right, the 'Semantic' option seems the best, 'Force Right-to-Left'. Furthermore, I want to add one more thing. You can keep the shape of the button's image by this option. User Defined Runtime Attributes

winner.ktw
  • 398
  • 2
  • 11
1

iOS 15: imageEdgeInsets and titleEdgeInsets are deprecated, and also ignored, we have to adjust by our own.

For example, I want to set the title at the beginning of the button and image at the end.

extension UIButton {
    func adjust() {
        guard let imageView = self.imageView else { return }
        imageView.translatesAutoresizingMaskIntoConstraints = false
        imageView.centerYAnchor.constraint(equalTo: self.centerYAnchor, constant: 0.0).isActive = true
        imageView.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: 0).isActive = true
        
        guard let titleLabel = self.titleLabel else { return }
        titleLabel.translatesAutoresizingMaskIntoConstraints = false
        titleLabel.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 0).isActive = true
        titleLabel.centerYAnchor.constraint(equalTo: self.centerYAnchor, constant: 0.0).isActive = true
    }
}

You can also put the code in layoutSubviews if subclass UIButton.

BollMose
  • 2,326
  • 4
  • 29
  • 35
Malik Kulsoom
  • 116
  • 2
  • 4
0

This worked for me by setting:

button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentRight;

Then for the inner image I set the right inset to 0.

button.imageEdgeInsets = UIEdgeInsetsMake(10.0, 10.0, 10.0, 0);
coletrain
  • 2,759
  • 32
  • 42
0

SWIFT 5

button.imageEdgeInsets = UIEdgeInsets(top: 0, left: (bounds.width - 16), bottom: 0, right: 0)
Bandyliuk
  • 191
  • 1
  • 10
0

Using UIButton Extension for image to right side

extension UIButton {
    func imageToRight() {
        transform = CGAffineTransform(scaleX: -1.0, y: 1.0)
        titleLabel?.transform = CGAffineTransform(scaleX: -1.0, y: 1.0)
        imageView?.transform = CGAffineTransform(scaleX: -1.0, y: 1.0)
    }
}

How to Use

yourButton.imageToRight()
Solayman Rana
  • 203
  • 3
  • 12
0

In iOS 15.0 you can simply use the new configuration API to specify the image placement, in this case: trailing. If you need to support earlier versions, another way of doing this could be by appending an NSTextAttachment (available since iOS 7.0) to an NSMutableAttributedString and use that as the button's title.

It is a bad idea to use the semantic content attribute for this, as suggested in other responses, and force it to right-to-left. That API is not meant for that use-case and can have unintended consequences. In this case, it breaks accessibility, especially navigation using VoiceOver. The reason is that if you are swiping to the right to get to the next element in the screen, and that element is forced to be right-to-left, VoiceOver will also reverse and if you swipe right again it will go to the previous element instead of the next one. If you swipe right again, you are back to the right-to-left element. And so on, and so on. The user gets stuck in a focus trap and it can be very confusing.

So the code could look something like this:

if #available(iOS 15.0, *) {
    var configuration = UIButton.Configuration.plain()
    let image = UIImage(systemName: "applelogo")
    configuration.image = image
    configuration.imagePadding = 8.0
    configuration.imagePlacement = .trailing
    button.configuration = configuration
    button.setTitle("Apple", for: .normal)
} else {
    let buttonTitle = "Apple"
    let titleAttributedString = NSMutableAttributedString(string: buttonTitle + " ")
    let textAttachment = NSTextAttachment(image: UIImage(systemName: "applelogo")!)
    let textAttachmentAttributedString = NSAttributedString(attachment: textAttachment)
    titleAttributedString.append(textAttachmentAttributedString)
    button.setAttributedTitle(titleAttributedString, for: .normal)
    // When using NSTextAttachment, configure an accessibility label manually either
    // replacing it for something meaningful or removing the attachment from it
    // (whatever makes sense), otherwise, VoiceOver will announce the name of the
    // SF symbol or "Atachement.png, File" when using an image
    button.accessibilityLabel = buttonTitle
}
dadederk
  • 276
  • 2
  • 11