skip to Main Content

I am using this code to create a button with an image. And I want the image size to be the same as the button size. I am using this code for that:

func buttonImage() {
   var configuration = UIButton.Configuration.plain()
   configuration.image = UIImage(named: "someImage")!
   configuration.baseBackgroundColor = .red
   configuration.contentInsets = .zero
        
    let button = UIButton(configuration: configuration)
    button.backgroundColor = .red
    button.translatesAutoresizingMaskIntoConstraints = false
        
    view.addSubview(button)
        
    button.widthAnchor.constraint(equalToConstant: 300).isActive = true
    button.heightAnchor.constraint(equalToConstant: 300).isActive = true
    button.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    button.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
}

but I have this result:

enter image description here

All works fine if I use single scale with 135×135 without @3x suffix instead of individual scales with 3 images 45×45, 90×90, 135×135 in my assets.

How to fix it with using configuration?

3

Answers


  1. This is not a problem with your configuration. It’s a problem with how you have setup your asset. If your asset is 45pt, UIButton will not render it bigger than 45pt even if your button is 300pt. If you want the icon to truly scale to any size, as you already discovered, you will need to use single scale. Single scale means that you are providing a vector asset so system knows it can scale the image to any size without distortion.

    TLDR: Stop using pngs and go with an svg or PDF and use Single Scale.

    Login or Signup to reply.
  2. A UIButton using UIButton.Configuration does not scale the image… it uses the image at its point size.

    If we have:

    and we run this code:

    guard let imgA = UIImage(named: "someImage"),
          let imgB = UIImage(named: "someImageU")
    else { fatalError() }
    
    print("imgA size:", imgA.size)
    print("imgB size:", imgB.size)
    

    we will get this output:

    imgA size: (45.0, 45.0)
    imgB size: (135.0, 135.0)
    

    Whether the device has a screen scale of 1, 2 or 3, the point size will always be the same, and UIKit will load the corresponding @1, @2 or @3 image.

    If you are using a png (or other format) image in your Asset Catalog, you can either save multiple sizes and do something like this:

    var btnImage: UIImage!
    if true {
        if UIScreen.main.scale == 1 {
            btnImage = UIImage(named: "someImage45x45")
        } else if UIScreen.main.scale == 2 {
            btnImage = UIImage(named: "someImage90x90")
        } else {
            btnImage = UIImage(named: "someImage135x135")
        }
    }
    

    Or, scale the UIImage on-the-fly before assigning it as the configuration’s .image property…

    Or, create a UIButton without using UIButton.Configuration

    Login or Signup to reply.
  3. UIButton always take some padding for their content like text and image , so For ours scenario it is better we take UIImage on the top of the UIButton. By this method we can also adjust image more flexible.

    As we change the size of button it automatically adjust size of image also.

    func buttonImage() {
               var configuration = UIButton.Configuration.plain()
               configuration.baseBackgroundColor = .red
               configuration.contentInsets = .zero
    
               let button = UIButton(configuration: configuration)
               button.translatesAutoresizingMaskIntoConstraints = false
               button.backgroundColor = .gray
    
               // Create the UIImageView
               let imageView = UIImageView()
               imageView.image = UIImage(named: "valentine-heart-icon-6")
               imageView.contentMode = .scaleAspectFill
               imageView.translatesAutoresizingMaskIntoConstraints = false
    
               view.addSubview(button)
               view.addSubview(imageView)
    
               // Set constraints for the button
               NSLayoutConstraint.activate([
                   button.widthAnchor.constraint(equalToConstant: 100),
                   button.heightAnchor.constraint(equalToConstant: 100),
                   button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
                   button.centerYAnchor.constraint(equalTo: view.centerYAnchor)
               ])
    
               // Set constraints for the imageView to position it on top of the button
               NSLayoutConstraint.activate([
                   imageView.topAnchor.constraint(equalTo: button.topAnchor),
                   imageView.leadingAnchor.constraint(equalTo: button.leadingAnchor),
                   imageView.trailingAnchor.constraint(equalTo: button.trailingAnchor),
                   imageView.bottomAnchor.constraint(equalTo: button.bottomAnchor)
               ])
           }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search