Ios UIScrollview使用for循环水平添加子视图纯自动布局

Ios UIScrollview使用for循环水平添加子视图纯自动布局,ios,autolayout,Ios,Autolayout,我有以下ui视图层次结构: -UIView -UIScrollView 我对UIScrollview与其超级视图的约束非常简单: @"H:|-%f-[%@]-%f-|" 及 他们正在按预期工作。 我正在尝试添加一个UIImageView作为scrollview水平视图的子视图。 因此,我的视图层次结构将变为: -UIView -UIScrollView -UIImageView 我在uicrollview中使用for循环以编程方式将UIImageView添加为子视图 在for循环中

我有以下
ui视图
层次结构:

-UIView
 -UIScrollView
我对
UIScrollview
与其超级视图的约束非常简单:

@"H:|-%f-[%@]-%f-|"

他们正在按预期工作。

我正在尝试添加一个
UIImageView
作为scrollview水平视图的子视图。 因此,我的视图层次结构将变为:

-UIView
 -UIScrollView
  -UIImageView
我在
uicrollview
中使用
for
循环以编程方式将
UIImageView
添加为子视图

for
循环中,我如何实现:

[SuperView]-10-[scrollview]-10-[UIImageView]-10-[UIImageView]-10-[UIScrollView]-10-[SuperView]

有问题的部分是粗体部分。 我所尝试的:

for(int i=1;i<3;i++)
        {
            UIImageView *image = [[UIImageView alloc] init];
            [image setImage:[UIImage imageNamed:[NSString stringWithFormat:@"%d.jpg",i]]];
            image.translatesAutoresizingMaskIntoConstraints = NO;
            [_scrollView addSubview:image];

            UIView *superView = _scrollView;



            NSDictionary * views = NSDictionaryOfVariableBindings(superView, image);

            NSString *formate = [NSString stringWithFormat:@"H:|-%f-[%@]-%f-|", scrollViewLeftMarginFromParent, @"image", scrollViewRightMarginFromParent];

            NSArray * WIDTH_CONSTRAINT = [NSLayoutConstraint constraintsWithVisualFormat:formate options:0 metrics:nil views:views];

            formate = [NSString stringWithFormat:@"V:|-%f-[%@]-%f-|", scrollViewTopMarginFromParent, @"image", scrollViewBottomMarginFromParent];

            NSArray * HEIGHT_CONSTRAINT = [NSLayoutConstraint constraintsWithVisualFormat:formate options:0 metrics:nil views:views];
            [superView addConstraints:WIDTH_CONSTRAINT];
            [superView addConstraints:HEIGHT_CONSTRAINT];
        }
如果这是正确的方法,那么如何在
for
循环中实现这一点


如果不是,那么什么是最好的方法。

其实很简单。您的方法是正确的,您所需要的只是如何将其转换为代码。我会尽量为你简化这件事。我假设UIImageView的宽度和高度为100。你可以随意改变

