Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/94.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 使用NSLayoutConstraints将任意数量的元素均匀地隔开几行_Ios_Objective C_Autolayout_Nslayoutconstraint - Fatal编程技术网

Ios 使用NSLayoutConstraints将任意数量的元素均匀地隔开几行

Ios 使用NSLayoutConstraints将任意数量的元素均匀地隔开几行,ios,objective-c,autolayout,nslayoutconstraint,Ios,Objective C,Autolayout,Nslayoutconstraint,我有一个关于在以下场景中使用布局约束的问题。一切都是代码(没有笔尖或故事板)。我想创建一个包含任意行项目的视图。每行包含任意数量的子视图 为了创建这个视图,我想传入一个两层深的数组。第一级数组包含每一行。第二级数组包含每行中的元素。例如,这可能看起来像这样: // These constraints force the rows to collectively fill gridView: rowView0.top = gridView.top rowView1.top = rowView0.b

我有一个关于在以下场景中使用布局约束的问题。一切都是代码(没有笔尖或故事板)。我想创建一个包含任意行项目的视图。每行包含任意数量的子视图

为了创建这个视图,我想传入一个两层深的数组。第一级数组包含每一行。第二级数组包含每行中的元素。例如,这可能看起来像这样:

// These constraints force the rows to collectively fill gridView:
rowView0.top = gridView.top
rowView1.top = rowView0.bottom + 10
rowView2.top = rowView1.bottom + 10
gridView.bottom = rowView2.bottom

// These constraints force the rows to have equal heights:
rowView1.height = rowView0.height
rowView2.height = rowView0.height

// These constraints force the rows to each be the width of gridView:
rowView0.leading = gridView.leading
rowView0.trailing = gridView.trailing
rowView1.leading = gridView.leading
rowView1.trailing = gridView.trailing
rowView2.leading = gridView.leading
rowView2.trailing = gridView.trailing
NSArray*元素=@[[subview1,subview2,subview3],@[subview4],@[subview5,subview6]

在此数组中,将有3行:

1) 第1行:子视图1、子视图2、子视图3
2) 第2行:子视图4
3) 第3行:子视图5、子视图6

我希望这些元素的格式为:

-所有行都应该是其父视图的全宽(为此,我们可以假定它是屏幕的大小)
-一行中的每个元素应具有相同的宽度,并且它们之间具有相同的空间量(例如,如果有4个元素,则1&2和2&3之间的空间可能为10pt)
-每行之间的垂直间距应相同(例如,每行之间的垂直间距为10pt)

在上面的场景中,第1行将有3个等宽等距的子视图,第2行将有1个占据该行全宽的子视图,第3行将有2个等宽等距的子视图

所以,问题是,我该怎么做

我已经为此工作了一段时间,我的理解似乎没有得到任何改善。谢谢你的帮助

您可以使用autolayout来实现这一点,但我认为如果您只是将
UICollectionView
与您自己的自定义
UICollectionViewLayout
子类一起使用,您的代码实际上会更容易理解

如果您真的想使用autolayout,我认为您应该通过引入中间级别的“行”视图,使视图层次结构与阵列层次结构相匹配:

gridView
├─ rowView0
│  ├─ subview1
│  ├─ subview2
│  └─ subview3
├─ rowView1
│  └─ subview4
└─ rowView2
   ├─ subview5
   └─ subview6
现在可以对行设置如下约束:

// These constraints force the rows to collectively fill gridView:
rowView0.top = gridView.top
rowView1.top = rowView0.bottom + 10
rowView2.top = rowView1.bottom + 10
gridView.bottom = rowView2.bottom

// These constraints force the rows to have equal heights:
rowView1.height = rowView0.height
rowView2.height = rowView0.height

// These constraints force the rows to each be the width of gridView:
rowView0.leading = gridView.leading
rowView0.trailing = gridView.trailing
rowView1.leading = gridView.leading
rowView1.trailing = gridView.trailing
rowView2.leading = gridView.leading
rowView2.trailing = gridView.trailing
这些约束应该是必要的(即不过度约束)和充分的(即不含糊)

然后,可以对每行应用相同的约束方案,并交换X轴和Y轴。例如,您可以在第0行中使用这些约束:

// These constraints collectively force the cells to fill rowView0:
subview1.leading = rowView0.leading
subview2.leading = subview1.trailing + 10
subview3.leading = subview2.trailing + 10
rowView0.trailing = subview3.trailing

// These constraints force the cells to have equal widths:
subview2.width = subview1.width
subview3.width = subview1.width

// These constraints force the cells to each be the height of rowView0:
subview1.height = rowView0.height
subview2.height = rowView0.height
subview3.height = rowView0.height

我想这样应该行得通。我试着在一般情况下创建,所以它应该适用于不同的行数和每行的元素数

#define subviewHeight 44
#define spaceFromTop 10
#define spaceFromSide 10
#define subviewVerticalSpacing 10
#define subviewHorizontalSpacing 10

@implementation ViewController

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    UIButton *subview1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [subview1 setTitle:@"View 1" forState:UIControlStateNormal];
    UIButton *subview2 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [subview2 setTitle:@"View 2" forState:UIControlStateNormal];
    UIButton *subview3 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [subview3 setTitle:@"View 3" forState:UIControlStateNormal];
    UIButton *subview4 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [subview4 setTitle:@"View 4" forState:UIControlStateNormal];
    UIButton *subview5 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [subview5 setTitle:@"View 5" forState:UIControlStateNormal];
    UIButton *subview6 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [subview6 setTitle:@"View 6" forState:UIControlStateNormal];

    NSArray *arrayOfSubviews = @[@[subview1, subview2, subview3], @[subview4], @[subview5, subview6]];

    [self addSubviewsWithConstraints:arrayOfSubviews];

}

