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