UIScrollView中使用Autolayout实现动态UILabel高度

16

我正在使用自动布局和 UIScrollView 来展示对象的某些属性。我通过 web 服务动态地下载此信息。滚动视图具有固定的宽度(因为我不想要垂直滚动行为),其子视图通过一组约束将其宽度保持不变,但我无法动态增加 UILabel 的高度。

我已经编写了所有代码,并使用 viewDidLoad 选择器创建子视图...

- (void)viewDidLoad {
    [super viewDidLoad];
    .
    .
    .

    UILabel *descriptionLabel = [[UILabel alloc] initWithFrame:CGRectZero];
    descriptionLabel.translatesAutoresizingMaskIntoConstraints = NO;
    descriptionLabel.numberOfLines = 0;
    descriptionLabel.lineBreakMode = NSLineBreakByWordWrapping;
    descriptionLabel.opaque = YES;
    descriptionLabel.backgroundColor = [UIColor clearColor];
    descriptionLabel.textColor = [UIColor whiteColor];
    descriptionLabel.textAlignment = NSTextAlignmentRight;
    descriptionLabel.font = [UIFont appetitoMediumItalicFontWithSize:15.0f];
    descriptionLabel.text = NSLocalizedStringFromTable(@"APT_DISH_DETAIL_DESCRIPTION", @"DishDetail", @"Etiqueta que contiene la descripción del platillo");
    [descriptionLabel setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
    [self.detailContentScrollView addSubview:descriptionLabel];
    self.descriptionLabelS = descriptionLabel;

    .
    .
    .
}

您可以查看self.detailContentScrollView变量,这是从视图控制器的nib创建的IBOulet

然后我使用updateConstraints选择器...

- (void)updateConstraints {
[super updateConstraints];
// This dictionary has more variables, ok
NSDictionary *viewsDict = @{@"dish_description_label": self.descriptionLabelS};
.
.
.

[self.descriptionLabelS setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
[self.detailContentScrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[view1][dish_description_label]-[view2][view3][view4]-|" options:0 metrics:nil views:viewsDict]];

.
.
.
}

最后,当我接收到Web服务的信息时,我会从滚动视图中发送sizeToFitUILabel选择器和layoutIfNeeded。但是我的UILabel永远不会根据新内容重新调整大小。我做错了什么?

4个回答

7
如果您想用视图来实现:
  • 添加一个UIScrollview,高度约束>= [你想要的最小值] 例如480

  • 在滚动视图中添加一个UILabel,高度约束>= [你想要的最小值] 例如460

就像以下图片所示:

scrollView constraints label constraints viewController the output will be something like that

如果需要以编程方式实现:

UIScrollView *scrollView= [UIScrollView new];
    scrollView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:scrollView];

    UILabel *scrollViewLabel = [[UILabel alloc] init];
    scrollViewLabel.numberOfLines = 0;
    scrollViewLabel.translatesAutoresizingMaskIntoConstraints = NO;
    [scrollView addSubview:scrollViewLabel];

    scrollViewLabel.text = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque ac urna ac ipsum sodales fermentum ornare quis tellus. Integer urna dolor, placerat ut pharetra sit amet, mattis a eros. Maecenas dapibus accumsan felis eget faucibus. Nulla rhoncus gravida neque, sed suscipit ex tempor quis. In sagittis sed enim ut posuere. Donec varius euismod rutrum. Pellentesque mauris sem, mollis id odio eu, maximus interdum elit. Mauris pharetra magna ut tortor lobortis sollicitudin. Cras volutpat porta facilisis. Praesent lacinia mi at volutpat accumsan. Sed eu cursus metus. Donec a convallis nunc. Curabitur tempus accumsan lacus vitae luctus. Sed non quam non leo condimentum congue. Nam dui ipsum, elementum in congue id, mollis ac mauris. Morbi finibus turpis quam, ut venenatis magna malesuada ac. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aliquam erat volutpat. Curabitur nulla mi, aliquam faucibus blandit et, maximus eu libero. Duis semper, est posuere egestas interdum, quam nibh convallis odio, efficitur tempor purus arcu quis justo. Donec euismod feugiat urna in viverra. Sed vel tristique massa. Morbi in consequat sem. Nunc placerat lacus a mauris tempus porttitor. Fusce sed iaculis tortor, nec luctus ligula. Donec euismod metus mauris. Mauris sit amet euismod sapien. Praesent lobortis interdum ligula consequat viverra. Quisque et tortor mattis, congue dolor a, sagittis ligula. Phasellus in lacinia magna. Fusce vel placerat nisi. Maecenas egestas mattis lorem, vel tincidunt mauris eleifend et. In eu pulvinar nibh. Suspendisse ac suscipit orci. Suspendisse at lectus vel purus hendrerit lacinia at posuere sapien. Nunc auctor nisi eget nunc suscipit auctor. Donec fringilla odio lectus, quis porttitor nisl fermentum eget. Nam nunc purus, lobortis id sem porta, accumsan egestas quam. Integer blandit feugiat nunc ac scelerisque. Pellentesque vehicula, massa eget mollis aliquam, felis nulla posuere elit, at gravida elit diam id ligula. Suspendisse pharetra velit sed lacus scelerisque viverra. Maecenas volutpat non metus a interdum. In vitae vestibulum enim. Proin vitae libero non odio finibus pulvinar. In condimentum, sapien ac vehicula lobortis, dolor magna iaculis ex, in consectetur turpis orci eget justo. Suspendisse in lobortis justo, bibendum finibus lorem. Suspendisse ullamcorper diam eu elit sollicitudin, at tempus massa dignissim. In a ante rhoncus, porttitor tortor fermentum, molestie nunc. Phasellus mi dolor, vehicula sed sodales ut, sollicitudin ac ex. Praesent consequat, nunc sed posuere condimentum, risus ex malesuada nulla, sed faucibus velit elit ac risus. Ut venenatis ut nisl in hendrerit.";


    /*** Auto Layout ***/

    NSDictionary *views = NSDictionaryOfVariableBindings(scrollView, scrollViewLabel);

    NSArray *scrollViewLabelConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[scrollViewLabel(scrollView)]" options:0 metrics:nil views:views];
    [scrollView addConstraints:scrollViewLabelConstraints];

    scrollViewLabelConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[scrollViewLabel]|" options:0 metrics:nil views:views];
    [scrollView addConstraints:scrollViewLabelConstraints];

    NSArray *scrollViewConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[scrollView]-|" options:0 metrics:nil views:views];
    [self.view addConstraints:scrollViewConstraints];

    scrollViewConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[scrollView]-|" options:0 metrics:nil views:views];
    [self.view addConstraints:scrollViewConstraints];


7

UIScrollView的内容大小会根据自动布局动态更新,你只需要执行以下操作:

- (void) setupScroll
{
    [_scrollView setTranslatesAutoresizingMaskIntoConstraints:NO];
    [_contentView setTranslatesAutoresizingMaskIntoConstraints:NO];

    [_scrollView addSubview:_contentView];

    NSArray *horizontal = [NSLayoutConstraint constraintsWithVisualFormat:@"|[_contentView]|"
                                                                  options:0
                                                                  metrics:nil
                                                                    views:NSDictionaryOfVariableBindings(_contentView)];
    NSArray *vertical = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_contentView]|"
                                                                options:0
                                                                metrics:nil
                                                                  views:NSDictionaryOfVariableBindings(_contentView)];

    [_scrollView addConstraints:horizontal];
    [_scrollView addConstraints:vertical];

    UIView *mainView = self.view;
    horizontal = [NSLayoutConstraint constraintsWithVisualFormat:@"|[_contentView(==mainView)]|"
                                                         options:0
                                                         metrics:nil
                                                           views:NSDictionaryOfVariableBindings(_contentView, mainView)];

    [mainView addConstraints:horizontal];
}

