在下面的屏幕截图中,请注意DropDownButton(所选视图)未进行实时渲染。另外,请注意" Designables最新版本"在Identity Inspector中。最后,请注意助理编辑器中的两个断点:如果我执行编辑器 - >调试所选视图然后命中这两个断点。
这是我运行时的样子:
以下是代码:
@IBDesignable
class DropDownButton: UIButton {
override init(frame: CGRect) {
super.init(frame: frame)
initialize()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
initialize()
}
private func initialize() {
if image(for: .normal) == nil {
//setImage(#imageLiteral(resourceName: "DropDown"), for: .normal)
let bundle = Bundle(for: DropDownButton.self)
if let image = UIImage(named: "DropDown", in: bundle, compatibleWith: nil) {
setImage(image, for: .normal) // Editor -> Debug Selected Views reaches this statement
}
}
if title(for: .normal) == nil {
setTitle("DropDown", for: .normal) // Editor -> Debug Selected Views reaches this statement
}
addTarget(self, action: #selector(toggle), for: .touchUpInside)
}
override func layoutSubviews() {
super.layoutSubviews()
if var imageFrame = imageView?.frame, var labelFrame = titleLabel?.frame {
labelFrame.origin.x = contentEdgeInsets.left
imageFrame.origin.x = labelFrame.origin.x + labelFrame.width + 2
imageView?.frame = imageFrame
titleLabel?.frame = labelFrame
}
}
override func setTitle(_ title: String?, for state: UIControlState) {
super.setTitle(title, for: state)
sizeToFit()
}
public var collapsed: Bool {
return imageView?.transform == CGAffineTransform.identity
}
public var expanded: Bool {
return !collapsed
}
private func collapse() {
imageView?.transform = CGAffineTransform.identity
}
private func expand() {
imageView?.transform = CGAffineTransform(rotationAngle: .pi)
}
@objc private func toggle(_: UIButton) {
if collapsed { expand() } else { collapse() }
}
}
首先编辑:
我根据@ DonMag的回答添加了prepareForInterfaceBuilder方法。这样做了一个改进但仍然有问题:界面构建器似乎对框架感到困惑。当我选择按钮时,仅选择标题,而不是图像(即三角形)。我添加了边框;它绕过标题和图像。这是一张图片:
如果我将按钮拖动到新位置,那么一切都会移动,标题和图像。
另外,prepareForInterfaceBuilder让我感到惊讶。我对这种方法的理解是它允许我只进行界面构建器设置,例如提供虚拟数据。