This is for macOS, not iOS ... thank you.
I have a very simple custom slider control that has 2 @IBInspectable properties - trackHeight and knobHeight. I want my control's frame in Interface Builder to resize in response to those 2 properties changing, so that users get visual feedback during design-time. Now, this works fine during runtime, but NOT in Interface Builder.
What happens in Interface Builder is: the frame stays the same size, but the track and knob (which are custom-drawn by me) of the slider are stretched. This is not what I want. The frame of the control should change.
I have searched a LOT for the solution, and this is what I have in my code, with no luck. Please help. Thanks in advance.
import Cocoa
@IBDesignable
class MySliderControl: NSControl {
override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
self.frame = NSMakeRect(frameRect.minX, frameRect.minY, 200, max(trackHeight, knobHeight))
}
required init?(coder: NSCoder) {
super.init(coder: coder)
self.frame = NSMakeRect(frame.minX, frame.minY, 200, max(trackHeight, knobHeight))
}
@IBInspectable var trackHeight: CGFloat = 4 {
didSet {
prepareForInterfaceBuilder()
needsDisplay = true
}
}
@IBInspectable var knobHeight: CGFloat = 10 {
didSet {
prepareForInterfaceBuilder()
needsDisplay = true
}
}
override func layout() {
self.setFrameSize(intrinsicContentSize)
super.layout()
}
override func prepareForInterfaceBuilder() {
// Resize the frame as a function of trackHeight and knobHeight.
self.setFrameSize(intrinsicContentSize)
super.prepareForInterfaceBuilder()
}
// Width is constant (200), and height is the maximum of knobHeight and trackHeight.
override var intrinsicContentSize: NSSize {
NSMakeSize(200, max(trackHeight, knobHeight))
}
override func draw(_ dirtyRect: NSRect) {
// Center knobRect with respect to barRect.
let barRect = NSMakeRect(0, knobHeight / 2 - trackHeight / 2, 200, trackHeight)
let knobRect = NSMakeRect(50, 0, 20, knobHeight)
var path = NSBezierPath(rect: barRect)
NSColor.gray.setFill()
path.fill()
path = NSBezierPath(rect: knobRect)
NSColor.white.setFill()
path.fill()
}
}
When overriding
intrinsicContentSize
, we need to invalidate it to inform IB that it needs to be updated. This will also trigger a call todraw(_ dirtyRect: NSRect)
.Give this a try:
Edit -- whoops, just saw the date on the post. Hopefully, you already got this worked out :)