Autolayout +基于总行的动态表高度约束

时间:2016-02-12 12:59:44

标签: ios objective-c uitableview autolayout nslayoutconstraint

首先,关于动态细胞的高度。所以不要混淆。

我有一个场景,我创造了三张牌

  1. 明细卡:显示位置的具体详情
  2. 图表卡:根据选择显示不同的图表
  3. 更多细节卡片:卡片显示更多细节
  4. 以下是上述卡片的屏幕:

    enter image description here enter image description here enter image description here

    查看上述屏幕的层次结构:

      
        
    • 控制器      
          
      • 滚动型
      •   
      • 卡-1
      •   
      • 卡-2
      •   
      • Card-3< ----我们对此卡感兴趣      
            
        • 自定义视图      
              
          • 的TableView
          •   
        •   
      •   
    •   

    所以我在这里展示了最后一张卡片的限制,以上所有卡片都是完美的!并且没有约束歧义或警告。

    让我们通过代码:

    首先将Card-3添加到ScrollView此处chartBox为Card-2,bottomBox为Card-3

    [self.scrollView addConstraints:[NSLayoutConstraint
                                     constraintsWithVisualFormat:@"V:[chartBox(200)]-(10)-[bottomBox]"
                                     options:0
                                     metrics:nil
                                     views:@{@"bottomBox" : self.bottomBox, @"chartBox" : self.chartBox}]];
    
    // Below constraint pin to increase content-size
    [self.scrollView addConstraints:[NSLayoutConstraint
                                    constraintsWithVisualFormat:@"V:[bottomBox]-(10)-|"
                                    options:0
                                    metrics:nil
                                    views:@{@"bottomBox" : self.bottomBox}]];
    
    [self.scrollView addConstraints:[NSLayoutConstraint
                                    constraintsWithVisualFormat:@"H:[bottomBox]-(10)-|"
                                    options:0
                                    metrics:nil
                                    views:@{@"bottomBox" : self.bottomBox}]];
    

    第二次将CustomView添加到Card-3此处bluePrintView为CustomView

    _bluePrintView = [[BluePrintView alloc] init];
    self.bluePrintView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.bottomBox addSubview:self.bluePrintView];
    
    [self.bottomBox addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[bluePrintView]|" options:0 metrics:nil views:@{@"bluePrintView":self.bluePrintView}]];
    [self.bottomBox addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[bluePrintView]|" options:0 metrics:nil views:@{@"bluePrintView":self.bluePrintView}]];
    
    CGRect screenRect = [[UIScreen mainScreen] bounds];
    CGFloat screenWidth = screenRect.size.width - 20;
    NSDictionary *metrices = @{@"width" : [NSNumber numberWithFloat:screenWidth]};
    [self.scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(10)-[bottomBox(width)]" options:0 metrics:metrices views:@{ @"bottomBox": self.bottomBox}]];
    

    第三次将TableView添加到CustomView

    self.tableView.tableFooterView = [[UIView alloc] init];
    
    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[tableView]|" options:0 metrics:nil views:@{@"tableView":self.tableView}]];
    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[tableView]|" options:0 metrics:nil views:@{@"tableView":self.tableView}]];
    
    // Height constraint
    CGFloat viewHeight = self.bounds.size.height;
    self.tableHeightConstraint = [NSLayoutConstraint constraintWithItem:self.tableView
                                                              attribute:NSLayoutAttributeHeight
                                                              relatedBy:NSLayoutRelationEqual
                                                                 toItem:nil
                                                              attribute:NSLayoutAttributeNotAnAttribute
                                                             multiplier:1.0
                                                               constant:viewHeight];
    [self addConstraint:self.tableHeightConstraint];
    
    [self.tableView addObserver:self forKeyPath:@"contentSize" options:0 context:NULL];
    

    在观察者方法中,我将更新tableHeightConstraint约束。

    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
        self.tableHeightConstraint.constant = self.tableView.contentSize.height;
        [self.tableView setNeedsLayout];
        [self.tableView layoutIfNeeded];
    }
    

    尝试所有可能性后,最终到此为止。约束警告。

    (
        "<NSLayoutConstraint:0x7fbeb1e7e8e0 V:|-(0)-[UITableView:0x7fbeb2843000]   (Names: '|':BluePrintView:0x7fbeb1e7ac30 )>",
        "<NSLayoutConstraint:0x7fbeb1e7e700 V:[UITableView:0x7fbeb2843000]-(0)-|   (Names: '|':BluePrintView:0x7fbeb1e7ac30 )>",
        "<NSLayoutConstraint:0x7fbeb1e7e9b0 V:[UITableView:0x7fbeb2843000(480)]>",
        "<NSLayoutConstraint:0x7fbeb1e81a20 '_UITemporaryLayoutHeight' V:[BluePrintView:0x7fbeb1e7ac30(0)]>"
    )
    
    Will attempt to recover by breaking constraint 
    <NSLayoutConstraint:0x7fbeb1e7e700 V:[UITableView:0x7fbeb2843000]-(0)-|   (Names: '|':BluePrintView:0x7fbeb1e7ac30 )>
    

    我通过从|移除[tableView]行来解决这些警告(通过删除底部约束到superView),但是tableView没有获得所需的高度。

    任何想法如何获得完整的tableView高度,没有任何约束警告。

    P.S。所有视图都是由代码创建的,没有XIB没有Storyboard布局。 iOS 9.2

1 个答案:

答案 0 :(得分:1)

我没有在约束设置中看到任何错误。

您可能会看到此UITemporaryLayoutHeight约束,因为您添加了contentSize观察者([self.tableView addObserver:self forKeyPath:@"contentSize" options:0 context:NULL] )在视图生命周期中过早,触发[self.tableView layoutIfNeeded]

尝试在viewDidLoad中添加观察者,将其移除到View Controller的dealloc中;或者在viewWillAppear中,然后在viewWillDisappear中将其删除,例如。