swiftbuttonuikituibuttontap

Why is my UIButton not completely tappable (UIKit in Swift)


This is my button:

import UIKit

class PassButton: UIButton {

    var videoVC: VideoGameVC?
    
    required init(isEnabled: Bool = false) {
        super.init(frame: .zero)
        
        self.isEnabled = true
        self.addTarget(self, action: #selector(pressed(_:)), for: .touchUpInside)

        let imageViewBackground = UIImageView(frame: CGRect(x:0, y:0, width: 70, height: 80))
        imageViewBackground.image = UIImage(named: "pass_button")
        imageViewBackground.contentMode = UIView.ContentMode.scaleAspectFill
        addSubview(imageViewBackground)
        sendSubviewToBack(imageViewBackground)
        
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    @objc func pressed(_ sender: UIButton) {
        print("presovan")
    }
   
    
}

and this is how I add it to another view controller:

func configPassButton() {
        passButton = PassButton()
        guard let passButton = passButton else { return }
        view.addSubview(passButton)
        passButton.translatesAutoresizingMaskIntoConstraints = false
        passButton.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20).isActive = true
        passButton.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor, constant: 20).isActive = true
        
        
    }

it is displayed, as I want it to be, but the area which is tappable is so tiny. Only top left corner of it is tappable, and a very small one (lik, 10% of the whole surface). How can I fix so whole are is tappable?


Solution

  • Assuming you have a 70:80 ratio image. such as this:

    enter image description here

    Your code displays it like this:

    enter image description here

    but, as you're aware, you can only tap the upper-left.

    If we add a 2-point red border to the button:

    passButton.layer.borderColor = UIColor.red.cgColor
    passButton.layer.borderWidth = 2
    

    it looks like this:

    enter image description here

    the button frame is only 30 x 34 ... and the 70 x 80 imageView is extending outside the bounds of the button. So, only the actual button frame can be tapped.

    If you give the button width and height constraints:

    passButton.widthAnchor.constraint(equalToConstant: 70.0).isActive = true
    passButton.heightAnchor.constraint(equalToConstant: 80.0).isActive = true
    

    then we see this:

    enter image description here

    and the entire button can be tapped.

    Adding a UIImageView as a subview is a terrible approach though.

    Much more appropriate is to set the background image property:

    // safely handle optional
    if let img = UIImage(named: "pass_button") {
        setBackgroundImage(img, for: [])
    }
    

    Again, we also need to set the width and height constraints, but now we are using a "standard" button instead of a subclass with added subviews:

    let passButton = UIButton()
    
    passButton.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(passButton)
    
    NSLayoutConstraint.activate([
        passButton.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20.0),
        passButton.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 20.0),
        passButton.widthAnchor.constraint(equalToConstant: 70.0),
        passButton.heightAnchor.constraint(equalToConstant: 80.0),
    ])
    
    if let img = UIImage(named: "pass_button") {
        passButton.setBackgroundImage(img, for: [])
    }
    

    If your image is not the same aspect-ratio as your button, there's a little more work to do... but, using your original code, you'd have the same problem - so I assume you're using a 70:80 aspect image to begin with.