带有 PDF 的 UIButton 图像具有全宽图像视图

UIButton Image with PDF has full width image view

我正在尝试构建一个类似按钮的单选按钮(一个圆圈,左边有一个点,旁边有文字 它在右边),几乎像这样:

我有 2 个 PDF (link to one of them),其中包含选定和未选定收音机的图像。我的按钮代码如下:

let radioBtn = UIButton()
radioBtn.setImage(UIImage(named: "radio", in: .module, compatibleWith: nil), for: .normal)
radioBtn.setImage(UIImage(named: "radio_ticked", in: .module, compatibleWith: nil), for: .selected)
radioBtn.contentHorizontalAlignment = .leading
radioBtn.titleLabel?.adjustsFontSizeToFitWidth = true
radioBtn.titleEdgeInsets = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 0)
radioBtn.contentEdgeInsets = UIEdgeInsets(top: 8, left: 0, bottom: 8, right: 0)
radioBtn.heightAnchor.constraint(equalToConstant: 40).isActive = true
radioBtn.contentVerticalAlignment = .center
radioBtn.imageView?.contentMode = .scaleAspectFit

问题是 UIImage 延伸了整个宽度(蓝色部分)并且没有 space 文本可以显示:

我想要完成的是收音机完全位于左侧,然后是旁边的文字,并带有一些插图。如何实现?

首先,您的代码没有为您的按钮设置 宽度。在这种情况下,该按钮会将其 imageView 的宽度设置为图像的大小 - 使用您的 pdf,最终宽度为 510 pts。

那么,几个选项...

  1. 使用一些缩放代码来调整图像大小。如果您将按钮高度设置为 40,顶部和底部插入 8 磅,则需要 24x24 图片。

  2. 为您的按钮设置宽度约束,并“即时”计算 imageView 插图。

可能最简单的方法是使用 UIButton 子类,例如:

class RadioButton: UIButton {

    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }
    func commonInit() -> Void {

        contentHorizontalAlignment = .leading

        // 8-pts inset "padding" on all 4 sides
        contentEdgeInsets = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)

        // set title inset Left to content inset Left
        var insets: UIEdgeInsets = titleEdgeInsets
        insets.left = contentEdgeInsets.left
        titleEdgeInsets = insets

        // set images for .normal and .selected
        if let img = UIImage(named: "radio") {
            setImage(img, for: .normal)
        }
        
        if let img = UIImage(named: "radio_ticked") {
            setImage(img, for: .selected)
        }
        
    }

    override func layoutSubviews() {
        super.layoutSubviews()

        // make sure an image was set (otherwise, there is no imageView)
        if let imgView = imageView {
            // get height of imageView
            let h = imgView.frame.height
            // get current (default) image edge insets
            var insets: UIEdgeInsets = imageEdgeInsets
            // set inset Right to width of self minus imageView Height + Left and Right content insets
            insets.right = bounds.width - (h + contentEdgeInsets.left + contentEdgeInsets.right)
            // update image edge insets
            imageEdgeInsets = insets
        }
    }
}

使用示例:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let radioBtn = RadioButton()
        
        // background color so we can see its frame
        radioBtn.backgroundColor = .red
        radioBtn.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(radioBtn)

        // give it a 22-pt bold font
        radioBtn.titleLabel?.font = .boldSystemFont(ofSize: 22.0)
        
        // set the Title
        radioBtn.setTitle("Testing", for: [])

        // Height: 40
        radioBtn.heightAnchor.constraint(equalToConstant: 40).isActive = true
        // Width: 240
        radioBtn.widthAnchor.constraint(equalToConstant: 240.0).isActive = true
        // centered in view
        radioBtn.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        radioBtn.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true

    }
}

结果: