What I want to achieve in AppKit (not in SwiftUI): [GIF] (example in SwiftUI)
- The
NSWindow
max width should not be limited to theNSTextField
max width. - The
NSWindow
min width should be limited to theNSTextField
min width. NSTextField
need to have these parameters: [min width:200
, max width:400
]
I had several attempts to implement this behavior in AppKit. I've been trying to do this for a few days now, but it doesn't work. [PIC] [GIF]
I tried to set the low priority on Leading / Trailing constraint.
This partially fixed the situation. I was able to change the size of the window normally, but the window size was not limited to the minimum size of NSTextField
.
[GIF]
CodePudding user response:
The important thing to notice here is that you only want the low priority constraints to be one way. That is, you don't want something like this:
// throughout the answer, I use "tf" for the text field, and "view" for its superview
let weakLeadingConstraint = tf.leadingAnchor.constraint(equalTo: view.leadingAnchor)
let weakTrailingConstraint = tf.trailingAnchor.constraint(equalTo: view.trailingAnchor)
weakLeadingConstraint.priority = .dragThatCannotResizeWindow
weakTrailingConstraint.priority = .dragThatCannotResizeWindow
Because these constraints would break when the window is resized, allowing the window to be resizable to any width where the leading and trailing anchors are "not equal" to those of the text field.
Instead, the low priority constraints should be >= or <= constraints. Think of the 2 equality constraints as the following 4 inequality constraints:
tf.leading <= view.leading
tf.trailing >= view.trailing
tf.leading >= view.leading
tf.trailing <= view.trailing
It is the first 2 that you want to break, leaving the last 2 (which says that the text field should always be within the window) in tact, when you resize the window.
The other constraints are quite straightforward, so I'll just present the whole code here:
tf.translatesAutoresizingMaskIntoConstraints = false
let weakLeadingConstraint = tf.leadingAnchor.constraint(lessThanOrEqualTo: view.leadingAnchor)
let weakTrailingConstraint = tf.trailingAnchor.constraint(greaterThanOrEqualTo: view.trailingAnchor)
weakLeadingConstraint.priority = .dragThatCannotResizeWindow
weakTrailingConstraint.priority = .dragThatCannotResizeWindow
NSLayoutConstraint.activate([
tf.centerXAnchor.constraint(equalTo: view.centerXAnchor),
tf.centerYAnchor.constraint(equalTo: view.centerYAnchor),
tf.leadingAnchor.constraint(greaterThanOrEqualTo: view.leadingAnchor),
tf.trailingAnchor.constraint(lessThanOrEqualTo: view.trailingAnchor),
weakLeadingConstraint,
weakTrailingConstraint,
tf.widthAnchor.constraint(greaterThanOrEqualToConstant: 200),
tf.widthAnchor.constraint(lessThanOrEqualToConstant: 400),
])