首發於公衆號微信
在 macOS 系統下,App 左上角的 3 個控制按鈕被稱爲「交通燈」,由於他們的顏色和現實中的交通訊號燈同樣(紅(關閉),黃(最小化),綠(最大化))。佈局
實際開發中會遇到按鈕的默認位置不能知足設計的需求,須要調整它們的位置。ui
然而系統並無提供方法直接調整他們的位置,開發中經常使用的方法有兩種:spa
模仿系統按鈕 使用黑魔法更改按鈕位置設計
第一種方法,要模仿系統的行爲須要一些額外的工做量,不考慮。 第二種方法工做量比較小,只是須要作一些分析工做,just do it !3d
查看一下這幾個按鈕的佈局:code
能夠看到它們處於 NSTitlebarContainerView 中的 NSTitlebarView 裏,並且使用的是自動佈局(autolayout)的方式。cdn
這樣思路就很簡單了,只要給這幾個按鈕設置約束,就能夠達到更改位置的目的了。blog
在什麼時機設置約束比較好呢?答案是在 Window 初始化完成以後就是最佳時機,代碼以下:繼承
@implementation TUINSWindow
- (instancetype)initWithContentRect:(CGRect)rect {
...
[self relayoutWindowButtons];
...
}
- (void)relayoutWindowButtons {
NSButton *closeButton = [self standardWindowButton:NSWindowCloseButton];
NSButton *minButton = [self standardWindowButton:NSWindowMiniaturizeButton];
NSButton *zoomButton = [self standardWindowButton:NSWindowZoomButton];
NSView *titlebarView = closeButton.superview;
closeButton.translatesAutoresizingMaskIntoConstraints = NO;
[titlebarView addConstraints:@[
[NSLayoutConstraint constraintWithItem:closeButton attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:titlebarView attribute:NSLayoutAttributeTop multiplier:1 constant:9],
[NSLayoutConstraint constraintWithItem:closeButton attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:titlebarView attribute:NSLayoutAttributeLeft multiplier:1 constant:2]
]];
minButton.translatesAutoresizingMaskIntoConstraints = NO;
[titlebarView addConstraints:@[
[NSLayoutConstraint constraintWithItem:minButton attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:titlebarView attribute:NSLayoutAttributeTop multiplier:1 constant:9],
[NSLayoutConstraint constraintWithItem:minButton attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:titlebarView attribute:NSLayoutAttributeLeft multiplier:1 constant:20]
]];
zoomButton.translatesAutoresizingMaskIntoConstraints = NO;
[titlebarView addConstraints:@[
[NSLayoutConstraint constraintWithItem:zoomButton attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:titlebarView attribute:NSLayoutAttributeTop multiplier:1 constant:9],
[NSLayoutConstraint constraintWithItem:zoomButton attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:titlebarView attribute:NSLayoutAttributeLeft multiplier:1 constant:38]
]];
}
@end
複製代碼
TUINSWindow 繼承自 NSWindow,在設置好了 style 以後就能夠調用 relayoutWindowButtons 方法設置約束了。
NSWindow 提供了獲取系統按鈕的方法:- (NSButton *)standardWindowButton:(NSWindowButton)b; 根據以前的分析,按鈕的父窗口就是 NSTitlebarView。
看一下調整以後的效果:
大功告成!
偷偷的說,我發現微信、企業微信的 macOS 版本,它們也是這麼實現的。
若是要像微信 macOS 版本那樣,只須要調整約束以下,在上面的約束中,不添加左約束就能夠了:
- (void)relayoutWindowButtons {
NSButton *closeButton = [self standardWindowButton:NSWindowCloseButton];
NSButton *minButton = [self standardWindowButton:NSWindowMiniaturizeButton];
NSButton *zoomButton = [self standardWindowButton:NSWindowZoomButton];
NSView *titlebarView = closeButton.superview;
closeButton.translatesAutoresizingMaskIntoConstraints = NO;
[titlebarView addConstraints:@[
[NSLayoutConstraint constraintWithItem:closeButton attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:titlebarView attribute:NSLayoutAttributeTop multiplier:1 constant:9]
]];
minButton.translatesAutoresizingMaskIntoConstraints = NO;
[titlebarView addConstraints:@[
[NSLayoutConstraint constraintWithItem:minButton attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:titlebarView attribute:NSLayoutAttributeTop multiplier:1 constant:9]
]];
zoomButton.translatesAutoresizingMaskIntoConstraints = NO;
[titlebarView addConstraints:@[
[NSLayoutConstraint constraintWithItem:zoomButton attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:titlebarView attribute:NSLayoutAttributeTop multiplier:1 constant:9]
]];
}
複製代碼
看一下效果,和微信對比一下,是否是一摸同樣了:
全文完,感謝閱讀 ^_^