Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/9.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 使用自动布局分发中心_Ios_Macos_Uiview_Autolayout_Nsview - Fatal编程技术网

Ios 使用自动布局分发中心

Ios 使用自动布局分发中心,ios,macos,uiview,autolayout,nsview,Ios,Macos,Uiview,Autolayout,Nsview,将问题缩小到X轴以简化 给定一个包含两个或多个具有共同祖先的视图的数组,我们如何使用autolayout均匀分布其X中心,以便: 第一个视图与公共祖先左对齐 最后一个视图与公共祖先右对齐 视图的X中心均匀分布 数组按顺序包含视图。对于视图和它们的共同祖先,不能假设其他任何东西。特别是: 视图可以有不同的大小 共同祖先的起源可能不同于(0,0) 公共祖先或任何视图的宽度可能随时更改 在代码中(使用UIView,但同样适用于NSView): -(NSArray*)约束通过分布式中心xofvi

将问题缩小到X轴以简化

给定一个包含两个或多个具有共同祖先的视图的数组,我们如何使用autolayout均匀分布其X中心,以便:

  • 第一个视图与公共祖先左对齐
  • 最后一个视图与公共祖先右对齐
  • 视图的X中心均匀分布
数组按顺序包含视图。对于视图和它们的共同祖先,不能假设其他任何东西。特别是:

  • 视图可以有不同的大小
  • 共同祖先的起源可能不同于(0,0)
  • 公共祖先或任何视图的宽度可能随时更改
在代码中(使用
UIView
,但同样适用于
NSView
):

