// // StackableViewController.m // myverizon // // Created by Scott Pfeil on 3/26/14. // Copyright (c) 2014 Verizon Wireless. All rights reserved. // #import "StackableViewController.h" #import "MFStyler.h" #import "ViewConstrainingView.h" @interface StackableViewController () @end @implementation StackableViewController - (void)newDataBuildScreen { [super newDataBuildScreen]; // Removes all the subviews so they can be updated again. [self removeUIViews]; } - (void)generateFormViewWithUIArray:(nullable NSArray *)formUIArray { self.formUIArray = formUIArray; [StackableViewController populateView:self.contentView withUIArray:formUIArray withSpacingBlock:^UIEdgeInsets(id _Nullable object) { return [self spaceAroundUIObject:object]; }]; } - (void)generateFormView:(nullable UIView *)view withUIArrayForConstrainingViews:(nullable NSArray *)formUIArray { self.formUIArray = formUIArray; [StackableViewController populateView:view withUIArrayForConstrainingViews:formUIArray withSpacingBlock:^UIEdgeInsets(id _Nullable object) { return [self spaceAroundUIObject:object]; }]; } - (UIEdgeInsets)spaceAroundUIObject:(nullable id)object { UIEdgeInsets insets = [StackableViewController standardSpaceAroundUIObject]; if (object == [self.formUIArray lastObject]) { // The last object should have space from the bottom insets.bottom = [MFStyler defaultVerticalPaddingForApplicationWidth]; } return insets; } - (void)removeUIViews { [StackableViewController removeUIViews:self.formUIArray]; } + (void)removeUIViews:(nullable NSArray *)views { for (NSUInteger i = 0; i < [views count]; i++) { UIView *view = [views objectAtIndex:i]; [view removeFromSuperview]; } } + (void)populateView:(nonnull UIView *)view withUIArray:(nonnull NSArray *)formUIArray withSpacingBlock:(nonnull UIEdgeInsets (^) (id _Nullable object))spacingBlock { if ([formUIArray count] > 0) { for (UIView *subview in formUIArray) { [view addSubview:subview]; } [StackableViewController autoLayoutView:view withUIArray:formUIArray withSpacingBlock:spacingBlock]; } } + (void)populateViewHorizontally:(nonnull UIView *)view withUIArray:(nonnull NSArray *)formUIArray withSpacingBlock:(nonnull UIEdgeInsets (^) (id _Nullable object))spacingBlock { if ([formUIArray count] > 0) { for (UIView *subview in formUIArray) { [view addSubview:subview]; } [StackableViewController autoLayoutViewHorizontally:view withUIArray:formUIArray withSpacingBlock:spacingBlock]; } } + (void)populateView:(nonnull UIView *)view withUIArrayForConstrainingViews:(nonnull NSArray *)formUIArray withSpacingBlock:(nonnull UIEdgeInsets (^) (id _Nullable object))spacingBlock { if ([formUIArray count] > 0) { for (UIView *subview in formUIArray) { ViewConstrainingView *constrainingView = [ViewConstrainingView viewConstrainingView:subview]; [view addSubview:constrainingView]; } [StackableViewController autoLayoutViewWithConstrainingViewsWithUIArray:formUIArray withSpacingBlock:spacingBlock]; } } + (void)autoLayoutView:(nonnull UIView *)view withUIArray:(nonnull NSArray *)formUIArray withSpacingBlock:(nonnull UIEdgeInsets (^) (id _Nullable object))spacingBlock { if ([formUIArray count] > 0) { // Adds the first object to the view and pins it to the top of the content view. id previousUIObject = [formUIArray objectAtIndex:0]; UIEdgeInsets spaceAroundObjectPrevious = spacingBlock(previousUIObject); [previousUIObject setTranslatesAutoresizingMaskIntoConstraints:NO]; [NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-top@999-[previousUIObject]" options:NSLayoutFormatDirectionLeadingToTrailing metrics:@{@"top":@(spaceAroundObjectPrevious.top)} views:NSDictionaryOfVariableBindings(previousUIObject)]]; [NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-left@999-[previousUIObject]-right-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:@{@"left":@(spaceAroundObjectPrevious.left),@"right":@(spaceAroundObjectPrevious.right)} views:NSDictionaryOfVariableBindings(previousUIObject)]]; // Sets the horizontal spacing and adds vertical spacing between all ui objects. for (NSUInteger i = 1; i < [formUIArray count]; i++) { id uiObject = [formUIArray objectAtIndex:i]; UIEdgeInsets spaceAroundObjectCurrent = spacingBlock(uiObject); [uiObject setTranslatesAutoresizingMaskIntoConstraints:NO]; [NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[previousUIObject]-space-[uiObject]" options:NSLayoutFormatDirectionLeadingToTrailing metrics:@{@"space":@(spaceAroundObjectPrevious.bottom + spaceAroundObjectCurrent.top)} views:NSDictionaryOfVariableBindings(previousUIObject,uiObject)]]; [NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-left@999-[uiObject]-right-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:@{@"left":@(spaceAroundObjectCurrent.left),@"right":@(spaceAroundObjectCurrent.right)} views:NSDictionaryOfVariableBindings(uiObject)]]; previousUIObject = uiObject; spaceAroundObjectPrevious = spaceAroundObjectCurrent; } // Pins the last object to the bottom of the content view. [NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[previousUIObject]-bottom-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:@{@"bottom":@(spaceAroundObjectPrevious.bottom)} views:NSDictionaryOfVariableBindings(previousUIObject)]]; } } + (void)autoLayoutViewHorizontally:(nonnull UIView *)view withUIArray:(nonnull NSArray *)formUIArray withSpacingBlock:(nonnull UIEdgeInsets (^) (id _Nullable object))spacingBlock { if ([formUIArray count] > 0) { // Adds the first object to the view and pins it to the top and left of the content view. id previousUIObject = [formUIArray objectAtIndex:0]; UIEdgeInsets spaceAroundObjectPrevious = spacingBlock(previousUIObject); [previousUIObject setTranslatesAutoresizingMaskIntoConstraints:NO]; [NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-top@999-[previousUIObject]-bottom-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:@{@"top":@(spaceAroundObjectPrevious.top),@"bottom":@(spaceAroundObjectPrevious.bottom)} views:NSDictionaryOfVariableBindings(previousUIObject)]]; [NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-left@999-[previousUIObject]" options:NSLayoutFormatDirectionLeadingToTrailing metrics:@{@"left":@(spaceAroundObjectPrevious.left)} views:NSDictionaryOfVariableBindings(previousUIObject)]]; // Sets the vertical spacing and adds horizontal spacing between all ui objects. for (NSUInteger i = 1; i < [formUIArray count]; i++) { id uiObject = [formUIArray objectAtIndex:i]; UIEdgeInsets spaceAroundObjectCurrent = spacingBlock(uiObject); [uiObject setTranslatesAutoresizingMaskIntoConstraints:NO]; [NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[previousUIObject]-space-[uiObject]" options:NSLayoutFormatDirectionLeadingToTrailing metrics:@{@"space":@(spaceAroundObjectPrevious.right + spaceAroundObjectCurrent.left)} views:NSDictionaryOfVariableBindings(previousUIObject,uiObject)]]; [NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-top@999-[uiObject]-bottom-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:@{@"top":@(spaceAroundObjectCurrent.top),@"bottom":@(spaceAroundObjectCurrent.bottom)} views:NSDictionaryOfVariableBindings(uiObject)]]; previousUIObject = uiObject; spaceAroundObjectPrevious = spaceAroundObjectCurrent; } // Pins the last object to the right of the content view. [NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[previousUIObject]-right-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:@{@"right":@(spaceAroundObjectPrevious.right)} views:NSDictionaryOfVariableBindings(previousUIObject)]]; } } + (void)autoLayoutViewWithConstrainingViewsWithUIArray:(nonnull NSArray *)formUIArray withSpacingBlock:(nonnull UIEdgeInsets (^) (id _Nullable object))spacingBlock { if ([formUIArray count] > 0) { // Adds the first object to the view and pins it to the top of the content view. UIView *uiObject = [formUIArray objectAtIndex:0]; ViewConstrainingView *previousConstrainingView = (ViewConstrainingView *)uiObject.superview; [previousConstrainingView.topAnchor constraintEqualToAnchor:previousConstrainingView.superview.topAnchor].active = YES; [previousConstrainingView.leftAnchor constraintEqualToAnchor:previousConstrainingView.superview.leftAnchor].active = YES; [previousConstrainingView.superview.rightAnchor constraintEqualToAnchor:previousConstrainingView.rightAnchor].active = YES; UIEdgeInsets spaceAroundObject = spacingBlock(uiObject); [previousConstrainingView setPinConstantsWithInsets:spaceAroundObject]; // Sets the horizontal spacing and adds vertical spacing between all ui objects. for (NSUInteger i = 1; i < [formUIArray count]; i++) { uiObject = [formUIArray objectAtIndex:i]; ViewConstrainingView *constrainingView = (ViewConstrainingView *)uiObject.superview; [constrainingView.topAnchor constraintEqualToAnchor:previousConstrainingView.bottomAnchor].active = YES; [constrainingView.leftAnchor constraintEqualToAnchor:constrainingView.superview.leftAnchor].active = YES; [constrainingView.superview.rightAnchor constraintEqualToAnchor:constrainingView.rightAnchor].active = YES; spaceAroundObject = spacingBlock(uiObject); [constrainingView setPinConstantsWithInsets:spaceAroundObject]; previousConstrainingView = constrainingView; } // Pins the last object to the bottom of the content view. [previousConstrainingView.superview.bottomAnchor constraintEqualToAnchor:previousConstrainingView.bottomAnchor].active = YES; } } - (void)resetSpaceForFormArrayWithConstrainingViews { for (UIView *view in self.formUIArray) { ViewConstrainingView *constrainingView = (ViewConstrainingView *)view.superview; [constrainingView setPinConstantsWithInsets:[self spaceAroundUIObject:view]]; } } + (UIEdgeInsets)standardSpaceAroundUIObject { CGFloat horizontal = [MFStyler defaultHorizontalPaddingForApplicationWidth]; CGFloat vertical = [MFStyler defaultVerticalPaddingForApplicationWidth]; return UIEdgeInsetsMake(vertical, horizontal, 0, horizontal); } @end