在这里,_contentView是您的UILabel(如果您有更复杂的视图层次结构,请放在一个视图容器上),而self.view是控制器视图(或其他任何内容)。希望这也有所帮助:iOS Autolayout with UIScrollview: Why does content view of scroll view not fill the scroll view?

同时不要忘记设置您的UILabel preferredMaxLayoutWidth

祝好!


这是另一个解决问题的功能性方案,谢谢。 - specktro
请查看此帖子以获取完整的实现:http://arielelkin.github.io/articles/uilabel-plus-uiscrollview-plus-autolayout/ - Eric
@Eric:链接失效了。 - testing
@testing:我现在已经在我的下面的答案中发布了完整的实现以及更新后的链接。 - Eric
我有self.scrollView和self.mainView1,当我使用constraintsWithVisualFormat:@"|[_mainView1]|"时,出现错误:终止应用程序由于未捕获的异常'NSInvalidArgumentException',原因是:无法解析约束格式:_mainView1不是视图字典中的键。|[_mainView1]|。你能帮我吗? - Ne AS

1

这是一个完整的实现:

/*** Init the scrollview and the label ***/

UIScrollView *scrollView= [UIScrollView new];
scrollView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:scrollView];

UILabel *scrollViewLabel = [[UILabel alloc] init];
scrollViewLabel.numberOfLines = 0;
scrollViewLabel.translatesAutoresizingMaskIntoConstraints = NO;
[scrollView addSubview:scrollViewLabel];

scrollViewLabel.text = @"Bacon ipsum dolor sit amet drumstick meatloaf filet mignon ham t-bone andouille meatball venison cow capicola jerky shankle shoulder ground round. Shank filet mignon pork chop ham hock, short ribs jerky prosciutto tongue porchetta. Biltong kevin strip steak tail jowl jerky boudin drumstick pastrami bresaola. Sirloin tail shoulder salami, hamburger beef doner turducken chuck boudin kielbasa sausage pork loin. Ball tip leberkas fatback, pork chop tail ham ribeye. Bresaola pancetta jerky beef kielbasa frankfurter, corned beef filet mignon ribeye tongue porchetta. Prosciutto short loin sirloin doner brisket jerky swine sausage bresaola chuck. Meatloaf pork chop ribeye bacon jerky turducken, andouille pork belly beef ribs ham hock leberkas. Andouille tri-tip capicola beef t-bone shank tenderloin turducken ball tip salami pork belly shankle. Kielbasa pastrami brisket, kevin spare ribs swine tail beef jerky venison filet mignon. Kevin leberkas ball tip, brisket bresaola chuck meatloaf beef doner drumstick hamburger capicola chicken. Tri-tip biltong drumstick pork prosciutto strip steak pastrami brisket shank hamburger flank tail cow. Pastrami beef ribs ribeye boudin spare ribs pork loin. Meatloaf tail pork belly strip steak doner. T-bone meatball pastrami, pork strip steak salami tail beef boudin leberkas. Venison t-bone fatback, pig brisket pork loin landjaeger turkey tri-tip biltong. Drumstick tri-tip hamburger boudin meatball pork pork chop short ribs chuck doner t-bone bacon frankfurter porchetta beef. Turkey cow meatball andouille pancetta, flank strip steak ham hock. Frankfurter corned beef rump turducken brisket, jerky short loin flank tri-tip ball tip ham hock swine spare ribs.";


/*** Auto Layout ***/

NSDictionary *views = NSDictionaryOfVariableBindings(scrollView, scrollViewLabel);

NSArray *scrollViewLabelConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[scrollViewLabel(scrollView)]" options:0 metrics:nil views:views];
[scrollView addConstraints:scrollViewLabelConstraints];

scrollViewLabelConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[scrollViewLabel]|" options:0 metrics:nil views:views];
[scrollView addConstraints:scrollViewLabelConstraints];

NSArray *scrollViewConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[scrollView]-|" options:0 metrics:nil views:views];
[self.view addConstraints:scrollViewConstraints];

scrollViewConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[scrollView]-|" options:0 metrics:nil views:views];
[self.view addConstraints:scrollViewConstraints];

详细解释如下:

https://arielelkin.github.io/articles/uilabel-plus-uiscrollview-plus-autolayout


1
我有同样的问题。苹果似乎存在一个错误,因此多行文本需要进行两次布局才能正确排版,并且所有内容都依赖于属性preferredMaxLayoutWidth。
最终,我在ScrollViewController中添加了以下两个方法:
- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    [self performSelectorOnMainThread:@selector(adjustScrollContentSizeOnMainThread) withObject:nil    waitUntilDone:NO];
}

- (void)adjustScrollContentSizeOnMainThread
{
    self.myLabel.preferredMaxLayoutWidth = self.myLabel.bounds.size.width;
}

我基于这个答案来解决问题:https://dev59.com/rGYs5IYBdhLWcg3wFP94#13616052

非常感谢你,我已经为此奋斗了很长时间,而你救了我。 - Harshit Gupta
1
没有这样的错误,因此不需要采用这种方法。@D33pN16h7的答案完美地解决了问题。将标签作为滚动视图的子视图添加,将其numberOfLines设置为0或大于1,并将这些约束添加到滚动视图中:@"H:|[label(scrollview)]"@"V:|[label]|" - Eric

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接