Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSTextView not properly resizing with auto layout

I have a simple layout, which consists of NSView and its subview NSTextView. NSTextView is programmatically filled with some text that spawns multiple lines. I tie everything together using auto-layout (all done programmatically). However, when everything is displayed NSTextView is cut off, only one line is showing.

After searching the web, the best answer I could find was:

Using Autolayout with expanding NSTextViews

However, this only works if I manually change the text in NSTextView after everything is displayed (which is not really my use case). The views are readjusted and the whole NSTextView is displayed.

I am trying to figure out when NSViewController is done with laying out subviews so that I could call invalidateIntrinsicContentSize on the NSTextView. The equivalent of viewDidLayoutSubviews in UIViewController.

Nothing I tried worked so far. I attempted calling invalidateIntrinsicContentSize for NSTextView:

  • At the end of loadView
  • After I filled NSTextView with my text

Is there a better way to achieve this?

like image 495
yura Avatar asked Jun 13 '14 16:06

yura


1 Answers

After further research, found the answer:

  1. Create custom NSView subclass that contains NSTextView
  2. In NSView subclass override layout method that calls invalidateIntrinsicContentSize

Also check out this link that explains subtleties of auto layout and intrinsic content size (among many other things):

http://www.objc.io/issue-3/advanced-auto-layout-toolbox.html

Sample code:

@interface MyView : NSView
  @property MyTextView *textView;
@end

@implementation MyView

// init & create content & set constraints

-(void) layout {
    [super layout];
    [self.textView invalidateIntrinsicContentSize];
}

@end

Implementation of MyTextView:

@implementation MyTextView

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

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

@end
like image 191
yura Avatar answered Sep 22 '22 18:09

yura