简体   繁体   中英

Subclassing UIButton and make it IBDesignable

I have an app that uses custom buttons, the buttons should simply have a background image. Instead of adding the background image to all buttons, I'd rather have a UIButton subclass. It would be great if the custom button also rendered properly in Interface Builder. This is my attempt so far:

import UIKit

@IBDesignable
class STACPatientButton: UIButton {

    override init(frame: CGRect) {
        NSLog("initWithFrame");
        super.init(frame: frame)
        _setup()
    }

    required init(coder: NSCoder) {
        NSLog("initWithCoder");
        super.init(coder: coder)
        _setup()
    }

    override func prepareForInterfaceBuilder() {
        _setup()
    }

    private func _setup() {
        if let image = UIImage(named:"patientButton.png") {
            let insets = UIEdgeInsetsMake(8.0, 8.0, 8.0, 8.0)
            let strechableImage = image.resizableImageWithCapInsets(insets)
            self.setBackgroundImage(strechableImage, forState: UIControlState.Normal)
            self.contentEdgeInsets = UIEdgeInsetsMake(16.0, 16.0, 16.0, 16.0)
            self.sizeToFit()
        }
    }

}

Where this is patientButton.png

在此输入图像描述

Two problems:

  1. the button doesn't render properly in Interface Builder. It just shows as a System button
  2. the title doesn't display unless I resize the button in Interface Builder to allow space for the image; ie, the contentEdgeInsets property and sizeToFit seem to have no effect

I guess it's a pretty basic question, but I can't any solution. Any advise?

EDIT 1 as per discussion with Matt below:

What I'm trying to achieve is to get some space around the title of the button. That was my understanding of contentEdgeInsets but it looks like I'm wrong. Without contentEdgeInsets this is the rendering of the button

在此输入图像描述

which looks horrible. I want to programmatically get something like this, without having to resize the button in IB

在此输入图像描述

You have misunderstood what contentEdgeInsets does. For the inset of your background image, you need to implement this method:

override func backgroundRectForBounds(bounds: CGRect) -> CGRect {
    return bounds.rectByInsetting(dx: 16, dy: 16)
}

For IBDesignable, what you're doing is structurally correct; if you delete your _setup() code and replace it with

self.backgroundColor = UIColor.redColor()

the button will in fact be red in IB. So maybe IB just doesn't "do" background images set in code and so on.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM