2013-07-27 4 views
15

Mam jeden UIView czarownica jest wypełniona programowo. Układ w tym UIView odbywa się za pomocą automatycznego układu.UIView z Auto layout, uzyskać jego rozmiar

Ten widok musi być podzbiorem jednego UIScrollView i musi przewijać się w pionie.

mam kod jak poniżej:

// self.scrollview is defined in IB and it has constraints to edges (margin:0 0 0 0) 

UIView *contentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1024, MAXFLOAT)]; 
[contentView setTranslatesAutoresizingMaskIntoConstraints:YES]; 

// Then I call some my parser which add subviews to the contentView and layout them using constraints. 

[self.scrollview addSubview:contentView]; 
[contentView setNeedsLayout]; 
[contentView layoutIfNeeded]; 

// Now, I need to know height of the contentView to be able to set contentSize to self.scrollview 

// UPDATE

Ok, mam ten UILabel, dodany do self.content który jest tworzony z UIView: [[UIView alloc] initWithFrame:CGRectMake(self.layoutMargin, self.layoutMargin, 1024 - self.layoutMargin*2, 100)]);

This Widok self.content jest dla mnie tylko kontenerem, który należy umieścić pod numerem UIScrollView. Potrzebuję wysokości self.content do ustawienia contentSize z UIScrollView.

[self.content setTranslatesAutoresizingMaskIntoConstraints:YES]; 

[self.content setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical]; 
[self.content setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical]; 

UILabel *textlabel = [[UILabel alloc] init]; 
UIFont *font; 


font = [UIFont fontWithName:@"InterstatePlus-Regular" size:16]; 

UIFont *bold; 

bold = [UIFont fontWithName:@"InterstatePlus-Bold" size:16]; 
NSDictionary *style = @{ 
         @"$default" : @{NSFontAttributeName : font}, 
         @"b"  : @{NSFontAttributeName : bold}, 
         @"em"  : @{NSFontAttributeName : [UIFont fontWithName:@"HelveticaNeue-Italic" size:14]}, 
         @"h1"  : @{NSFontAttributeName : [UIFont fontWithName:@"HelveticaNeue-Medium" size:48]}, 
         @"h2"  : @{NSFontAttributeName : [UIFont fontWithName:@"HelveticaNeue-Medium" size:36]}, 
         @"h3"  : @{NSFontAttributeName : [UIFont fontWithName:@"HelveticaNeue-Medium" size:32]}, 
         @"h4"  : @{NSFontAttributeName : [UIFont fontWithName:@"HelveticaNeue-Medium" size:24]}, 
         @"h5"  : @{NSFontAttributeName : [UIFont fontWithName:@"HelveticaNeue-Medium" size:18]}, 
         @"h6"  : @{NSFontAttributeName : [UIFont fontWithName:@"HelveticaNeue-Medium" size:16]} 
         }; 
[textlabel setNumberOfLines:0]; 



NSError *error = nil; 
NSString *string = @"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing <br>Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type<br> and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."; 
NSString *replacedString = [string stringByReplacingOccurrencesOfString:@"<br>" withString:@"\n"]; 
NSAttributedString *attributedString = [SLSMarkupParser attributedStringWithMarkup:replacedString style:style error:&error]; 
NSMutableAttributedString *mutAttributedString = [[NSMutableAttributedString alloc] initWithAttributedString:attributedString]; 

NSInteger strLength = [attributedString length]; 
NSMutableParagraphStyle *paragraphstyle = [[NSMutableParagraphStyle alloc] init]; 
[mutAttributedString addAttribute:NSParagraphStyleAttributeName 
          value:paragraphstyle 
          range:NSMakeRange(0, strLength)]; 

if (mutAttributedString) { 
    textlabel.attributedText = mutAttributedString; 
} 


[textlabel setTranslatesAutoresizingMaskIntoConstraints:NO]; 

[textlabel setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical]; 
[textlabel setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical]; 


textlabel.textAlignment = NSTextAlignmentLeft; 

[textlabel setTextColor:[UIColor blackColor]]; 

[textlabel setBackgroundColor:[UIColor clearColor]]; 
textlabel.lineBreakMode = NSLineBreakByWordWrapping; 
[textlabel setNumberOfLines:0]; 
[self.content addSubview:textlabel]; 

[textlabel mas_makeConstraints:^(MASConstraintMaker *make) { 
    make.top.equalTo(self.content.mas_top).with.offset(0); 
    make.right.equalTo(self.content.mas_right).with.offset(0); 
    make.height.equalTo(@1200); 
    make.left.equalTo(self.content.mas_left).with.offset(0); 
}]; 
[self.containerView addSubview:self.content]; 
[self.containerView setBackgroundColor:[UIColor redColor]]; 
[self.content setBackgroundColor:[UIColor yellowColor]]; 

CGSize s = [self.content systemLayoutSizeFittingSize:UILayoutFittingCompressedSize]; 
NSLog(@"Size: %f %f", s.width, s.height); 

