我正在嘗試在 Objective-C Mac 應用程式中以編程方式使自動布局作業。
目標非常基本,視窗頂部有一個簡單的類似工具列的視圖。高度不應改變,視圖應保持在視窗頂部,寬度應隨視窗調整大小。
當我在 .xib 中配置它時,它作業得很好。不用擔心高度,我只添加從自定義視圖到超級視圖(即 NSWindow 的 contentView)的前導、尾隨和頂部約束連接。我不必更改任何優先級或其他設定。
我需要以編程方式執行此操作,在代碼中創建視窗、子視圖和約束。我已經嘗試使用錨點和 NSLayoutConstraint 物件(引數化和基于視覺布局字串)。在所有情況下,我都會得到一個奇怪的行為,其中視窗的 contentView 調整大小,高度為零,并且螢屏上沒有繪制任何內容。
這是使用錨點的一種完整方法:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// make window
NSRect windowRect = NSMakeRect(0.0, 0.0, 900.0, 200.0);
NSWindowStyleMask windowStyle = NSWindowStyleMaskTitled
| NSWindowStyleMaskClosable
| NSWindowStyleMaskResizable
| NSWindowStyleMaskMiniaturizable;
NSWindow * win = [[NSWindow alloc] initWithContentRect:windowRect
styleMask:windowStyle
backing:NSBackingStoreBuffered
defer:NO];
win.title = @"Window Made in Code";
win.contentView.translatesAutoresizingMaskIntoConstraints = NO;
// add view
NSRect viewFrame = windowRect;
viewFrame.size.height = 80.0;
viewFrame.origin.y = 120.0;
NSView * view = [[MyView alloc] initWithFrame:viewFrame];
[win.contentView addSubview:view];
[view setNeedsDisplay:YES];
// add constraints
[view.leadingAnchor constraintEqualToAnchor:win.contentView.leadingAnchor].active = YES;
[view.trailingAnchor constraintEqualToAnchor:win.contentView.trailingAnchor].active = YES;
[view.topAnchor constraintEqualToAnchor:win.contentView.topAnchor].active = YES;
// note, the above also tried using layoutMargins of superview, same behavior
// show window
[win setIsVisible:YES];
[win center];
self.codeWindow = win;
[self.codeWindow makeKeyAndOrderFront:NSApp];
}
如果我不添加約束,一切都會正確繪制,但正如預期的那樣,子視圖不會隨視窗調整大小。
When I add the constraints, the superview (window's contentView) gets resized to height 0, so nothing gets drawn. If I omit the top constraint this does not happen, however the horizontal constraints then work backward: rather than resizing subview as the window is resized, they prevent the Window contentView from resizing horizontally; I can still drag the window larger but debugging see that the content view frame width does not increase.
Here's an alternate code approach I also tried using NSLayoutConstraint factory methods; here I'm setting priority but no different priority corrects the behavior:
NSLayoutConstraint * leadingC = [NSLayoutConstraint constraintWithItem:view
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:view.superview
attribute:NSLayoutAttributeLeading
multiplier:1.0
constant:0.0];
leadingC.priority = NSLayoutPriorityDragThatCannotResizeWindow;
NSLayoutConstraint * trailingC = [NSLayoutConstraint constraintWithItem:view
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:view.superview
attribute:NSLayoutAttributeLeading
multiplier:1.0
constant:0.0];
trailingC.priority = NSLayoutPriorityDragThatCannotResizeWindow;
NSLayoutConstraint * topC = [NSLayoutConstraint constraintWithItem:view
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:view.superview
attribute:NSLayoutAttributeTop
multiplier:1.0
constant:0.0];
[NSLayoutConstraint activateConstraints:@[leadingC, trailingC, topC]];
[view.superview addConstraints:self.constraints];
Since I'm getting the same bad result trying this several different ways I feel like I must be completely missing something with NSLayoutConstraint, but I haven't been able to figure it out from tutorials or documentation. I did compare via debugging layout constraints at runtime between .xib and code-created windows but haven't been able to reconstruct what I'm doing wrong from the differences, except that the .xib superview has NSAutoresizingMaskLayoutConstraint objects.
If I comment-out win.contentView.translatesAutoresizingMaskIntoConstraints = NO; I do get resizing behavior programmatically, but that is confusing to me - I thought when we created explicit constraints we were supposed to set that flag to NO?
Thanks for any suggestions on how to get this working!
uj5u.com熱心網友回復:
當您選擇加入約束時,您必須使用約束完整地描述視圖的大小。在這種情況下,您已經指定了工具列的寬度,并設定了它的位置,但看起來您正在嘗試使用最初提供視圖的框架來修復高度。您還必須有一個約束來設定其高度。
還translatesAutoresizingMaskIntoConstraints描述了一個視圖如何與其父視圖相關,而不是它的子視圖。所以你應該在工具列視圖上設定它,而不是在視窗的 contentView 上。試試這個代碼:
#import "AppDelegate.h"
@interface AppDelegate ()
@end
@interface MyView : NSView
@end
@implementation MyView
- (void)drawRect:(NSRect)dirtyRect
{
CGContextRef cgContext = [[NSGraphicsContext currentContext] CGContext];
CGContextSetFillColorWithColor(cgContext, [[NSColor yellowColor] CGColor]);
CGContextFillRect(cgContext, self.bounds);
}
@end
@implementation AppDelegate
{
NSWindowController *disjointController;
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
NSRect windowRect = NSMakeRect(0.0, 0.0, 900.0, 200.0);
NSWindowStyleMask windowStyle = NSWindowStyleMaskTitled
| NSWindowStyleMaskClosable
| NSWindowStyleMaskResizable
| NSWindowStyleMaskMiniaturizable;
NSWindow * win = [[NSWindow alloc] initWithContentRect:windowRect
styleMask:windowStyle
backing:NSBackingStoreBuffered
defer:NO];
win.title = @"Window Made in Code";
// add view
NSView *view = [[MyView alloc] initWithFrame: windowRect];
view.translatesAutoresizingMaskIntoConstraints = NO;
view.layer.backgroundColor = [[NSColor yellowColor] CGColor];
[win.contentView addSubview: view];
// add constraints
[view.leadingAnchor constraintEqualToAnchor: win.contentView.leadingAnchor].active = YES;
[view.trailingAnchor constraintEqualToAnchor: win.contentView.trailingAnchor].active = YES;
[view.topAnchor constraintEqualToAnchor: win.contentView.topAnchor].active = YES;
[view.heightAnchor constraintEqualToConstant: 80].active = YES;
// show window
[win center];
disjointController = [[NSWindowController alloc] initWithWindow: win];
[win makeKeyAndOrderFront:NSApp];
}
- (void)applicationWillTerminate:(NSNotification *)aNotification {
// Insert code here to tear down your application
}
- (BOOL)applicationSupportsSecureRestorableState:(NSApplication *)app {
return YES;
}
@end
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/350515.html
標籤:objective-c macos cocoa autolayout appkit
上一篇:給定正整數A的3次冪
