ORStackView

by orta

Vertically stack views using Auto Layout, with an order specific subclass that uses view tags for or...

427 Stars 30 Forks Last release: Not found MIT License 102 Commits 13 Releases

Available items

No Items, yet!

The developer of this repository has not created any items for sale yet. Need a bug fixed? Help with integration? A different license? Create a request here:

ORStackView

Build Status Coverage Status Version Platform

Makes setting up a collection of stacked views simple. Uses FLKAutoLayout to simplify the API, you should probably be using it anyway. Depending on demand this can be switched out. If you're interested in more information you can read ORStackView.h

Recommendation

It's probably not the best idea to use ORStackView in a new project, given that UIStackView exists, and there are a lot of pods that aim to have a compatible API with that. Some things that ORStackView does better: View Controllers, and internal margins for individual items. However, you'd probably find yourself fighting the grain in the future.

ORStackView

You can create an ORStackView and simply add subviews to it in the order in which you'd like them to appear. New subviews are added to the bottom of the ORStackView. In the this example, tapping the first subview will add a new subview to the bottom of the stack.

- (void)loadView
{
    self.view = [[ORStackView alloc] init];
}

  • (void)viewDidLoad { ORColourView *view1 = [[ORColourView alloc] init]; view1.text = @"ORStackView - Tap Me"; view1.fakeContentSize = (CGSize){ UIViewNoIntrinsicMetric , 40};

    UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(addView)]; [view1 addGestureRecognizer:tapGesture];

    ORColourView *view2 = [[ORColourView alloc] init]; view2.text = @"Subtitle"; view2.fakeContentSize = (CGSize){ UIViewNoIntrinsicMetric , 20 };

    ORColourView *view3 = [[ORColourView alloc] init]; view3.text = @"By default, new subviews are added to the bottom of ORStackView."; view3.fakeContentSize = (CGSize){ UIViewNoIntrinsicMetric , 100 };

    [self.view addSubview:view1 withPrecedingMargin:20 sideMargin:30]; [self.view addSubview:view2 withPrecedingMargin:40 sideMargin:70]; [self.view addSubview:view3 withPrecedingMargin:30 sideMargin:20]; }

  • (void)addView { ORColourView *view = [[ORColourView alloc] init]; view.text = @"Tap to remove"; view.fakeContentSize = (CGSize){ UIViewNoIntrinsicMetric , 24 }; [self.view addSubview:view withPrecedingMargin:5 sideMargin:40]; }

ORStackView with ordering

If you have views which should only appear once you've got confirmation from an external source, you can add your subviews using

insertSubview:atIndex:withPrecedingMargin:
,
insertSubview:atIndex:withPrecedingMargin:sideMargin:
,
insertSubview:belowSubview:withPrecedingMargin:
or
insertSubview:aboveSubview:withPrecedingMargin:

In this example, subviews appear in a different order than they are added chronologically. Tapping the first subview adds a new subview to the middle of the stack.

- (void)loadView
{
    self.view = [[ORStackView alloc] init];
}

  • (void)viewDidLoad { ORColourView *view1 = [[ORColourView alloc] init]; view1.text = @"1 - ORStackView - Tap Me"; view1.fakeContentSize = (CGSize){ UIViewNoIntrinsicMetric , 40}; UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(addView)]; [view1 addGestureRecognizer:tapGesture];

    ORColourView *view2 = [[ORColourView alloc] init]; view2.text = @"2 - You can control the order your ORStackView's subviews"; view2.fakeContentSize = (CGSize){ UIViewNoIntrinsicMetric , 50 };

    ORColourView *view3 = [[ORColourView alloc] init]; view3.text = @"3 - Lorem ipsum, etc. etc."; view3.fakeContentSize = (CGSize){ UIViewNoIntrinsicMetric , 20 };

    ORColourView *view4 = [[ORColourView alloc] init]; view4.text = @"4 - Lorem ipsum, etc. etc."; view4.fakeContentSize = (CGSize){ UIViewNoIntrinsicMetric , 20 };

    [self.view insertSubview:view2 atIndex:0 withPrecedingMargin:20 sideMargin:20]; [self.view insertSubview:view4 atIndex:1 withPrecedingMargin:15 sideMargin:20]; [self.view insertSubview:view1 atIndex:0 withPrecedingMargin:10 sideMargin:20]; [self.view insertSubview:view3 atIndex:2 withPrecedingMargin:10 sideMargin:20]; }

  • (void)addView { ORColourView *view = [[ORColourView alloc] init]; view.text = @"Tap to remove"; view.fakeContentSize = (CGSize){ UIViewNoIntrinsicMetric , 24 }; [self.view addSubview:view withPrecedingMargin:5 sideMargin:40]; }

ORTagBasedAutoStackView

Another option is to use ORTagBasedAutoStackView to order your subviews visually in a different order than you will be adding them chronologically. ORTagBasedAutoStackView uses view tags to specify the order in which views will appear from top to bottom. For example these views will be ordered correctly regardless of the insertion order chronologically. Tapping the first view adds a new view with a

tag
of
3
to the middle of the stack.

