Search code examples
swiftuibuttoncalayeruibackgroundcolor

UIButton visible background


Can't find any useful information about custom view field on UIButton I need to create a subclass of UIButton with big button frame and small visible part of it Also I need to animate background on button tap so I need to set button background as a backgroundImage

Here is my code:

public final class BigSmallButton: UIButton {
...

public override var buttonType: UIButton.ButtonType {
    return .custom
}

override init(frame: CGRect) {
    super.init(frame: frame)

    NSLayoutConstraint(item: self,
                       attribute: .height,
                       relatedBy: .equal,
                       toItem: nil,
                       attribute: .notAnAttribute,
                       multiplier: 1.0,
                       constant: 44).isActive = true

    let imageSize = CGSize(width: 24, height: 24)
    let backgroundImage = UIImage.image(with: Constants.buttonBackgroundColor, size: imageSize)
    setBackgroundImage(backgroundImage, for: .normal)

    layer.cornerRadius = Constants.buttonIconSize.height / 2.0
    layer.masksToBounds = true
    
    layer.frame = CGRect(x: 0, y: 0, width: bounds.width, height: imageSize.height)
}

And then add to NavigationController

let bigSmallButton = BigSmallButton(frame: .zero)
navigationItem.rightBarButtonItem = UIBarButtonItem(customView: bigSmallButton)

It works but my button height becomes equal to 24.0 not 44.0

I need answer about is it possible to make such button?

And if it's possible then what I’m doing wrong?


Solution

  • The only way that I found is overriding button function point(inside point: CGPoint, with event: UIEvent?)

    Something like this:

    let hitFrame: CGRect
    
        override init(frame: CGRect) {
            super.init(frame: frame)
    
            hitFrame = CGRect(x: frame.minX, y: frame.minY - 10.0, width: frame.width, height: frame.height + 10.0)
        }
    
        override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
            return hitFrame.contains(point)
        }