2012-06-28 22 views
17

我的應用程序由一個NSScrollView組成,其文檔視圖包含多個垂直堆疊的NSTextViews - 每個文本添加後都會在垂直方向調整大小。使用Autolayout擴展NSTextViews

目前,這是全部代碼管理。 NSTextViews自動調整大小,但我觀察它們的大小調整爲NSViewFrameDidChangeNotification,重新計算它們的所有來源以便它們不重疊,並調整它們的超級視圖(滾動視圖的文檔視圖),以便它們都適合並可以滾動到。

這看起來好像它將成爲自動佈局的完美人選!我在第一個文本視圖及其容器,最後一個文本視圖及其容器,以及每個文本視圖之間設置了NSLayoutConstraints。然後,如果任何文本視圖增長,它會自動「下推」它下面的文本視圖的起源以滿足限制,最終增加文檔視圖的大小,並且每個人都很開心!

除了,似乎沒有辦法讓NSTextView自動增長,因爲文本是在基於約束的佈局中添加的?使用完全相同的NSTextView,如果我沒有爲其高度指定約束,它會自動擴展爲之前輸入的文本,它會默認爲0並且不會顯示。如果我確實指定了一個約束條件,即使是不等於> = 20,它仍然停留在該大小,並且不會隨着文本的添加而增長。

我懷疑這與NSTextView的實現-intrinsicContentSize有關,默認返回(NSViewNoInstrinsicMetric, NSViewNoInstrinsicMetric)

所以我的問題:如果我的子類NSTextView基於我的文本的佈局返回更有意義的intrinsicContentSize,那麼我的自動佈局是否按預期工作?

任何指針實施intrinsicContentSize垂直調整大小的NSTextView?

+0

你可以添加一些圖形/截圖/線框有助於理解設置嗎?你是否嘗試計算文本高度並將其返回到'intrinsicContentSize'中? – JJD

回答

10

我有一個與NSTextField類似的問題,事實證明,這是由於想要沿着垂直方向緊緊擁抱其文本內容的視圖。因此,如果您將內容擁抱優先級設置爲低於其他約束條件的優先級,則可能會有效。例如: -

[textView setContentHuggingPriority:NSLayoutPriorityFittingSizeCompression-1.0 forOrientation:NSLayoutConstraintOrientationVertical]; 
+0

很高興能找到這個。我發現我必須在'NSSplitView'中爲垂直對齊的'NSTextField'做到這一點,但只有當它們是可選的而且不可編輯的!奇怪的是編輯行爲會影響約束,但是你去了。我將每個人的水平內容擁抱優先級從250改爲249,問題就消失了。 – theory

+0

在Swift 4下,這似乎是'setContentHuggingPriority(NSLayoutConstraint.Priority.fittingSizeCompression,對於:NSLayoutConstraint.Orientation.vertical)' 不知道-1的含義是什麼,但它似乎沒有工作。謝謝,馬克! –

18

我工作在一個非常類似的設置 - 包含文本的看法觀點,即擴展以適合其文本內容,並使用自動佈局垂直堆疊。

到目前爲止,我不得不繼承NSTextView,這是沒有感覺乾淨,但在實際工作寄望:

- (NSSize) intrinsicContentSize { 
    NSTextContainer* textContainer = [self textContainer]; 
    NSLayoutManager* layoutManager = [self layoutManager]; 
    [layoutManager ensureLayoutForTextContainer: textContainer]; 
    return [layoutManager usedRectForTextContainer: textContainer].size; 
} 

- (void) didChangeText { 
    [super didChangeText]; 
    [self invalidateIntrinsicContentSize]; 
} 

addSubview時添加文本視圖的初始大小,奇怪的是,不固有尺寸;我還沒有想出如何發佈第一個失效(連接viewDidMoveToSuperview並沒有幫助),但我相信我會最終弄清楚。

+2

非常有用!感謝您分享您的發現! – jemmons

+1

注意:我目前正在試圖讓大小平滑地動畫,並試驗我是否可以使用自動佈局來控制高度(或者補充內在大小)。事實證明,你可以通過調用'[constraint setConstant:newHeight]'給它一個新的高度來修改一個約束,其中'constraint'是一個提供高度設置的單個約束。它目前工作,但與'NSTextContainer'的自動調整大小衝突,導致閃爍。 –

3

下面是如何使用自動佈局作出擴大NSTextView,斯威夫特3 enter image description here

  • 我用Anchors的自動佈局
  • 使用textDidChangeNSTextDelegateNSTextViewDelegate符合NSTextDelegate
  • 的想法是textViewedges的限制,這意味着無論何時,只要intrinsicContentSize變化,將擴大其母公司,這是scrollView

    import Cocoa 
    import Anchors 
    
    class TextView: NSTextView { 
        override var intrinsicContentSize: NSSize { 
        guard let manager = textContainer?.layoutManager else { 
         return .zero 
        } 
    
        manager.ensureLayout(for: textContainer!) 
    
        return manager.usedRect(for: textContainer!).size 
        } 
    } 
    
    class ViewController: NSViewController, NSTextViewDelegate { 
    
        @IBOutlet var textView: NSTextView! 
        @IBOutlet weak var scrollView: NSScrollView! 
        override func viewDidLoad() { 
        super.viewDidLoad() 
    
        textView.delegate = self 
    
        activate(
         scrollView.anchor.top.constant(100), 
         scrollView.anchor.paddingHorizontally(30) 
        ) 
    
        activate(
         textView.anchor.edges 
        ) 
        } 
    
        // MARK: - NSTextDelegate 
        func textDidChange(_ notification: Notification) { 
        guard let textView = notification.object as? NSTextView else { return } 
    
        print(textView.intrinsicContentSize) 
        textView.invalidateIntrinsicContentSize() 
        } 
    }