To Log: Rozmiar: 17713,000000 0,000000

I wygląda na to: http://d.pr/i/Rxku

+0

Czy cały ten kod w 'viewDidLoad'? –

+0

Tak, w viewDidLoad – dormitkon

Odpowiedz

33

sizeToFit jest źle API używać jeśli używasz autoLayout.

Prawidłowym api do użycia w autowybiorze jest UIViewsystemLayoutSizeFittingSize: najprawdopodobniej przekazujący UILayoutFittingCompressedSize. Spowoduje to zwrócenie CGSize, który jest minimalnym rozmiarem, który może ograniczyć widok z określonymi ograniczeniami.

Sprawdź this Link

EDIT: W odpowiedzi na dodatkowy kod, który został oddelegowany ...

nigdy nie używałem biblioteki Masonry wcześniej, ale to jest czysty!

UILabels zapewniają wystarczającą wielkość, aby wyświetlić ich tekst. Aby obliczyć ten rozmiar w przypadku tekstu wielowierszowego, etykieta musi znać jeden wymiar, który zostanie ustalony, i jest to pożądany wymiar szerokości za pośrednictwem właściwości preferredMaxLayoutWidth. Jeśli nie podasz wartości preferredMaxLayoutWidth (domyślnie jest to 0), etykieta oblicza wewnętrzny rozmiar zawartości AS, jeśli układa pojedynczą linię tekstu.

W swoim kodzie nigdy nie ustawiasz etykiety preferredMaxLayoutWidth, więc każdy układ wykonany przez autolayout, który opiera się na wewnętrznymContentsSize etykiety, nie będzie taki, jak się spodziewasz.

Wziąłem swój kod i destyluje go do nowego przykład, który powinien być w stanie skopiować/przenieść do czystego viewcontroller podklasy:

#import "Masonry.h" 

@interface TSViewController() 
@end 

@implementation TSViewController 
{ 
    UIScrollView* _scrollView; 
    UIView*   _containerView; 

    UILabel*  _titleLabel; 
    UILabel*  _contentLabel; 
} 

- (void) viewDidLoad 
{ 
    [super viewDidLoad]; 

    self.view.backgroundColor = [UIColor darkGrayColor]; 

    // create/configure our scrollview 
    _scrollView = [UIScrollView new]; 
    _scrollView.translatesAutoresizingMaskIntoConstraints = NO; 
    _scrollView.backgroundColor = [UIColor scrollViewTexturedBackgroundColor]; 
    [self.view addSubview: _scrollView]; 

    // create/configure our container 
    _containerView = [UIView new]; 
    _containerView.translatesAutoresizingMaskIntoConstraints = NO; 
    _containerView.backgroundColor = [UIColor yellowColor]; 
    [_scrollView addSubview: _containerView]; 

    // create/configure our content - title and content labels 
    _titleLabel = [UILabel new]; 
    _titleLabel.translatesAutoresizingMaskIntoConstraints = NO; 
    _titleLabel.numberOfLines = 1; 
    _titleLabel.font = [UIFont fontWithName: @"Courier" size: 80]; 
    _titleLabel.text = @"Lorem Ipsum"; 
    _titleLabel.backgroundColor = [UIColor lightGrayColor]; 
    _titleLabel.textAlignment = NSTextAlignmentCenter; 
    [_containerView addSubview: _titleLabel]; 

    _contentLabel = [UILabel new]; 
    _contentLabel.translatesAutoresizingMaskIntoConstraints = NO; 
    _contentLabel.numberOfLines = 0; 
    _contentLabel.font = [UIFont fontWithName: @"Courier" size: 40]; 
    _contentLabel.text = self.loremIpsum; 
    [_containerView addSubview: _contentLabel]; 

    // configure constraints for each view: 

    [_scrollView mas_makeConstraints: ^(MASConstraintMaker *make) { 

     // glue the scrollview to its superview with a 20 point inset: 

     make.top.equalTo(self.view.mas_top).with.offset(20); 
     make.left.equalTo(self.view.mas_left).with.offset(20); 
     make.right.equalTo(self.view.mas_right).with.offset(-20); 
     make.bottom.equalTo(self.view.mas_bottom).with.offset(-20); 
    }]; 

    [_containerView mas_makeConstraints: ^(MASConstraintMaker *make) { 

     // per the iOS 6.0 Release Notes, this is how to use auto-layout for a container view 
     // inside a scrollview. basically, tie the edges of the containerview to the scrollview. 
     // http://developer.apple.com/library/ios/#releasenotes/General/RN-iOSSDK-6_0/ 
     // see section "Here are some notes regarding Auto Layout support for UIScrollView" 

     make.top.equalTo(_scrollView.mas_top); 
     make.left.equalTo(_scrollView.mas_left); 
     make.right.equalTo(_scrollView.mas_right); 
     make.bottom.equalTo(_scrollView.mas_bottom); 

     // match the width of the containerview to the scrollview width: 
     make.width.equalTo(_scrollView.mas_width); 

     // match the height of the containerview to the intrinsic height of the contentlabel + 100 points for our fixed height title 

     // (this is the magical part.) 
     make.height.equalTo(_contentLabel.mas_height).with.offset(100); 
    }]; 

    [_titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { 

     // tie the contentlabel edges to the sides of its container: 
     make.top.equalTo(_containerView.mas_top).with.offset(0); 
     make.left.equalTo(_containerView.mas_left).with.offset(0); 
     make.right.equalTo(_containerView.mas_right).with.offset(0); 

     // fixed height 
     make.height.equalTo(@100); 
    }]; 

    [_contentLabel mas_makeConstraints:^(MASConstraintMaker *make) { 

     // tie top edge to the bottom of our title 
     make.top.equalTo(_titleLabel.mas_bottom); 

     // tie the remaining edges to the sides of the container: 
     make.left.equalTo(_containerView.mas_left); 
     make.right.equalTo(_containerView.mas_right); 
     make.bottom.equalTo(_containerView.mas_bottom); 
    }]; 
} 

