1

What I want to achieve in AppKit (not in SwiftUI): [GIF] (example in SwiftUI)

  • The NSWindow max width should not be limited to the NSTextField max width.
  • The NSWindow min width should be limited to the NSTextField 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]

1 Answer 1

0

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),
])
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.