我有一个自定义NSView的层次结构,我以不受autolayout约束支持的样式进行布局。现在,我只是在观看调整大小事件,并在所有子视图(及其子视图......)上调用-setFrame
,但就源代码复杂性而言,这不是很好的扩展。 (当我在层次结构的底部添加一个新的子视图时,我必须在顶视图中添加其布局逻辑 - 这似乎并不理想。)
正如我所理解的,解决这个问题的正确方法是覆盖NSView的-layout方法(当我想在树的某个层面强制布局时调用-setNeedsLayout
)。
不幸的是,这方面的文档有点简洁,并且(尽管有“CocoaSlides”链接),Apple没有覆盖此方法的示例代码。我尝试在Github上搜索,但事实证明“布局”在Objective-C代码中是一个相当常见的词,我还没有找到一个我想要的那个。
例如,假设我有一个AAView(NSView),里面有一些BBView,它显示了一些自动换行的文本,它想要以100%的宽度显示它们(模糊地像一个NSStackView,我想,虽然这是Cocoa的另一个完全没有文档记录的特征。
因为BBViews的高度取决于它们的宽度(由于它们的自动换行),所以它们不能有-intrinsicContentSize
(正确吗?)。 AAView的-layout方法想要放置BBViews,即设置它们的frameSize和frameOrigin。但是,为了了解BBView的大小,它需要询问BBView - 但BBView无法在其-layout
方法中设置其自己的大小(仅适用于其子视图,如果有的话) )。因此,在这些类中-layout
的任何实现也需要一些带外方法(比如BBView上的-requestedHeightForWidth:(CGFloat)width
),此时我不确定它是否比我自己更好ad-hoc -setFrame
调用(即CocoaSlides实际执行的操作)。
有人能指出一些为自定义NSView实现-layout
的示例代码吗?我只是没有看到它应该如何工作。我完全咆哮了错误的树吗?
答案 0 :(得分:1)
我相信你可以在BBView上使用-intrinsicContentSize使用autolayout做你想要的,假设我理解了这个问题。
如果你的BBView总是希望始终是你的AAView的确切宽度(或接近那个),你可以设置标准的水平约束来强制执行此操作。这解决了宽度。
要在BBView上执行高度覆盖-setFrameSize:如果宽度已从旧宽度更改,请调用-invalidateIntrinsicContentSize。
在BBView上的-intrinsicContentSize中,您可以查看当前宽度并根据字符串在其中的布局方式计算高度。返回{self.frame.width,calculatedHeight},你就可以回家了。 (如果-intrinsicContentSize被大量调用并且你的布局很昂贵,那么对此有明显的优化。)
编辑:实际上,你应该返回(NSSize){NSViewNoInstrinsicMetric,calculatedHeight},而不是当前的宽度。遗憾。
答案 1 :(得分:0)
(回答这种方式很晚,因为其他人可能正在寻找答案而我去年犯了同样的错误):
请勿查看涉及框架的方法以获得答案。相反 - 而Apple对此非常清楚 - 在编写新应用程序时应该使用Autolayout。在Autolayout-land中,一切都是不同的,而intrinsicContentSize是用与自动布局工作的方法之一,但操纵框架和手动更新窗口大小和位置是一个死胡同。