Ariel
Ariel

Reputation: 2742

How to center an image inside an UIButton without stretching in both direction in Swift?

I am making a custom keyboard and I need to centre the image of the shift icon inside the shift button. The image is 100px x 100px.

However, the button frame in portrait is 36pt x 38pt, and in landscape, it is 68pt x 32pt. I have tried using button image inset property to centre the image. However, it does not does so.

I tried myself and set the image edge insets to (25,25,25,25), the image centres in both sizes. However, the icon becomes too small to see.

shiftButton.setImage(UIImage(named: "shift"), forState: .Normal)

shiftButton.imageEdgeInsets = UIEdgeInsetsMake(0,0,0,0)

I am making the button programatically. And, I need the button to scale maintaining its aspect ratio i.e. 1:1. Its maximum width or height is always tied to the button's height itself. The image width/height should be maximum of button's height. And, it should not stretch in any way to distort the icon. However, the button itself can stretch.

I need the image to scale according to button frame but maintain its aspect ratio. And, it can down scale or up scale, but should always maintain the 1:1 aspect ratio.

Any suggestions for solving this problem?

Upvotes: 28

Views: 33664

Answers (6)

Zhou Haibo
Zhou Haibo

Reputation: 2068

To work on UIButton with image is sort of tricky things. I think below two lines could solve your problem.

And there is a good post Aligning text and image on UIButton

// Keep button's image to its original ratio.
button.imageView?.contentMode = .scaleAspectFit
// Give button image a little space from all the four edges.
button.imageEdgeInsets = UIEdgeInsets(top: 3, left: 3, bottom: 3, right: 3)

A button in my project

    lazy var downloadButton: TransitionButton = {
        let button = TransitionButton()
        button.translatesAutoresizingMaskIntoConstraints = false
        let config = UIImage.SymbolConfiguration(pointSize: 26, weight: .bold, scale: .default)
        let image = UIImage(systemName: "arrow.down", withConfiguration: config)?.withTintColor(.white, renderingMode: .alwaysOriginal)
        button.setImage(image, for: .normal)
        button.imageView?.contentMode = .scaleAspectFit
        button.imageEdgeInsets = UIEdgeInsets(top: 3, left: 3, bottom: 3, right: 3)
        button.backgroundColor = .systemPink
        button.layer.cornerRadius = 12
        button.addTarget(self, action: #selector(downloadButtonTapped(_:)), for: .touchUpInside)
        button.spinnerColor = .white
        return button
    }()

Upvotes: 3

Scott Zhu
Scott Zhu

Reputation: 8441

If you're using storyboard, double-check that you don't have anything set for the button title.

Upvotes: 19

Prateep Gedupudi
Prateep Gedupudi

Reputation: 399

  • Add User Defined Runtime Attributes to your button.

In the screen shot below value 1 is equal to scaleAspectFit

imageView.ContentMode = scaleAspectFit

enter image description here enter image description here

Upvotes: 15

Ariel
Ariel

Reputation: 2742

Finally a solution came through. You must set the content mode for the image inside the UIButton.

The solution is to update the contentMode of the Image when you are using a foreground image inside a button along with the contentMode of the UIButton.

shiftButton.contentMode = .Center
shiftButton.imageView?.contentMode = .ScaleAspectFit

Upvotes: 37

Justin Vallely
Justin Vallely

Reputation: 6089

I was able to center the image by setting the content insets to 0 using the size inspector on the storyboard:

enter image description here

Upvotes: 8

Viktor Simkó
Viktor Simkó

Reputation: 2627

Set the button's content mode to Center:

shiftButton.contentMode = .Center

Upvotes: 3

Related Questions