-(NSArray*)约束通过分布式中心xofview:(NSArray*)视图
{
const NSInteger count=views.count;
NSAssert(计数>=2,@“数组必须至少包含2个视图”);
NSMutableArray*约束=[NSMutableArray];
UIView*sharedAncestor=[views sharedAncestor];//Util方法
UIView*firstView=[views firstObject];
[constraints addObject:[firstView ConstraintByIgngleFTToView:sharedAncestor];//Util方法
UIView*previousView=[self firstObject];
对于(NSInteger i=1;i
我能想到的实现这一点的最佳方法是使用

- (void)addConstraintsToView:(UIView *)view position:(NSInteger)position count:(NSInteger)count offset:(CGFloat)offset {

    view.translatesAutoresizingMaskIntoConstraints = NO;

    [view addConstraint:[NSLayoutConstraint constraintWithItem:view
                                                     attribute:NSLayoutAttributeWidth
                                                     relatedBy:NSLayoutRelationEqual
                                                        toItem:nil
                                                     attribute:NSLayoutAttributeNotAnAttribute
                                                    multiplier:1.0
                                                      constant:view.frame.size.width]];

    [view addConstraint:[NSLayoutConstraint constraintWithItem:view
                                                     attribute:NSLayoutAttributeHeight
                                                     relatedBy:NSLayoutRelationEqual
                                                        toItem:nil
                                                     attribute:NSLayoutAttributeNotAnAttribute
                                                    multiplier:1.0
                                                      constant:view.frame.size.height]];

    CGFloat multiplier = (2.0 / (count - 1)) * position;
    CGFloat middle = (count - 1) / 2;
    CGFloat standard = ((offset / 2) / (count - 1)) * -(position - middle);
    CGFloat constant = (position == 0) ? view.frame.size.width / 2 : (position == count - 1) ? -view.frame.size.width / 2 : standard;

    [self.mainView addConstraint:[NSLayoutConstraint constraintWithItem:view
                                                              attribute:NSLayoutAttributeCenterX
                                                              relatedBy:NSLayoutRelationEqual
                                                                 toItem:self.mainView
                                                              attribute:NSLayoutAttributeCenterX
                                                             multiplier:multipler
                                                               constant:constant]];

    [self.mainView addConstraint:[NSLayoutConstraint constraintWithItem:view
                                                              attribute:NSLayoutAttributeCenterY
                                                              relatedBy:NSLayoutRelationEqual
                                                                 toItem:self.mainView
                                                              attribute:NSLayoutAttributeCenterY
                                                             multiplier:1.0
                                                               constant:0.0]];

}
constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant:

要在superview上均匀间隔子视图中心,请将子视图的
NSLAYUTATTRIBUTECENTERX
约束到
NSLAYUTATTRIBUTECENTERX
superview,并使用乘数变量将其隔开

CGFloat multiplier = (2.0 / (count - 1)) * position
其中
count
array。count
position
array
中的视图索引。这将均匀地分隔视图,但是第一个和最后一个视图不会按要求对齐

为了正确对齐第一个视图,我们只需将
常量设置为
frame.size.wdith/2

为了正确对齐最后一个视图,我们只需将
常量设置为
-(frame.size.width/2)

越来越近了,但是间距有点不正常,所以我们需要再次使用
常量和偏移量。首先我们需要第一个和最后一个视图的总宽度

UIView *viewFirst = array[0];
CGFloat widthFirst = viewFirst.frame.size.width;
UIView *viewLast = array[array.count - 1];
CGFloat widthLast = viewLast.frame.size.width;
CGFloat offset = widthFirst + widthLast;
现在我们可以使用它,结合
count
position
来偏移所有其他视图

CGFloat middle = (count - 1) / 2; // work out the centre of the array
CGFloat constant = ((offset / 2) / (count - 1)) * -(position - middle);
将所有这些放在一个方法中

- (void)addConstraintsToView:(UIView *)view position:(NSInteger)position count:(NSInteger)count offset:(CGFloat)offset {

    view.translatesAutoresizingMaskIntoConstraints = NO;

    [view addConstraint:[NSLayoutConstraint constraintWithItem:view
                                                     attribute:NSLayoutAttributeWidth
                                                     relatedBy:NSLayoutRelationEqual
                                                        toItem:nil
                                                     attribute:NSLayoutAttributeNotAnAttribute
                                                    multiplier:1.0
                                                      constant:view.frame.size.width]];

    [view addConstraint:[NSLayoutConstraint constraintWithItem:view
                                                     attribute:NSLayoutAttributeHeight
                                                     relatedBy:NSLayoutRelationEqual
                                                        toItem:nil
                                                     attribute:NSLayoutAttributeNotAnAttribute
                                                    multiplier:1.0
                                                      constant:view.frame.size.height]];

    CGFloat multiplier = (2.0 / (count - 1)) * position;
    CGFloat middle = (count - 1) / 2;
    CGFloat standard = ((offset / 2) / (count - 1)) * -(position - middle);
    CGFloat constant = (position == 0) ? view.frame.size.width / 2 : (position == count - 1) ? -view.frame.size.width / 2 : standard;

    [self.mainView addConstraint:[NSLayoutConstraint constraintWithItem:view
                                                              attribute:NSLayoutAttributeCenterX
                                                              relatedBy:NSLayoutRelationEqual
                                                                 toItem:self.mainView
                                                              attribute:NSLayoutAttributeCenterX
                                                             multiplier:multipler
                                                               constant:constant]];

    [self.mainView addConstraint:[NSLayoutConstraint constraintWithItem:view
                                                              attribute:NSLayoutAttributeCenterY
                                                              relatedBy:NSLayoutRelationEqual
                                                                 toItem:self.mainView
                                                              attribute:NSLayoutAttributeCenterY
                                                             multiplier:1.0
                                                               constant:0.0]];

}
因此,在
viewDidLoad
中,计算偏移量并在每次调用此方法时遍历视图数组

UIView *viewFirst = array[0];
CGFloat widthFirst = viewFirst.frame.size.width;
UIView *viewLast = array[array.count - 1];
CGFloat widthLast = viewLast.frame.size.width;
CGFloat offset = widthFirst + widthLast;

for(NSInteger i = 0; i < array.count; i++) {
    UIView *view = array[i];
    [self.mainView addSubview:view];
    [self addConstraintsToView:view position:i count:array.count offset:offset];
}
UIView*viewFirst=array[0];
CGFloat WITHFIRST=viewFirst.frame.size.WITH;
UIView*viewLast=array[array.count-1];
CGFloat WITHLAST=viewLast.frame.size.WITH;
CGFloat偏移=宽度第一+宽度最后;
对于(NSInteger i=0;i
嘿,普雷斯托

编辑:
只是注意到这并不完全正确,因为当第一个视图和最后一个视图的宽度不同时,它不会正确偏移,但希望您能理解这一点(如果它们都是相同的,这将非常有效)

我认为这应该可行。它将创建间隔,并在任意一侧的视图中心和间隔的左、右边缘之间添加约束。该方法的设置假设您已经创建了所有视图,但尚未将它们添加到superview中。就这样说吧,

[self equallySpaceCentersOfViews:@[l1,l2,l3,l4] inView:someView];
// add a constraint here to vertically place one of the views in someView (all the views have their centerY's equal)
这是方法

-(void)equallySpaceCentersOfViews:(NSArray *) views inView:(UIView *) superview {

    //create and add all the spacers to the superview
    NSMutableArray *spacers = [NSMutableArray new];
    for (int i =0; i<views.count - 1; i++) {
        UIView *spacer = [UIView new];
        spacer.translatesAutoresizingMaskIntoConstraints = NO;
        [superview addSubview:spacer];
        [spacers addObject:spacer];
    }

    //Add all the views to the superview.
    for (UIView *obj in views) {
        [obj setTranslatesAutoresizingMaskIntoConstraints:NO];
        [superview addSubview:obj];
    }

    // Create the constraints to the two edges
    [superview addConstraint:[NSLayoutConstraint constraintWithItem:views[0] attribute:NSLayoutAttributeLeft relatedBy:0 toItem:superview attribute:NSLayoutAttributeLeft multiplier:1 constant:0]];
    [superview addConstraint:[NSLayoutConstraint constraintWithItem:views.lastObject attribute:NSLayoutAttributeRight relatedBy:0 toItem:superview attribute:NSLayoutAttributeRight multiplier:1 constant:0]];

    //Create the constraints between the views and spacers
    [views enumerateObjectsUsingBlock:^(UIView *obj, NSUInteger idx, BOOL *stop) {
        [superview addConstraint:[NSLayoutConstraint constraintWithItem:obj attribute:NSLayoutAttributeCenterX relatedBy:0 toItem:spacers[idx] attribute:NSLayoutAttributeLeft multiplier:1 constant:0]];
        [superview addConstraint:[NSLayoutConstraint constraintWithItem:obj attribute:NSLayoutAttributeCenterY relatedBy:0 toItem:spacers[idx] attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];
        [superview addConstraint:[NSLayoutConstraint constraintWithItem:views[idx+1] attribute:NSLayoutAttributeCenterX relatedBy:0 toItem:spacers[idx] attribute:NSLayoutAttributeRight multiplier:1 constant:0]];
        [superview addConstraint:[NSLayoutConstraint constraintWithItem:views[idx+1] attribute:NSLayoutAttributeCenterY relatedBy:0 toItem:spacers[idx] attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];
        if (idx+1 == views.count-1) *stop = YES;
    }];

    //Make all the spacers have the same width
    [spacers enumerateObjectsUsingBlock:^(UIView *spacer, NSUInteger idx, BOOL *stop) {
        [superview addConstraint:[NSLayoutConstraint constraintWithItem:spacer attribute:NSLayoutAttributeWidth relatedBy:0 toItem:spacers[idx+1] attribute:NSLayoutAttributeWidth multiplier:1 constant:0]];
        if (idx+1 == spacers.count-1) *stop = YES;
    }];
}
-(void)相等空间中心视图:(NSArray*)视图中的视图:(UIView*)超级视图{
//创建所有间隔并将其添加到superview
NSMUTABLEARRY*间隔符=[NSMUTABLEARRY new];

对于(int i=0;i您假设共享祖先和视图具有固定的宽度。感谢您的尝试。添加图形的功劳如下:)对于可变宽度的共享祖先,这应该可以很好地工作,但我同意,如果子视图的宽度不固定,它将失败。有了这么多的变量,您可能会更好地覆盖布局子视图,并在这里计算每个视图的框架,而不是使用约束。我很好奇为什么您希望以这种方式排列视图。我认为眼睛将当你与中心的间距相等时,视图之间的间距将不均匀。这个问题相当复杂,特别是当你的最终目标是在二维空间中进行此操作时。你首先需要弄清楚哪个视图最宽,如果它有两个相邻视图,哪一个更宽以确定最小值中心间距离不会导致视图重叠。我同意Michael Platt的意见;这不是自动布局的真正工作。@rdelmar配送中心是一个常见的设计要求。作为一种操作,它在Photoshop和Illustrator中被广泛使用。这在autolayout中无法实现是一个有效的答案,顺便说一句:)好的,我想我不能这样做nk的情况下,这看起来不错,但我不是一个设计师(我的艺术天赋接近于零)。我想我可能是太匆忙了,排除了自动布局。我要尝试一些东西。如果可行,我会发布一个答案。谢谢@rdelmar。我会稍后发布我所做的。