-(void)setUI
{
    lastView = nil;   //Declare a UIImageView* as instance var.
    arrayCount = [array count]; //In your case a static count of 3

    for(NSInteger index =0; index < arrayCount; index++)
    {
        UIImageView *view = [[UIImageView alloc] init];
        [self.mainScroll addSubview:view];

        [view setTranslatesAutoresizingMaskIntoConstraints:NO];

        [self.mainScroll addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-20-[view(100)]-20-|" options:0 metrics:nil views:@{@"view":view}]];

        //--> If view is first then pin the leading edge to main ScrollView otherwise to the last View.
        if(lastView == nil && index == 0) {
            [self.mainScroll addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-10-[view(100)]" options:0 metrics:nil views:@{@"view":view}]];
        }
        else {
            [self.mainScroll addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[lastView]-10-[view(100)]" options:0 metrics:nil views:@{@"lastView":lastView, @"view":view}]];
        }
        //--> If View is last then pin the trailing edge to mainScrollView trailing edge.
        if(index == arrayCount-1) {
            [self.mainScroll addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[view]-10-|" options:0 metrics:nil views:@{@"view":view}]];
        }
        //--> Assign the current View as last view to keep the reference for next View.
        lastView = view;
    }
}
-(void)setUI
{
lastView=nil;//将UIImageView*声明为实例变量。
arrayCount=[array count];//在本例中,静态计数为3
对于(NSInteger index=0;index如果视图是第一个视图,则将前缘固定到主滚动视图,否则固定到最后一个视图。
if(lastView==nil&&index==0){
[self.main Scroll addConstraints:[NSLayoutConstraintsWithVisualFormat:@“H:|-10-[view(100)]选项:0度量:无视图:@{“view”:view}]];
}
否则{
[self.main Scroll addConstraints:[NSLayoutConstraintsWithVisualFormat:@“H:[lastView]--10-[view(100)]选项:0度量:无视图:@{“lastView”:lastView,@“view”:view}];
}
//-->如果视图是最后一个视图,则将后缘固定到主滚动视图后缘。
if(索引==arrayCount-1){
[self.main Scroll addConstraints:[NSLayoutConstraintsWithVisualFormat:@“H:[view]--10-|”选项:0度量:无视图:@{“view”:view}];
}
//-->将当前视图指定为最后一个视图,以保留下一个视图的参照。
lastView=视图;
}
}

其实很简单。您的方法是正确的,您所需要的只是如何将其转换为代码。我会尽量为你简化这件事。我假设UIImageView的宽度和高度为100。你可以随意改变

-(void)setUI
{
    lastView = nil;   //Declare a UIImageView* as instance var.
    arrayCount = [array count]; //In your case a static count of 3

    for(NSInteger index =0; index < arrayCount; index++)
    {
        UIImageView *view = [[UIImageView alloc] init];
        [self.mainScroll addSubview:view];

        [view setTranslatesAutoresizingMaskIntoConstraints:NO];

        [self.mainScroll addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-20-[view(100)]-20-|" options:0 metrics:nil views:@{@"view":view}]];

        //--> If view is first then pin the leading edge to main ScrollView otherwise to the last View.
        if(lastView == nil && index == 0) {
            [self.mainScroll addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-10-[view(100)]" options:0 metrics:nil views:@{@"view":view}]];
        }
        else {
            [self.mainScroll addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[lastView]-10-[view(100)]" options:0 metrics:nil views:@{@"lastView":lastView, @"view":view}]];
        }
        //--> If View is last then pin the trailing edge to mainScrollView trailing edge.
        if(index == arrayCount-1) {
            [self.mainScroll addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[view]-10-|" options:0 metrics:nil views:@{@"view":view}]];
        }
        //--> Assign the current View as last view to keep the reference for next View.
        lastView = view;
    }
}
-(void)setUI
{
lastView=nil;//将UIImageView*声明为实例变量。
arrayCount=[array count];//在本例中,静态计数为3
对于(NSInteger index=0;index如果视图是第一个视图,则将前缘固定到主滚动视图,否则固定到最后一个视图。
if(lastView==nil&&index==0){
[self.main Scroll addConstraints:[NSLayoutConstraintsWithVisualFormat:@“H:|-10-[view(100)]选项:0度量:无视图:@{“view”:view}]];
}
否则{
[self.main Scroll addConstraints:[NSLayoutConstraintsWithVisualFormat:@“H:[lastView]--10-[view(100)]选项:0度量:无视图:@{“lastView”:lastView,@“view”:view}];
}
//-->如果视图是最后一个视图,则将后缘固定到主滚动视图后缘。
if(索引==arrayCount-1){
[self.main Scroll addConstraints:[NSLayoutConstraintsWithVisualFormat:@“H:[view]--10-|”选项:0度量:无视图:@{“view”:view}];
}
//-->将当前视图指定为最后一个视图,以保留下一个视图的参照。
lastView=视图;
}
}

我遇到过类似的情况,我的scrollview及其内容视图是从IB创建的,但子视图是通过编程方式添加的。为子视图编写约束使视图控制器膨胀。for循环也得到了大量的ifs和else,因此我编写了一个UIView子类来处理这个场景

在IB中更改内容视图的类类型,获取其引用,通过直接设置属性
stackViewItems
,或方法
-(void)insertStackItem:
-(void)insertStackItem:atIndex:

#import "IEScrollContentView.h"

@interface IEScrollContentView()
{
    NSMutableArray * _stackViewItems;
}

@property (nonatomic,strong) NSLayoutConstraint * topConstraint;
@property (nonatomic,strong) NSLayoutConstraint * bottomConstraint;

@end

@implementation IEScrollContentView

@synthesize stackViewItems = _stackViewItems;

//-----------------------------------------------------------------//
#pragma mark - Init Methods
//-----------------------------------------------------------------//

-(instancetype)initWithCoder:(NSCoder *)aDecoder {
    if(self = [super initWithCoder:aDecoder])
        _stackViewItems = [NSMutableArray new];
    return self;
}

-(instancetype)initWithFrame:(CGRect)frame {
    if(self = [super initWithFrame:frame])
        _stackViewItems = [NSMutableArray new];
    return self;
}

//-----------------------------------------------------------------//
#pragma mark - Public Methods
//-----------------------------------------------------------------//

-(void)setStackViewItems:(NSArray *)stackViewItems {
    if(!_stackViewItems)
        _stackViewItems = [NSMutableArray new];

    for (UIView * view in stackViewItems) {
        [self insertStackItem:view];
    }
}

-(void)insertStackItem:(UIView *)stackItem
{
    [self insertStackItem:stackItem atIndex:_stackViewItems.count];
}

-(void)insertStackItem:(UIView *)stackItem atIndex:(NSUInteger)index
{
    if(!stackItem || index > _stackViewItems.count)return;

    if(index == 0)
        [self addView:stackItem
            belowView:self
            aboveView:_stackViewItems.count>0?_stackViewItems.firstObject:self];

    else if(index==_stackViewItems.count)
        [self addView:stackItem
            belowView:_stackViewItems[index-1]
            aboveView:self];
    else
        [self addView:stackItem
            belowView:_stackViewItems[index-1]
            aboveView:_stackViewItems[index]];
}

//-----------------------------------------------------------------//
#pragma mark - Constraining Views
//-----------------------------------------------------------------//

-(void)addView:(UIView *)view belowView:(UIView *)viewAbove aboveView:(UIView *)viewBelow {

    view.translatesAutoresizingMaskIntoConstraints = NO;
    [self addSubview:view];

    NSArray * defaultConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[view]-0-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(view)];
    NSLayoutConstraint * upperConstraint,* lowerConstraint;

    if(viewAbove==self) {
        [self removeConstraint:_topConstraint];
        upperConstraint = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[view]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(view)].firstObject;
        _topConstraint = upperConstraint;
    }
    else
        upperConstraint = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[viewAbove]-0-[view]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(view,viewAbove)].firstObject;

    if(viewBelow==self) {
        [self removeConstraint:_bottomConstraint];
        lowerConstraint = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[view]-0-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(view)].firstObject;
        _bottomConstraint = lowerConstraint;
    }
    else
        lowerConstraint = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[view]-0-[viewBelow]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(view,viewBelow)].firstObject;

    [self addConstraints:defaultConstraints];
    [self addConstraints:@[upperConstraint,lowerConstraint]];

    [_stackViewItems addObject:view];
}

@end
我已经把文件上传到这里了


我遇到过类似的情况,我的scrollview及其内容视图是从IB创建的,但子视图是通过编程方式添加的。为子视图编写约束使视图控制器膨胀。for循环也得到了大量的ifs和else,因此我编写了一个UIView子类来处理这个场景

在IB中更改内容视图的类类型,获取其引用,通过直接设置属性
stackViewItems
,或方法
-(void)insertStackItem:
-(void)insertStackItem:atIndex:

#import "IEScrollContentView.h"

@interface IEScrollContentView()
{
    NSMutableArray * _stackViewItems;
}

@property (nonatomic,strong) NSLayoutConstraint * topConstraint;
@property (nonatomic,strong) NSLayoutConstraint * bottomConstraint;

@end

@implementation IEScrollContentView

@synthesize stackViewItems = _stackViewItems;

//-----------------------------------------------------------------//
#pragma mark - Init Methods
//-----------------------------------------------------------------//

-(instancetype)initWithCoder:(NSCoder *)aDecoder {
    if(self = [super initWithCoder:aDecoder])
        _stackViewItems = [NSMutableArray new];
    return self;
}

-(instancetype)initWithFrame:(CGRect)frame {
    if(self = [super initWithFrame:frame])
        _stackViewItems = [NSMutableArray new];
    return self;
}

//-----------------------------------------------------------------//
#pragma mark - Public Methods
//-----------------------------------------------------------------//

-(void)setStackViewItems:(NSArray *)stackViewItems {
    if(!_stackViewItems)
        _stackViewItems = [NSMutableArray new];

    for (UIView * view in stackViewItems) {
        [self insertStackItem:view];
    }
}

-(void)insertStackItem:(UIView *)stackItem
{
    [self insertStackItem:stackItem atIndex:_stackViewItems.count];
}

-(void)insertStackItem:(UIView *)stackItem atIndex:(NSUInteger)index
{
    if(!stackItem || index > _stackViewItems.count)return;

    if(index == 0)
        [self addView:stackItem
            belowView:self
            aboveView:_stackViewItems.count>0?_stackViewItems.firstObject:self];

    else if(index==_stackViewItems.count)
        [self addView:stackItem
            belowView:_stackViewItems[index-1]
            aboveView:self];
    else
        [self addView:stackItem
            belowView:_stackViewItems[index-1]
            aboveView:_stackViewItems[index]];
}

//-----------------------------------------------------------------//
#pragma mark - Constraining Views
//-----------------------------------------------------------------//

-(void)addView:(UIView *)view belowView:(UIView *)viewAbove aboveView:(UIView *)viewBelow {

    view.translatesAutoresizingMaskIntoConstraints = NO;
    [self addSubview:view];

    NSArray * defaultConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[view]-0-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(view)];
    NSLayoutConstraint * upperConstraint,* lowerConstraint;

    if(viewAbove==self) {
        [self removeConstraint:_topConstraint];
        upperConstraint = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[view]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(view)].firstObject;
        _topConstraint = upperConstraint;
    }
    else
        upperConstraint = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[viewAbove]-0-[view]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(view,viewAbove)].firstObject;

    if(viewBelow==self) {
        [self removeConstraint:_bottomConstraint];
        lowerConstraint = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[view]-0-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(view)].firstObject;
        _bottomConstraint = lowerConstraint;
    }
    else
        lowerConstraint = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[view]-0-[viewBelow]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(view,viewBelow)].firstObject;

    [self addConstraints:defaultConstraints];
    [self addConstraints:@[upperConstraint,lowerConstraint]];

    [_stackViewItems addObject:view];
}

@end
我已经把文件上传到这里了


您要求的似乎是算法修复,与
ios
autolayout
没有直接关系。您要求的似乎是算法修复,与
ios
autolayout
没有直接关系。