UIScrollview add subview horizontally pure autolayout with for loop

人走茶凉 提交于 2019-12-25 16:53:44

问题


I have the following UIView hierarchy:

-UIView
 -UIScrollView

My constraint for UIScrollview with relation to it's super view are very simple:

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

and

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

They are working as expected.

I am trying to add a UIImageView as subview of scrollview Horizontal. So my view hierarchy will become:

-UIView
 -UIScrollView
  -UIImageView

I am adding UIImageView as subview programmatically in UIScrollView using a for loop.

In the for loop, how can I achieve:

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

The problematic section is the bold part. What I have tried:

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];
        }

The approach I can think of:

    LeftSide:
    [scrollview]-10-[UIImageView]
    Right side:
    [UIImageView]-10-[scrollview]
    in between:
    [UIImageView]-10-[UIImageView]

If it's the right approach, then how do I achieve this in for loop.

If it's not then what is best approach.


回答1:


It's quite simple actually. Your approach is correct, all you need is how you convert that into code. I will try to simplify this for you. I am assuming a UIImageView's width & height as 100. You can change as you like

-(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;
    }
}



回答2:


I had encountered similar situation where my scrollview along with its content view was created from IB, but the subviews were added programatically. Writing constraints for subviews was making the View controller bloated. Also the for loop was was getting a lots of ifs and elses,hence I wrote a UIView Subclass to handle this scenario.

Change the class type for you Content View in IB, get a reference of it, add subviews through directly setting the property stackViewItems,or methods -(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

I have uploaded the files here

IEScrollContentView.h IEScrollContentView.h.m



来源:https://stackoverflow.com/questions/33991500/uiscrollview-add-subview-horizontally-pure-autolayout-with-for-loop

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!