使用 Masonry 配置好约束,再给每个 label 设置好内容(内容确定已经设置),为什么拿到的 label 的宽度是 0

问答Utopia • 于 2015-11-10 09:13:32 +0800 • 最后由 Utopia2015-11-11 00:39:51 +0800 7989 阅读

使用Masonry 配置好约束,再给每个label设置好约束和内容(内容确定已经设置),拿到的label的宽度是0。最终label是正常显示的。

这是实现的代码:四个函数从上到下依次调用

//创建labels
- (void)createView
{
    [self.view addSubview:[UIView new]];
    //创建分类选择视图

    classificationScrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(0, kNavigationBarHeight + kStatusBarHeight, kScreenWidth, kClassificationScrollViewHeight)];
    [self.view addSubview:classificationScrollView];

    classificationScrollView.contentSize = CGSizeMake(2 * kScreenWidth, kClassificationScrollViewHeight);

    classificationScrollView.backgroundColor = [UIColor yellowColor];

    contentView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, contentViewWidth, kClassificationScrollViewHeight)];
    [classificationScrollView addSubview:contentView];

    contentView.backgroundColor = [UIColor redColor];

    classificationScrollView.bounces = NO;

    //创建类别
    labelViewArray = [[NSMutableArray alloc]initWithCapacity:11];

    for (int i = 0; i < classificationArray.count; i++)
    {
        UILabel *labelView = [UILabel new];
        [labelViewArray addObject:labelView];
        [contentView addSubview:labelView];
    }

}

