问题
I have read many answers to questions about dynamically resizing NSWindows and nothing has quite worked yet.
I have built a 'popover' like window to be displayed form the menu bar, I couldn't use NSPopover because it isn't quite customisable enough in terms of design. My view hierarchy current looks like this:
NSWindow Subclass
- NSView (clears the titlebar rendering, draws popover arrow)
- NSView (contentView)
- NSOutlineView (main table of content)
- NSView (window footer)
What I need is for the window to expand and contract with items in the NSOutlineView expanding and contracting, so that the window is always precisely the correct height for the outline view, footer, and the popover arrow at the top.
I have methods to calculate the required height for the outline view based on the content. So far I have been trying to recalculate the size when awakeFromNib
is called on the content view controller, and then again on the delegate methods outlineViewItemDidCollapse:
and outlineViewItemDidExpand:
, but I am never able to resize the window correctly.
I have tried lots of different ways and none worked. Is there a 'canonical' way to do this? I've seen people talking about -[NSWindow frameForContentRect:]
in relation to this sort of problem, but I can't quite work out how that is needed.
Maybe I am going about this completely the wrong way, I hope not though. It seems like this should be possible, it's just getting the right things in the right places. Unfortunately GUI programming is not a strong point for me. I would appreciate any ideas or solutions people have.
Thanks.
Edit: This was solved, partly due to the marked answer, and partly due to a few other things. The clearing NSView did not have an autoresize mask, so I set this to expand in all directions, this helped with some of the resizing issues. Also, the method I was using for calculating the height required was not entirely correct and had a few problems.
With the provided answer, the way to find the required height is good for some circumstances, but I didn't have a 'root' item that could be measured. This is something that may need to be taken into account.
回答1:
Here is my method, it works very well, but there are probably better than that.
- (void)outlineViewItemDidExpand:(NSNotification *)notification {
[self resizeWindowHeight];
}
- (void)outlineViewItemDidCollapse:(NSNotification *)notification {
[self resizeWindowHeight];
}
- (void)resizeWindowHeight {
NSRect wRect = [myWindow frame];
NSRect oRect = [myoutlineView rectOfRow:([myoutlineView numberOfRows] - 1)]; //get rect of last row
CGFloat n = oRect.origin.y + oRect.size.height + 22;
wRect.origin.y = wRect.origin.y + (wRect.size.height - n);
wRect.size.height = n;
[myWindow setFrame:wRect display:YES animate:YES];
}
The number 22 is the sum of : (top window - top Outline) + height of Outline header + height of horizontal scroller + (bottom window - bottom Outline) + height of toolbar
My settings in IB for this example : no horizontal scroller and no header , height of Outline = height of the contentView of the window, so 22 is the window border.
If you have a toolbar or the horizontal scroller is hidden automatically, you need to add conditions in the code to check the visibility of (the toolbar and scroller) and change the height accordingly.
回答2:
One approach is to record the initial height of the outline view and the initial height of the window and then, as the outline view height changes, compute the new height of the window = old height + (new outline height - old outline height). By working only in terms of changes from an initial state, it makes things more flexible. You don't have to replicate your whole layout in code as you would if you were recomputing the size of things from scratch. You can use IB to lay out the window and it should retain that layout without the code having to know much about the specifics. And you can update the layout in IB and the code still works.
Otherwise, I suggest you show what you've tried and explain how it isn't right.
来源:https://stackoverflow.com/questions/10952643/dynamically-resize-nswindow-based-on-nsoutlineview-height