By default, in MacOS, you can double click the titlebar of a window to zoom it (resize to fit the screen - different from maximize). Double clicking it again brings it back to the previous size.
This works fine on my Catalyst app too. However I need to hide the titlebar and need to give my own custom UIView in that titlebar area the double click behavior. I am able to hide it using this: #endif
Is there a method which lets me toggle the window zoom?
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
I am using the window.level set to .floating as described here:
https://developer.apple.com/documentation/appkit/nswindow/level
The setting itself works okay. However, in a multi monitor setup, the floating window is appearing on both the screens.
How can I prevent this? My users report that before macOS Sonoma, this used to not happen. Has this behaviour changed? How can I revert back to the old behaviour?
I have a UILabel subclass showing NSAttributedString in which I need to draw a rounded rectangle background color around links:
import UIKit
class MyLabel: UILabel {
private var linkRects = [[CGRect]]()
private let layoutManager = NSLayoutManager()
private let textContainer = NSTextContainer(size: .zero)
private let textStorage = NSTextStorage()
override func draw(_ rect: CGRect) {
let path = UIBezierPath()
linkRects.forEach { rects in
rects.forEach { linkPieceRect in
path.append(UIBezierPath(roundedRect: linkPieceRect, cornerRadius: 2))
}
}
UIColor.systemGreen.withAlphaComponent(0.4).setFill()
path.fill()
super.draw(rect)
}
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setup()
}
private func setup() {
numberOfLines = 0
adjustsFontForContentSizeCategory = true
isUserInteractionEnabled = true
lineBreakMode = .byWordWrapping
contentMode = .redraw
clearsContextBeforeDrawing = true
isMultipleTouchEnabled = false
backgroundColor = .red.withAlphaComponent(0.1)
textContainer.lineFragmentPadding = 0
textContainer.maximumNumberOfLines = numberOfLines
textContainer.lineBreakMode = lineBreakMode
textContainer.layoutManager = layoutManager
layoutManager.textStorage = textStorage
layoutManager.addTextContainer(textContainer)
textStorage.addLayoutManager(layoutManager)
}
override func layoutSubviews() {
super.layoutSubviews()
calculateRects()
}
private func calculateRects(){
linkRects.removeAll()
guard let attributedString = attributedText else {
return
}
textStorage.setAttributedString(attributedString)
let labelSize = frame.size
textContainer.size = labelSize
layoutManager.ensureLayout(for: textContainer)
let textBoundingBox = layoutManager.usedRect(for: textContainer)
print("labelSize: \(labelSize)")
print("textBoundingBox: \(textBoundingBox)")
var wholeLineRanges = [NSRange]()
layoutManager.enumerateLineFragments(forGlyphRange: NSRange(0 ..< layoutManager.numberOfGlyphs)) { _, rect, _, range, _ in
wholeLineRanges.append(range)
print("Whole line: \(rect), \(range)")
}
attributedString.enumerateAttribute(.link, in: NSRange(location: 0, length: attributedString.length)) { value, clickableRange, _ in
if value != nil {
var rectsForCurrentLink = [CGRect]()
wholeLineRanges.forEach { wholeLineRange in
if let linkPartIntersection = wholeLineRange.intersection(clickableRange) {
var rectForLinkPart = layoutManager.boundingRect(forGlyphRange: linkPartIntersection, in: textContainer)
rectForLinkPart.origin.y = rectForLinkPart.origin.y + (textContainer.size.height - textBoundingBox.height) / 2 // Adjust for vertical alignment
rectsForCurrentLink.append(rectForLinkPart)
print("Link rect: \(rectForLinkPart), \(linkPartIntersection)")
}
}
if !rectsForCurrentLink.isEmpty {
linkRects.append(rectsForCurrentLink)
}
}
}
print("linkRects: \(linkRects)")
setNeedsDisplay()
}
}
And I use this as such:
let label = MyLabel()
label.setContentHuggingPriority(.required, for: .vertical)
label.setContentHuggingPriority(.required, for: .horizontal)
view.addSubview(label)
label.snp.makeConstraints { make in
make.width.lessThanOrEqualTo(view.safeAreaLayoutGuide.snp.width).priority(.required)
make.horizontalEdges.greaterThanOrEqualTo(view.safeAreaLayoutGuide).priority(.required)
make.center.equalTo(view.safeAreaLayoutGuide).priority(.required)
}
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .justified
let s = NSMutableAttributedString(string: "Lorem Ipsum: ", attributes: [.font: UIFont.systemFont(ofSize: 17, weight: .regular), .paragraphStyle: paragraphStyle])
s.append(NSAttributedString(string: "This property controls the maximum number of lines to use in order to fit the label's text into its bounding rectangle.", attributes: [.link: URL(string: "https://news.ycombinator.com/") as Any, .foregroundColor: UIColor.link, .font: UIFont.systemFont(ofSize: 14, weight: .regular), .paragraphStyle: paragraphStyle]))
label.attributedText = s
Notice the paragraphStyle.alignment = .justified
This results in:
As you can see, the green rect background is starting a bit further to the right and also ending much further to the right.
If I set the alignment to be .left or .center, then it gives me the correct rects:
Also note that if I keep .justified but change the font size for the "Lorem Ipsom:" part to be a bit different, lets say 16 instead of 17, then it gives me the correct rect too:
Also note that if we remove some word from the string, then also it starts giving correct rect. It seems like if the first line is too squished, then it reports wrong rects.
Why is .justified text alignment giving me wrong rects? How can I fix it?
Topic:
UI Frameworks
SubTopic:
UIKit