//配置约束
- (void)setAutolayout
{
    [labelViewArray[0] mas_makeConstraints:^(MASConstraintMaker *make)
    {
        make.top.bottom.equalTo(contentView);
        make.left.equalTo(contentView.mas_left).offset(kSpace);
    }];

    [labelViewArray[1] mas_makeConstraints:^(MASConstraintMaker *make)
     {
         make.top.bottom.equalTo(contentView);
         make.left.equalTo(((UILabel *)labelViewArray[0]).mas_right).offset(kSpace);
     }];

    [labelViewArray[2] mas_makeConstraints:^(MASConstraintMaker *make)
     {
         make.top.bottom.equalTo(contentView);
         make.left.equalTo(((UILabel *)labelViewArray[1]).mas_right).offset(kSpace);
     }];

    [labelViewArray[3] mas_makeConstraints:^(MASConstraintMaker *make)
     {
         make.top.bottom.equalTo(contentView);
         make.left.equalTo(((UILabel *)labelViewArray[2]).mas_right).offset(kSpace);

     }];

    [labelViewArray[4] mas_makeConstraints:^(MASConstraintMaker *make)
     {
         make.top.bottom.equalTo(contentView);
         make.left.equalTo(((UILabel *)labelViewArray[3]).mas_right).offset(kSpace);

     }];

    [labelViewArray[5] mas_makeConstraints:^(MASConstraintMaker *make)
     {
         make.top.bottom.equalTo(contentView);
         make.left.equalTo(((UILabel *)labelViewArray[4]).mas_right).offset(kSpace);

     }];

    [labelViewArray[6] mas_makeConstraints:^(MASConstraintMaker *make)
     {
         make.top.bottom.equalTo(contentView);
         make.left.equalTo(((UILabel *)labelViewArray[5]).mas_right).offset(kSpace);

     }];

    [labelViewArray[7] mas_makeConstraints:^(MASConstraintMaker *make)
     {
         make.top.bottom.equalTo(contentView);
         make.left.equalTo(((UILabel *)labelViewArray[6]).mas_right).offset(kSpace);

     }];

    [labelViewArray[8] mas_makeConstraints:^(MASConstraintMaker *make)
     {
         make.top.bottom.equalTo(contentView);
         make.left.equalTo(((UILabel *)labelViewArray[7]).mas_right).offset(kSpace);
        // make.right.equalTo(contentView);

     }];

    [labelViewArray[0] setContentHuggingPriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisHorizontal];
    [labelViewArray[1] setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
    [labelViewArray[2] setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
    [labelViewArray[3] setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
    [labelViewArray[4] setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
    [labelViewArray[5] setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
    [labelViewArray[6] setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
    [labelViewArray[7] setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
    [labelViewArray[8] setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];


}

//设置每个label的内容
- (void)setArrayViews
{
    for (int i = 0; i < classificationArray.count; i++)
    {
        UILabel *labelView = labelViewArray[i];
        labelView.text = classificationArray[i];
        labelView.textAlignment = NSTextAlignmentCenter;
    }
}

//这个函数里面求每个label的宽度,输出的label的宽度全是0
- (void)resetContentView
{
    NSInteger widthSum = 0;

    for (int i = 0; i < classificationArray.count; i++)
    {
        UILabel *lableView = labelViewArray[i];
        widthSum =  widthSum + lableView.bounds.size.width;
        NSLog(@"%f", lableView.bounds.size.width);
    }

    contentViewWidth = (classificationArray.count + 1) * kSpace + widthSum;

    contentView.bounds = CGRectMake(0, 0, contentViewWidth, kClassificationScrollViewHeight);


}
回复: 5
  • dugege 2015-11-10 10:27:54 +0800

    如果你真需要这么搞,可以在- (void)resetContentView方法里的的开始加上下面句代码试试 [self.view updateConstraintsIfNeeded];

  • dugege 2015-11-10 10:31:49 +0800

    不过建议你不要这么搞

    Masonry底层实现其实是Autolayout,所以更新不会立马触发,造成了你上面的问题。你可以看下Masonry源码和苹果文档的介绍UnderstandingAutolayout

  • Utopia 2015-11-10 11:06:46 +0800

    @dugege 嗯,还是不行。 我想实现简书滑动选择类别的功能,下图绿线部分。

    file

    但是我发现如果两个label并列显示在同一个view里,左边的label左对齐父视图,右边的label右对齐父视图,那么左边的label总是比右边的label宽。就像下图中的两个label:

    file

    这是实现的代码:

    _label1 = [UILabel new];
    _label1.backgroundColor = [UIColor yellowColor];
    _label1.text = @"label,";
    
    _label2 = [UILabel new];
    _label2.backgroundColor = [UIColor greenColor];
    _label2.text = @"label,";
    
    [_contentView1 addSubview:_label1];
    [_contentView1 addSubview:_label2];
    
    [_label1 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(_contentView1.mas_top).with.offset(5);
        make.left.equalTo(_contentView1.mas_left).with.offset(2);
        make.height.equalTo(@40);
    }];
    
    [_label2 mas_makeConstraints:^(MASConstraintMaker *make) {
    
        make.left.equalTo(_label1.mas_right).with.offset(2);
        make.top.equalTo(_contentView1.mas_top).with.offset(5);
        make.right.equalTo(_contentView1.mas_right).with.offset(-2);
        make.height.equalTo(@40);
    }];
    
    [_label1 setContentHuggingPriority:UILayoutPriorityRequired
                               forAxis:UILayoutConstraintAxisHorizontal];
    
    [_label1 setContentCompressionResistancePriority:UILayoutPriorityRequired
                                             forAxis:UILayoutConstraintAxisHorizontal];
    
    [_label2 setContentHuggingPriority:UILayoutPriorityRequired
                               forAxis:UILayoutConstraintAxisHorizontal];
    
    [_label2 setContentCompressionResistancePriority:UILayoutPriorityRequired
                                             forAxis:UILayoutConstraintAxisHorizontal];
    

    所以为了解决这个问题我就让右边的 label 不要右对齐父视图,但是这样两个 label 就可能填不满父视图,父视图的右边可能空出一截,也有可能出现父视图不够大的情况,所以我就想在设置好 labe l后重新计算父视图的宽度,但是结果拿不到 label 的宽度。

    可能是 ContentHugging 和 ContentCompression 设置的不对。我对 Masonry 还不熟悉,想下载 demo 学习,结果又运行不了。好郁闷,我现在运行 pod instal 已经成功了,但是 xcode 里同时有好几个工程,example 是其中一个工程,所以的工程都编译成功了,但是我不知道怎么让 example 工程运行。单独进入 Example 文件夹运行工程又编译错误, Example 文件下面没有 .xcworkspace 类型的文件,只有xcodeproj文件,但是又用到cocoapods 。无解了。。。

  • dugege 2015-11-10 11:19:26 +0800

    复写viewDidLayoutSubviews方法,在里面调用resetContentView,这方法应该好使了,先睡觉

  • Utopia 2015-11-11 00:39:50 +0800

    @dugege 不行额,谢谢了,我再想想别的办法。

  • 请注意单词拼写,以及中英文排版,参考此页
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`, 更多语法请见这里 Markdown 语法
  • 支持表情,见 Emoji cheat sheet
  • @name 会链接到用户页面,并会通知他
  • 上传图片, 支持拖拽和剪切板黏贴上传, 格式限制 - jpg, png, gif
Ctrl+Enter