- (void)loadView
{
    self.view = [[ORTagBasedAutoStackView alloc] init];
}

  • (void)viewDidLoad { ORColourView *view1 = [[ORColourView alloc] init]; view1.text = @"Tap Me\ntag = 1"; view1.fakeContentSize = (CGSize){ UIViewNoIntrinsicMetric , 70}; view1.tag = 1;

    UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(addView)]; [view1 addGestureRecognizer:tapGesture];

    ORColourView *view2 = [[ORColourView alloc] init]; view2.text = @"ORTagBasedAutoStackView uses view tags to order your subviews\ntag = 2"; view2.fakeContentSize = (CGSize){ UIViewNoIntrinsicMetric , 70 }; view2.tag = 2;

    ORColourView *view4 = [[ORColourView alloc] init]; view4.text = @"tag = 4"; view4.fakeContentSize = (CGSize){ UIViewNoIntrinsicMetric , 50 }; view4.tag = 4;

    ORColourView *view5 = [[ORColourView alloc] init]; view5.text = @"tag = 5"; view5.fakeContentSize = (CGSize){ UIViewNoIntrinsicMetric , 60 }; view5.tag = 5;

    [self.view addSubview:view2 withPrecedingMargin:10 sideMargin:40]; [self.view addSubview:view5 withPrecedingMargin:20 sideMargin:20]; [self.view addSubview:view4 withPrecedingMargin:10 sideMargin:20]; [self.view addSubview:view1 withPrecedingMargin:20 sideMargin:30]; }

  • (void)addView { if ([[self.view.subviews filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"tag = 3"]] count] > 0) return;

    ORColourView *view3 = [[ORColourView alloc] init]; view3.text = @"tap to remove me\ntag = 3"; view3.fakeContentSize = (CGSize){ UIViewNoIntrinsicMetric , 50 }; view3.tag = 3;

    [self.view addSubview:view3 withPrecedingMargin:20 sideMargin:70]; }

ORSplitStackView

ORSplitStackView is a view containing two ORStackView columns. Add subviews to the

leftStack
and
rightStack
views. ORSplitStackView adjusts its height to fit the taller of the two stack views.

- (void)loadView
{
  self.view = [[UIView alloc] init];
}

  • (void)viewDidLoad { ORSplitStackView *splitView = [[ORSplitStackView alloc] initWithLeftPredicate:@"155" rightPredicate:@"130"]; [self.view addSubview:splitView]; [self.view addConstraint:[NSLayoutConstraint constraintWithItem:splitView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0]]; if ([self respondsToSelector:@selector(topLayoutGuide)]) { [self.view addConstraint:[NSLayoutConstraint constraintWithItem:splitView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.topLayoutGuide attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0]]; }

    splitView.backgroundColor = [UIColor purpleColor]; ORColourView *left1 = [[ORColourView alloc] init]; left1.text = @"Tap Me"; left1.fakeContentSize = (CGSize){ UIViewNoIntrinsicMetric , 50};

    ORColourView *right1 = [[ORColourView alloc] init]; right1.text = @"Tap Me"; right1.fakeContentSize = (CGSize){ UIViewNoIntrinsicMetric , 60};

    UITapGestureRecognizer *leftGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(addView:)]; [left1 addGestureRecognizer:leftGesture]; UITapGestureRecognizer *rightGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(addView:)]; [right1 addGestureRecognizer:rightGesture];

    ORColourView *left2 = [[ORColourView alloc] init]; left2.text = @"ORSplitStackView is a view containing two stack views."; left2.fakeContentSize = (CGSize){ UIViewNoIntrinsicMetric , 90};

    ORColourView *left3 = [[ORColourView alloc] init]; left3.text = @"ORSplitStackView adjusts its height to fit its content"; left3.fakeContentSize = (CGSize){ UIViewNoIntrinsicMetric , 75};

    ORColourView *right2 = [[ORColourView alloc] init]; right2.text = @"a view"; right2.fakeContentSize = (CGSize){ UIViewNoIntrinsicMetric , 45};

    ORColourView *right3 = [[ORColourView alloc] init]; right3.text = @"a view"; right3.fakeContentSize = (CGSize){ UIViewNoIntrinsicMetric , 40};

    [splitView.leftStack addSubview:left1 withPrecedingMargin:0 sideMargin:10]; [splitView.leftStack addSubview:left2 withPrecedingMargin:10 sideMargin:5]; [splitView.leftStack addSubview:left3 withPrecedingMargin:10 sideMargin:15]; [splitView.rightStack addSubview:right1 withPrecedingMargin:0 sideMargin:15]; [splitView.rightStack addSubview:right2 withPrecedingMargin:10 sideMargin:10]; [splitView.rightStack addSubview:right3 withPrecedingMargin:10 sideMargin:5]; }

  • (void)addView:(UITapGestureRecognizer *)gesture { ORColourView *view = [[ORColourView alloc] init]; view.text = @"Tap to remove"; view.fakeContentSize = (CGSize){ UIViewNoIntrinsicMetric , 24 }; [(ORStackView *)gesture.view.superview addSubview:view withPrecedingMargin:5 sideMargin:10]; }

Example Usage

pod try ORStackView
or to run the example project; clone the repo, and run
pod install
from the Project directory.

Installation

ORStackView is available through CocoaPods, to install it simply add the following line to your Podfile:

pod "ORStackView"

Author

Orta Therox, [email protected]

License

ORStackView is available under the MIT license. See the LICENSE file for more info.

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.