- (void) viewWillLayoutSubviews 
{ 
    // perform a scrollview layout so the containerView width will be set 
    [_scrollView setNeedsLayout]; 
    [_scrollView layoutIfNeeded]; 

    // update the preferred layout width of the content label; 
    // this affects the label's intrinsicContentSize and will force our constraints to be recalculated 
    CGFloat preferredWidth = _containerView.frame.size.width; 
    _contentLabel.preferredMaxLayoutWidth = preferredWidth; 


    // we don't need this since the scrollview is fully using autolayout to adjust the content-size. but just to show that it works: 

    CGSize fittingSize = [_containerView systemLayoutSizeFittingSize: UILayoutFittingCompressedSize]; 

    NSLog(@"container fitting size: %@", NSStringFromCGSize(fittingSize)); 
} 

- (NSString*) loremIpsum 
{ 
    return @"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing <br>Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type<br> and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."; 
} 

@end 

A oto wyjście z systemLayoutSizeFittingSize gdy ograniczenia są działa ładnie:

2013-08-05 15:01:16.309 testLabelConstraints[8265:c07] container fitting size: {721, 6868} 
+0

U użyte: CGSize s = [self.mainContentView systemLayoutSizeFittingSize: UILayoutFittingCompressedSize]; NSLog (@ "Rozmiar:% f% f", s.width, s.height); I otrzymuję: Rozmiar: 5584.000000 0.000000 :( – dormitkon

+1

@dormitkon -Nasze ograniczenia mogą być pomieszane.Możesz spróbować prostszego przypadku i dodać z powrotem złożoność, gdy już to działa? Lub dodaj więcej kodu ze swoim ograniczenia pokazujące, dzięki czemu możemy pomóc: – TomSwift

+0

Więzy są generowane w oparciu o układ XML, więc mogą się zmieniać ze strony na stronę. Sprawdziłem z autolayouttrace i układ jest w porządku: | – dormitkon

-1

Czy próbowałeś już KVO?

w viewDidLoad dodać obserwatora:

[contentView addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew | NSKeyValueObservingOptionPrior context:NULL]; 

następnie dodać tę metodę:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { 
    if([keyPath isEqualToString:@"frame"]) { 
     CGRect oldFrame = CGRectNull; 
     CGRect newFrame = CGRectNull; 
     if([change objectForKey:@"old"] != [NSNull null]) { 
      oldFrame = [[change objectForKey:@"old"] CGRectValue]; 
     } 
     if([object valueForKeyPath:keyPath] != [NSNull null]) { 
      newFrame = [[object valueForKeyPath:keyPath] CGRectValue]; 
     } 
     //new size! 
     if (newFrame.size.width > 0 && newFrame.size.height > 0) { 
      NSLog(@"%@", NSStringFromCGRect(newFrame)); 
     } 
    } 
} 

to powinno wydrukować ramkę swojego contentView gdy jest ustawiony na coś większego następnie CGSize(1,1)

2

If Rozumiem Cię, problemem jest uzyskanie widoku lub widoków, które dynamicznie zmieniają rozmiar, aby odpowiednio przewijać, gdy są subskrybentami z ScrollView. To jest to, miałem ten problem i można go rozwiązać, nawet nie martwiąc się o rozmiar zawartości.

Oto link do tech notatki z Apple zatytułowany „UIScrollView i autoLayout” tu

http://developer.apple.com/library/ios/technotes/tn2154/_index.html

Jest łatwy do naśladowania źródło w nocie która szczegółowo dwa podejścia do rozwiązania tego problemu. Mam nadzieję, że to pomaga, to naprawdę mi pomogło.

Dodatkowo, jeśli próbujesz przejrzeć zbiór subskrybentów w swoim ScrollView, przeczytaj ten artykuł i przykład, ponownie, jasne wyjaśnienie za pomocą kodu.

Apeth Programowanie IOS 6, Rozdział 20. przewijania Views on line tutaj:

http://www.apeth.com/iOSBook/ch20.html