以编程方式在子视图中创建约束

时间:2014-04-07 17:18:37

标签: objective-c ios7 autolayout nsautolayout

我最近试图找出自动布局。几乎我认为我用编辑器理解它,但是当它以编程方式管理它时,它真的很难。

无论如何,让我解释一下我试图解决的问题;

我有一个带autolayout的tableviewcell。在这个单元格中,我有一个子视图,我想稍后用代码填充它。到目前为止还不错。 我也是一个自动布局设计的自定义视图控制器。我想要完成的是重复n次这些不同的视图控制器实例在子视图中查看,其余边距为10px到前一项。

以下是视图的层次结构;

--cell
----label1
----label2
----subview
------view controller's view 1
------view controller's view 2 
------view controller's view 3
..
..
------view controller's view n
----button
----button

这是我到目前为止所提供的代码;

self是指tableviewcell self.workoutView指的是subview SPPostWorkoutItemViewController指的是内部controllers

SPPostWorkoutItemViewController *previousController = nil;

    for(int i=0; i < p.workout.workoutItems.count; i++ ){

        WorkoutItem *workoutItem = p.workout.workoutItems[i];
        SPPostWorkoutItemViewController *workoutItemController = [[SPPostWorkoutItemViewController alloc]initWithWorkoutItem:workoutItem];

        if(previousController == nil){

            NSLayoutConstraint * cons = [NSLayoutConstraint constraintWithItem:workoutItemController.view
                                                                 attribute:NSLayoutAttributeTop
                                                                 relatedBy:NSLayoutRelationEqual
                                                                    toItem:self.workoutView
                                                                 attribute:NSLayoutAttributeTop
                                                                multiplier:1.0
                                                                  constant:10];

            [self.workoutView addConstraint:cons];
        }
        else{

            NSLayoutConstraint * cons = [NSLayoutConstraint constraintWithItem:workoutItemController.view
                                                                     attribute:NSLayoutAttributeTop
                                                                     relatedBy:NSLayoutRelationEqual
                                                                        toItem:previousController.view
                                                                     attribute:NSLayoutAttributeTop
                                                                    multiplier:1.0
                                                                      constant:10];

            [self.workoutView addConstraint:cons];
        }


        [self.workoutView addSubview:workoutItemController.view];
        previousController = workoutItemController;


    }

1 个答案:

答案 0 :(得分:0)

这是我带来的最终解决方案。它的工作完美。 我使用了Masonry布局框架。它确实简化了自动布局语法并使其更具可读性。

让自动布局正常工作。

  • 容器视图没有高度约束
  • top subview具有从顶部
  • 的容器视图的约束
  • 每个子视图都具有前一个子视图的最高约束
  • 最后一个子视图具有从底部开始的容器视图的约束

另外,为了正确地扩展子视图,我需要在子视图中定义标签约束。我跟着this answer,它解释得很完美。

最后代码是,希望它能帮助别人;

SPPostWorkoutItemViewController *previousController = nil;

for(int i=0; i < p.workout.workoutItems.count; i++ ){

    WorkoutItem *workoutItem = p.workout.workoutItems[i];
    SPPostWorkoutItemViewController *workoutItemController = [[SPPostWorkoutItemViewController alloc]initWithWorkoutItem:workoutItem];


    [self.workoutView addSubview:workoutItemController.view];

    //first workout item so margin with parent
    //also margin 6 pixel to parent from left side
    if(previousController == nil){

        [workoutItemController.view mas_makeConstraints: ^(MASConstraintMaker *make) {

            make.top.equalTo(self.workoutView.mas_top).with.offset(0);
            make.left.equalTo(self.workoutView.mas_left).with.offset(6);
        }];
    }
    else{

        //second workout item margin with previous one
        [workoutItemController.view mas_makeConstraints: ^(MASConstraintMaker *make) {

            make.top.equalTo(previousController.view.mas_bottom).with.offset(5);
            make.left.equalTo(self.workoutView.mas_left).with.offset(6);
        }];
    }

    //don't forget to margin last workout item with parent's bottom
    if(i == (p.workout.workoutItems.count - 1)){

        [workoutItemController.view mas_makeConstraints: ^(MASConstraintMaker *make) {

            make.bottom.equalTo(self.workoutView.mas_bottom).with.offset(0);
        }];
    }

    previousController = workoutItemController;        
}