【问题标题】:Custom UIButton @IBDesignable自定义 UIButton @IBDesignable
【发布时间】:2017-11-17 16:33:28
【问题描述】:

我创建了一个看起来像复选标记的 UIButton 子类。

这是类:

import UIKit

@IBDesignable
class CheckedButton: UIButton {

    // MARK: - Properties
    @IBInspectable var checked: Bool = false {
        didSet {
            // Toggle the check/uncheck images
            updateImage()
        }
    }


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

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setup()
    }

    private func setup() {
        updateImage()
        self.addTarget(self, action: #selector(tapped), for: .touchUpInside)
    }

    private func updateImage() {
        let image = checked ? UIImage(named: "checked") : UIImage(named: "unchecked")
        self.setImage(image, for: .normal)
    }

    /// Called each time the button is tapped, and toggles the checked property
    @objc private func tapped() {
        checked = !checked
        print("New value: \(checked)")
    }  
}

由于我将checkedproperty 设置为@IBInspectable,我在 IB 中看到它:

奇怪的是:

  • 如果我将此属性设为default,它会正确显示在情节提要中

  • 但如果我在检查器中选择onoff,屏幕不会正确更新。

由于该类被标记为@IBDesignable,我希望按钮外观会根据在检查器选项卡中为此属性设置的值在 IB 中更新。 有线索吗?

【问题讨论】:

    标签: ios swift uibutton ibdesignable ibinspectable


    【解决方案1】:

    UIimage(named:) 方法使用主包,但 Interface Builder 以不同的方式加载资源。

    试试这个:

    UIImage(named: "checked", in: bundle, compatibleWith: nil)

     @IBDesignable
    
     class CheckedButton: UIButton {
    
     // MARK: - Properties
     @IBInspectable var checked: Bool = false {
         didSet {
             // Toggle the check/uncheck images
             updateImage()
         }
     }
    
    
     override init(frame: CGRect) {
         super.init(frame: frame)
         setup()
     }
    
     required init?(coder aDecoder: NSCoder) {
         super.init(coder: aDecoder)
         setup()
     }
    
     override func prepareForInterfaceBuilder() {
         super.prepareForInterfaceBuilder()
         setup()
     }
    
     internal func setup() {
         self.addTarget(self, action: #selector(tapped), for: .touchUpInside)
     }
    
     private func updateImage() {
         let bundle = Bundle(for: CheckedButton.self)
         let image = checked ? UIImage(named: "checked", in: bundle, compatibleWith:nil) : UIImage(named: "unchecked", in: bundle, compatibleWith:nil)
         self.setBackgroundImage(image, for: .normal)
     }
    
     /// Called each time the button is tapped, and toggles the checked property
     @objc private func tapped() {
         checked = !checked
         print("New value: \(checked)")
     }
    

    【讨论】:

      【解决方案2】:

      我的建议是使用其他自定义函数从资产中获取图像:

      extension UIImage {
          public static func image(name: String, _ sender: UIView?) -> UIImage? {
              #if TARGET_INTERFACE_BUILDER
                  if let sender = sender {
                      let bundle = Bundle(for: sender.classForCoder)
                      return UIImage(named: name, in: bundle, compatibleWith: sender.traitCollection)
                  } else {
                      return UIImage(named: name)
                  }
              #else
                  return UIImage(named: name)
              #endif
          }
      }
      

      你的例子:

      private func updateImage() {
          let image = checked ? UIImage.image(name: "checked", self) : UIImage(name: "unchecked", self)
         setImage(image, for: .normal)
      }
      

      另外,UIButton 类具有检查状态,您可以使用它而无需创建自己的子类:

      let btn = UIButton(type: .custom)
      btn.setImage(UIImage.image(name: "unchecked", self), for: .normal)
      btn.setImage(UIImage.image(name: "checked", self), for: .selected)
      
      btn.isSelected = true // change button state between checked and unchecked
      

      【讨论】:

      • 感谢您的回答。但是,要获取资源库中的几个图像,您的扩展看起来相当复杂(这是 Apple 现在推荐的方式)。另外,我需要对这个按钮进行子类化,因为我会多次使用它,而且我不想一遍又一遍地进行相同的图像设置。
      猜你喜欢
      • 2020-12-03
      • 1970-01-01
      • 1970-01-01
      • 2014-12-23
      • 2011-08-10
      • 2021-03-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多