-(void)addSubviewsWithConstraints:(NSArray *) arrayOfArrays {
    NSMutableArray *arrayOfViewsDicts = [NSMutableArray array]; // make the views dictionaries needed for the views parameter of constraintsWithVisualFormat:options:metrics:views:. One for each row.

    for (NSArray *array in arrayOfArrays) {
        NSMutableDictionary *dict = [NSMutableDictionary dictionary];
        for (int i = 0; i < array.count; i++) {
            [dict setObject:array[i] forKey:[NSString stringWithFormat:@"view%d",i]];
        }
        [arrayOfViewsDicts addObject:dict];
    }

    for (int i=0; i<arrayOfArrays.count; i++) {
        NSString *formatString = [self makeConstraintsForRowOfSubviews:arrayOfArrays[i] withViewsDict:arrayOfViewsDicts[i]]; // Make the format string for a row of subviews

        for (id subview in arrayOfArrays[i]) {
            [subview setTranslatesAutoresizingMaskIntoConstraints:NO];
            [self.view addSubview:subview];
            NSLayoutConstraint *heightCon = [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeHeight relatedBy:0 toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:subviewHeight];
            [subview addConstraint:heightCon];

            NSLayoutConstraint *verticalCon = [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeTop relatedBy:0 toItem:self.view attribute:NSLayoutAttributeTop multiplier:1 constant:spaceFromTop + ((subviewHeight + subviewVerticalSpacing)*i)];
            [self.view addConstraint:verticalCon];
        }
        NSArray *cons = [NSLayoutConstraint constraintsWithVisualFormat:formatString options:NSLayoutFormatAlignAllBottom metrics:nil views:arrayOfViewsDicts[i]];

        [self.view addConstraints:cons];
    }
}


-(NSString *) makeConstraintsForRowOfSubviews:(NSArray *) arrayOfSubviews withViewsDict:(NSDictionary *) viewsDict {
    NSMutableString *formatString = [NSMutableString string];

    for (int i = 0; i<arrayOfSubviews.count; i++) {
        if (i == 0) {
            [formatString appendFormat:@"|-%d-[%@]",spaceFromSide,[viewsDict allKeysForObject:arrayOfSubviews[i]][0]];
        }else{
            [formatString appendFormat:@"-%d-[%@(==view0)]",subviewHorizontalSpacing,[viewsDict allKeysForObject:arrayOfSubviews[i]][0]];
        }
    }

    [formatString appendFormat:@"-%d-|",spaceFromSide];
    return formatString;
}
#定义子视图高度44
#从前10名定义空格
#从10边定义空格
#定义子视图垂直间距10
#定义子视图水平间距10
@实现视图控制器
-(无效)视图显示:(BOOL)动画{
[超级视图显示:动画];
UIButton*子视图1=[UIButton Button类型为:UIButtonyPeroundRect];
[子视图1设置标题:@“视图1”表示状态:UIControlStateNormal];
UIButton*子视图2=[UIButton-Button类型:UIButtonyPeroundRect];
[子视图2设置标题:@“视图2”用于状态:UIControlStateNormal];
UIButton*子视图3=[UIButton Button类型为:UIButtonyPeroundRect];
[子视图3设置标题:@“视图3”表示状态:UIControlStateNormal];
UIButton*子视图4=[UIButton Button类型为:UIButtonyPeroundRect];
[子视图4设置标题:@“视图4”用于状态:UIControlStateNormal];
UIButton*子视图5=[UIButton Button类型为:UIButtonyPeroundRect];
[子视图5设置标题:@“视图5”表示状态:UIControlStateNormal];
UIButton*子视图6=[UIButton Button类型为:UIButtonyPeroundRect];
[子视图6设置标题:@“视图6”用于状态:UIControlStateNormal];
NSArray*arrayOfSubviews=@[[subview1,subview2,subview3],@[subview4],@[subview5,subview6];
[self-addSubviewsWithConstraints:arrayOfSubviews];
}
-(void)添加子视图约束:(NSArray*)ArrayOfarray{
NSMutableArray*arrayOfViewsDicts=[NSMutableArray];//使用VisualFormat:options:metrics:views:。为每行创建Constraints的views参数所需的视图字典。
用于(NSArray*阵列中的阵列Farrays){
NSMutableDictionary*dict=[NSMutableDictionary];
对于(int i=0;i对于(int i=0;我是确定10磅间距,还是希望autolayout选择间距?如果希望autolayout选择间距,您希望它如何选择?@robmayoff我会输入我想要的间距量--它不会由autolayouts计算。嘿,Rob--感谢您的反馈。Re:UICollectionView,这会很好在许多情况下都有意义,但我这里使用的是在UITableView的页眉或页脚中放置几行按钮(类似于iOS联系人)。对于您的答案,如果行数和每行中的元素数是一致的,这肯定会起作用。不幸的是,我正在尝试构造这样一个数组,以便可以传递任意行数的数组,每个行中都有任意数目的元素。我想我需要做的是为每行创建一个UIView,然后iter遍历行的元素并创建相应的NSLayoutAttributeTracing约束(在此之前,我可能必须计算宽度)。然后,我想我需要遍历每一行,将每一行添加到最终的UIView中,并为每一行视图添加一个新的约束,该约束提供了适当的NSLayoutAttributeTop/Bottom。从概念上讲,这听起来很合理,但我在实现它时遇到了困难:(非常有用。感谢@rdelmar!您构建VFL格式字符串的方式很聪明。