2014-01-09 79 views
4

我有自定義NSView的層次結構,我正在佈局自動佈局約束不支持的樣式。現在,我只是在觀看調整大小事件,並在我所有的子視圖(及其子視圖...)上調用-setFrame,但就源代碼複雜性而言,這並不能很好地擴展。 (當我在層次結構的底部添加一個新的子視圖時,我必須在頂部視圖中添加其佈局邏輯 - 這看起來並不理想。)NSView的-layout方法的重寫究竟應該如何工作?

解決此問題的正確方法,就像我理解它,是覆蓋NSView的-layout方法(然後在我想強制佈局的某個級別時調用-setNeedsLayout)。

不幸的是,該文檔有點簡潔,並且(儘管有「CocoaSlides」鏈接),但沒有來自Apple的示例代碼覆蓋此方法。我試圖在Github上搜索,但事實證明,「佈局」在Objective-C代碼中是一個相當常見的詞,我還沒有找到一個我想要的。例如,假設我有一個AAView(NSView),裏面有一些BBView,它顯示一些文字包裝的文本,並且想要以它自己的寬度的100%顯示它們(有點像NSStackView ,我想,儘管這是可可的另一個完全沒有記錄的特徵)。

因爲BBView的高度取決於它們的寬度(由於它們的文字換行),所以它們不能有-intrinsicContentSize(正確?)。 AAView的-layout方法想要放置BBViews,即設置它們的frameSize和frameOrigin。但是,爲了瞭解BBView的大小,需要詢問BBView - 但BBView無法在其-layout方法中設置自己的大小(僅適用於子視圖,如果有的話)。因此,在這些類中的-layout的任何實現也需要一些帶外方法(例如BBView上的-requestedHeightForWidth:(CGFloat)width),此時我不確定這比我自己的特定-setFrame調用(即, CocoaSlides實際上做了什麼)。

有人能指點我一些示例代碼,它爲自定義NSViews實現-layout?我只是沒有看到這應該如何工作。我完全吠叫錯了樹嗎?

回答

1

我相信你可以用BBView上的-intrinsicContentSize做你想要的自動佈局,假設我理解了這個問題。

如果您的BBView總是希望始終是您的AAView的確切寬度(或與之相近的東西),那麼您可以設置標準水平約束來執行此操作。這解決了寬度。

要執行高度,請在BBView上覆蓋-setFrameSize:並且如果寬度已從舊寬度更改,請調用-invalidateIntrinsicContentSize。

在BBView的-intrinsicContentSize中,查看當前寬度並根據字符串在其內部的佈局計算高度。返回{self.frame.width,calculatedHeight},你是無家可歸的。 (有明顯的優化,如果-intrinsicContentSize稱爲很多,你的佈局是昂貴的。)

編輯:其實,你應該返回(NSSize){NSViewNoInstrinsicMetric,calculatedHeight},而不是當前的寬度。抱歉。

+0

嗯,我有很多問題!我希望大致瞭解如何覆蓋'-layout',但我相信你是對的,我可以使用比我更大的自動佈局,比如在這個(簡化)的情況下。 – user241221

+0

讓我困惑的一點是:蘋果文檔會說「這種固有尺寸必須獨立於內容框架」,但聽起來好像你說要繼續前進並依賴於內容框架,並根據需要使其無效。 – user241221

+0

對,他們說的不太正確 - 他們的意思是它必須獨立於內容框架,否則你必須自己使內在大小無效。我在我的代碼中完成了這個工作,它效果很好。 –

0

(後期要回答這個方式,因爲別人可能會尋找的答案,我在去年同樣的錯誤):

別看涉及幀你的答案的方法。相反 - 蘋果對此非常清楚 - 在編寫新應用程序時,您應該使用Autolayout。 Autolay-land中的所有內容都不相同,intrinsicContentSize是自動佈局工作之一,但是操縱幀和手動更新窗口大小和位置是一個死路。