28

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?

halfer
  • 19,824
  • 17
  • 99
  • 186
Ariel
  • 2,471
  • 1
  • 26
  • 43

6 Answers6

37

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
halfer
  • 19,824
  • 17
  • 99
  • 186
Ariel
  • 2,471
  • 1
  • 26
  • 43
17

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

Scott Zhu
  • 8,341
  • 6
  • 31
  • 38
14
  • 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

7

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

Justin Vallely
  • 5,932
  • 3
  • 30
  • 44
  • This actually worked for me though I changed the image insets to get my image center within the button. I had to set "left" to 11. I haven't properly sent constraints though, and maybe that's why the above answers didn't work and this one did. Thank you so much! – Moondra Aug 27 '18 at 05:39
3

Set the button's content mode to Center:

shiftButton.contentMode = .Center
Ariel
  • 2,471
  • 1
  • 26
  • 43
Viktor Simkó
  • 2,607
  • 16
  • 22
  • I've already tried it. This does not seem to work in this particular case. Maybe, its because the image is larger that the size of frame. – Ariel Aug 01 '16 at 11:22
  • When the button width starts to stretch, the image seems to stretch as well. And, this behaviour is not desired at all. – Ariel Aug 02 '16 at 08:05
  • According to the docs `.Center` shouldn't stretch at all: "The option to center the content in the view’s bounds, keeping the proportions the same." – Viktor Simkó Aug 02 '16 at 08:21
  • 1
    as of iOS 11 this will only work if you have height and width constraints on the Button. – Anjan Biswas Apr 10 '18 at 05:59
3

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
    }()
Zhou Haibo
  • 1,681
  • 1
  • 12
  • 32