├── Snapshots
├── snapshot0.png
└── snapshot1.png
├── FDStackViewDemo
├── Images.xcassets
│ ├── Contents.json
│ ├── forkingdog.imageset
│ │ ├── 11923583.png
│ │ └── Contents.json
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── FDCodeBasedViewController.h
├── FDStoryboardBasedViewController.h
├── AppDelegate.h
├── main.m
├── Info.plist
├── FDCodeBasedViewController.m
├── AppDelegate.m
├── FDStoryboardBasedViewController.m
└── Base.lproj
│ ├── LaunchScreen.xib
│ └── Main.storyboard
├── FDStackViewDemo.xcodeproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
└── project.pbxproj
├── .gitignore
├── LICENSE
├── FDStackView
├── FDTransformLayer.h
├── FDGapLayoutGuide.h
├── FDGapLayoutGuide.m
├── FDLayoutSpacer.h
├── FDTransformLayer.m
├── FDStackViewDistributionLayoutArrangement.h
├── FDStackViewExtensions.h
├── FDStackViewAlignmentLayoutArrangement.h
├── FDLayoutSpacer.m
├── FDStackViewLayoutArrangement.m
├── FDStackView.h
├── FDStackViewExtensions.m
├── FDStackViewLayoutArrangement.h
├── FDStackView.m
├── FDStackViewDistributionLayoutArrangement.m
└── FDStackViewAlignmentLayoutArrangement.m
├── FDStackView.podspec
└── README.md
/Snapshots/snapshot0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/forkingdog/FDStackView/HEAD/Snapshots/snapshot0.png
--------------------------------------------------------------------------------
/Snapshots/snapshot1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/forkingdog/FDStackView/HEAD/Snapshots/snapshot1.png
--------------------------------------------------------------------------------
/FDStackViewDemo/Images.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/FDStackViewDemo/Images.xcassets/forkingdog.imageset/11923583.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/forkingdog/FDStackView/HEAD/FDStackViewDemo/Images.xcassets/forkingdog.imageset/11923583.png
--------------------------------------------------------------------------------
/FDStackViewDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/FDStackViewDemo/FDCodeBasedViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // FDCodeBasedViewController.h
3 | // FDStackViewDemo
4 | //
5 | // Created by sunnyxx on 15/10/10.
6 | // Copyright © 2015年 forkingdog. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface FDCodeBasedViewController : UIViewController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/FDStackViewDemo/FDStoryboardBasedViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // FDStoryboardBasedViewController.h
3 | // FDStackViewDemo
4 | //
5 | // Created by sunnyxx on 15/9/15.
6 | // Copyright © 2015 forkingdog. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface FDStoryboardBasedViewController : UITableViewController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/FDStackViewDemo/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // FDStackViewDemo
4 | //
5 | // Created by sunnyxx on 15/9/6.
6 | // Copyright (c) 2015年 forkingdog. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface AppDelegate : UIResponder
12 |
13 | @property (strong, nonatomic) UIWindow *window;
14 |
15 |
16 | @end
17 |
18 |
--------------------------------------------------------------------------------
/FDStackViewDemo/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // FDStackViewDemo
4 | //
5 | // Created by sunnyxx on 15/9/6.
6 | // Copyright (c) 2015年 forkingdog. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "AppDelegate.h"
11 |
12 | int main(int argc, char * argv[]) {
13 | @autoreleasepool {
14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/FDStackViewDemo/Images.xcassets/forkingdog.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "11923583.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | build/
4 | *.pbxuser
5 | !default.pbxuser
6 | *.mode1v3
7 | !default.mode1v3
8 | *.mode2v3
9 | !default.mode2v3
10 | *.perspectivev3
11 | !default.perspectivev3
12 | xcuserdata
13 | *.xccheckout
14 | *.moved-aside
15 | DerivedData
16 | *.hmap
17 | *.ipa
18 | *.xcuserstate
19 |
20 | # CocoaPods
21 | #
22 | # We recommend against adding the Pods directory to your .gitignore. However
23 | # you should judge for yourself, the pros and cons are mentioned at:
24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
25 | #
26 | #Pods/
27 |
--------------------------------------------------------------------------------
/FDStackViewDemo/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | }
33 | ],
34 | "info" : {
35 | "version" : 1,
36 | "author" : "xcode"
37 | }
38 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/FDStackView/FDTransformLayer.h:
--------------------------------------------------------------------------------
1 | // The MIT License (MIT)
2 | //
3 | // Copyright (c) 2015-2016 forkingdog ( https://github.com/forkingdog )
4 | //
5 | // Permission is hereby granted, free of charge, to any person obtaining a copy
6 | // of this software and associated documentation files (the "Software"), to deal
7 | // in the Software without restriction, including without limitation the rights
8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | // copies of the Software, and to permit persons to whom the Software is
10 | // furnished to do so, subject to the following conditions:
11 | //
12 | // The above copyright notice and this permission notice shall be included in all
13 | // copies or substantial portions of the Software.
14 | //
15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | // SOFTWARE.
22 |
23 | #import
24 |
25 | @interface FDTransformLayer : CATransformLayer
26 |
27 | @end
28 |
--------------------------------------------------------------------------------
/FDStackViewDemo/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 | UIInterfaceOrientationLandscapeLeft
37 | UIInterfaceOrientationLandscapeRight
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/FDStackView/FDGapLayoutGuide.h:
--------------------------------------------------------------------------------
1 | // The MIT License (MIT)
2 | //
3 | // Copyright (c) 2015-2016 forkingdog ( https://github.com/forkingdog )
4 | //
5 | // Permission is hereby granted, free of charge, to any person obtaining a copy
6 | // of this software and associated documentation files (the "Software"), to deal
7 | // in the Software without restriction, including without limitation the rights
8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | // copies of the Software, and to permit persons to whom the Software is
10 | // furnished to do so, subject to the following conditions:
11 | //
12 | // The above copyright notice and this permission notice shall be included in all
13 | // copies or substantial portions of the Software.
14 | //
15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | // SOFTWARE.
22 |
23 | #import
24 |
25 | @interface FDGapLayoutGuide : UIView
26 | @property (nonatomic, readonly) UIView *owningView;
27 | @end
28 |
--------------------------------------------------------------------------------
/FDStackView/FDGapLayoutGuide.m:
--------------------------------------------------------------------------------
1 | // The MIT License (MIT)
2 | //
3 | // Copyright (c) 2015-2016 forkingdog ( https://github.com/forkingdog )
4 | //
5 | // Permission is hereby granted, free of charge, to any person obtaining a copy
6 | // of this software and associated documentation files (the "Software"), to deal
7 | // in the Software without restriction, including without limitation the rights
8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | // copies of the Software, and to permit persons to whom the Software is
10 | // furnished to do so, subject to the following conditions:
11 | //
12 | // The above copyright notice and this permission notice shall be included in all
13 | // copies or substantial portions of the Software.
14 | //
15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | // SOFTWARE.
22 |
23 | #import "FDGapLayoutGuide.h"
24 | #import "FDTransformLayer.h"
25 |
26 | @implementation FDGapLayoutGuide
27 |
28 | + (Class)layerClass {
29 | return FDTransformLayer.class;
30 | }
31 |
32 | - (UIView *)owningView {
33 | return self.superview;
34 | }
35 |
36 | @end
37 |
--------------------------------------------------------------------------------
/FDStackViewDemo/FDCodeBasedViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // FDCodeBasedViewController.m
3 | // FDStackViewDemo
4 | //
5 | // Created by sunnyxx on 15/10/10.
6 | // Copyright © 2015年 forkingdog. All rights reserved.
7 | //
8 |
9 | #import "FDCodeBasedViewController.h"
10 |
11 | @implementation FDCodeBasedViewController
12 |
13 | - (void)viewDidLoad {
14 | [super viewDidLoad];
15 |
16 | UILabel *forkingLabel = [[UILabel alloc] init];
17 | forkingLabel.text = @"forking";
18 | UIImageView *logoImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"forkingdog"]];
19 | UILabel *dogLabel = [[UILabel alloc] init];
20 | dogLabel.text = @"dog";
21 |
22 | UIStackView *stackView = [[UIStackView alloc] initWithArrangedSubviews:@[forkingLabel, logoImageView, dogLabel]];
23 | stackView.translatesAutoresizingMaskIntoConstraints = NO;
24 | stackView.axis = UILayoutConstraintAxisHorizontal;
25 | stackView.distribution = UIStackViewDistributionFill;
26 | stackView.alignment = UIStackViewAlignmentCenter;
27 | [self.view addSubview:stackView];
28 |
29 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:stackView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]];
30 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:stackView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];
31 | }
32 |
33 | @end
34 |
--------------------------------------------------------------------------------
/FDStackView/FDLayoutSpacer.h:
--------------------------------------------------------------------------------
1 | // The MIT License (MIT)
2 | //
3 | // Copyright (c) 2015-2016 forkingdog ( https://github.com/forkingdog )
4 | //
5 | // Permission is hereby granted, free of charge, to any person obtaining a copy
6 | // of this software and associated documentation files (the "Software"), to deal
7 | // in the Software without restriction, including without limitation the rights
8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | // copies of the Software, and to permit persons to whom the Software is
10 | // furnished to do so, subject to the following conditions:
11 | //
12 | // The above copyright notice and this permission notice shall be included in all
13 | // copies or substantial portions of the Software.
14 | //
15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | // SOFTWARE.
22 |
23 | #import
24 |
25 | @interface FDLayoutSpacer : UIView
26 | @property (nonatomic, readonly) UIView *owningView;
27 | @property (nonatomic, assign, getter=isHorizontal) BOOL horizontal;
28 | @property (nonatomic, strong, readonly) NSMutableArray *systemConstraints;
29 | @end
30 |
--------------------------------------------------------------------------------
/FDStackView/FDTransformLayer.m:
--------------------------------------------------------------------------------
1 | // The MIT License (MIT)
2 | //
3 | // Copyright (c) 2015-2016 forkingdog ( https://github.com/forkingdog )
4 | //
5 | // Permission is hereby granted, free of charge, to any person obtaining a copy
6 | // of this software and associated documentation files (the "Software"), to deal
7 | // in the Software without restriction, including without limitation the rights
8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | // copies of the Software, and to permit persons to whom the Software is
10 | // furnished to do so, subject to the following conditions:
11 | //
12 | // The above copyright notice and this permission notice shall be included in all
13 | // copies or substantial portions of the Software.
14 | //
15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | // SOFTWARE.
22 |
23 | #import "FDTransformLayer.h"
24 |
25 | @implementation FDTransformLayer
26 |
27 | - (void)setOpaque:(BOOL)opaque {
28 | // Clear CATransformLayer's warnings.
29 | }
30 |
31 | - (void)setBackgroundColor:(CGColorRef)backgroundColor {
32 | // Clear CATransformLayer's warnings.
33 | }
34 |
35 | @end
36 |
--------------------------------------------------------------------------------
/FDStackView/FDStackViewDistributionLayoutArrangement.h:
--------------------------------------------------------------------------------
1 | // The MIT License (MIT)
2 | //
3 | // Copyright (c) 2015-2016 forkingdog ( https://github.com/forkingdog )
4 | //
5 | // Permission is hereby granted, free of charge, to any person obtaining a copy
6 | // of this software and associated documentation files (the "Software"), to deal
7 | // in the Software without restriction, including without limitation the rights
8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | // copies of the Software, and to permit persons to whom the Software is
10 | // furnished to do so, subject to the following conditions:
11 | //
12 | // The above copyright notice and this permission notice shall be included in all
13 | // copies or substantial portions of the Software.
14 | //
15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | // SOFTWARE.
22 |
23 | #import
24 | #import "FDStackViewLayoutArrangement.h"
25 |
26 | @interface FDStackViewDistributionLayoutArrangement : FDStackViewLayoutArrangement
27 | @property (nonatomic, assign) CGFloat spacing;
28 | @property (nonatomic, assign) UIStackViewDistribution distribution;
29 | - (void)resetAllConstraints;
30 | @end
31 |
--------------------------------------------------------------------------------
/FDStackView/FDStackViewExtensions.h:
--------------------------------------------------------------------------------
1 | // The MIT License (MIT)
2 | //
3 | // Copyright (c) 2015-2016 forkingdog ( https://github.com/forkingdog )
4 | //
5 | // Permission is hereby granted, free of charge, to any person obtaining a copy
6 | // of this software and associated documentation files (the "Software"), to deal
7 | // in the Software without restriction, including without limitation the rights
8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | // copies of the Software, and to permit persons to whom the Software is
10 | // furnished to do so, subject to the following conditions:
11 | //
12 | // The above copyright notice and this permission notice shall be included in all
13 | // copies or substantial portions of the Software.
14 | //
15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | // SOFTWARE.
22 |
23 | #import
24 |
25 | @interface NSMapTable (FDAllObjects)
26 | @property (nonatomic, readonly) NSArray *fd_allObjects;
27 | @end
28 |
29 | @interface NSArray<__covariant ObjectType> (FDCarAndCdr)
30 | @property (nonatomic, readonly) ObjectType car;
31 | @property (nonatomic, readonly) NSArray *cdr;
32 | @end
33 |
--------------------------------------------------------------------------------
/FDStackView/FDStackViewAlignmentLayoutArrangement.h:
--------------------------------------------------------------------------------
1 | // The MIT License (MIT)
2 | //
3 | // Copyright (c) 2015-2016 forkingdog ( https://github.com/forkingdog )
4 | //
5 | // Permission is hereby granted, free of charge, to any person obtaining a copy
6 | // of this software and associated documentation files (the "Software"), to deal
7 | // in the Software without restriction, including without limitation the rights
8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | // copies of the Software, and to permit persons to whom the Software is
10 | // furnished to do so, subject to the following conditions:
11 | //
12 | // The above copyright notice and this permission notice shall be included in all
13 | // copies or substantial portions of the Software.
14 | //
15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | // SOFTWARE.
22 |
23 | #import "FDStackViewLayoutArrangement.h"
24 |
25 | @interface FDStackViewAlignmentLayoutArrangement : FDStackViewLayoutArrangement
26 | @property (nonatomic, assign) UIStackViewAlignment alignment;
27 | @property (nonatomic, strong) NSMutableDictionary *alignmentConstraints;
28 | @property (nonatomic, strong) NSMapTable *hiddingDimensionConstraints;
29 | @end
30 |
--------------------------------------------------------------------------------
/FDStackView/FDLayoutSpacer.m:
--------------------------------------------------------------------------------
1 | // The MIT License (MIT)
2 | //
3 | // Copyright (c) 2015-2016 forkingdog ( https://github.com/forkingdog )
4 | //
5 | // Permission is hereby granted, free of charge, to any person obtaining a copy
6 | // of this software and associated documentation files (the "Software"), to deal
7 | // in the Software without restriction, including without limitation the rights
8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | // copies of the Software, and to permit persons to whom the Software is
10 | // furnished to do so, subject to the following conditions:
11 | //
12 | // The above copyright notice and this permission notice shall be included in all
13 | // copies or substantial portions of the Software.
14 | //
15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | // SOFTWARE.
22 |
23 | #import "FDLayoutSpacer.h"
24 | #import "FDTransformLayer.h"
25 |
26 | @implementation FDLayoutSpacer
27 | @synthesize systemConstraints = _systemConstraints;
28 |
29 | + (Class)layerClass {
30 | return FDTransformLayer.class;
31 | }
32 |
33 | - (NSMutableArray *)systemConstraints {
34 | if (!_systemConstraints) {
35 | _systemConstraints = [NSMutableArray array];
36 | }
37 | return _systemConstraints;
38 | }
39 |
40 | - (UIView *)owningView {
41 | return self.superview;
42 | }
43 |
44 | @end
--------------------------------------------------------------------------------
/FDStackViewDemo/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // FDStackViewDemo
4 | //
5 | // Created by sunnyxx on 15/9/6.
6 | // Copyright (c) 2015年 forkingdog. All rights reserved.
7 | //
8 |
9 | #import "AppDelegate.h"
10 |
11 | @interface AppDelegate ()
12 |
13 | @end
14 |
15 | @implementation AppDelegate
16 |
17 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
18 | // Override point for customization after application launch.
19 | return YES;
20 | }
21 |
22 | - (void)applicationWillResignActive:(UIApplication *)application {
23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
24 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
25 | }
26 |
27 | - (void)applicationDidEnterBackground:(UIApplication *)application {
28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
30 | }
31 |
32 | - (void)applicationWillEnterForeground:(UIApplication *)application {
33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
34 | }
35 |
36 | - (void)applicationDidBecomeActive:(UIApplication *)application {
37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
38 | }
39 |
40 | - (void)applicationWillTerminate:(UIApplication *)application {
41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
42 | }
43 |
44 | @end
45 |
--------------------------------------------------------------------------------
/FDStackView/FDStackViewLayoutArrangement.m:
--------------------------------------------------------------------------------
1 | // The MIT License (MIT)
2 | //
3 | // Copyright (c) 2015-2016 forkingdog ( https://github.com/forkingdog )
4 | //
5 | // Permission is hereby granted, free of charge, to any person obtaining a copy
6 | // of this software and associated documentation files (the "Software"), to deal
7 | // in the Software without restriction, including without limitation the rights
8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | // copies of the Software, and to permit persons to whom the Software is
10 | // furnished to do so, subject to the following conditions:
11 | //
12 | // The above copyright notice and this permission notice shall be included in all
13 | // copies or substantial portions of the Software.
14 | //
15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | // SOFTWARE.
22 |
23 | #import "FDStackViewLayoutArrangement.h"
24 | #import "FDStackViewAlignmentLayoutArrangement.h"
25 | #import "FDStackViewDistributionLayoutArrangement.h"
26 |
27 | @implementation FDStackViewLayoutArrangement
28 |
29 | - (instancetype)initWithItems:(NSArray *)items onAxis:(UILayoutConstraintAxis)axis {
30 | if (self = [super init]) {
31 | _mutableItems = [[NSMutableArray alloc] initWithArray:items];
32 | _canvasConnectionConstraints = [NSMutableArray array];
33 | _axis = axis;
34 | }
35 | return self;
36 | }
37 |
38 | - (void)addItem:(UIView *)item {
39 | [self.mutableItems addObject:item];
40 | }
41 |
42 | - (void)removeItem:(UIView *)item {
43 | [self.mutableItems removeObject:item];
44 | }
45 |
46 | - (void)insertItem:(UIView *)item atIndex:(NSUInteger)index {
47 | [self.mutableItems insertObject:item atIndex:index];
48 | }
49 |
50 | - (NSArray *)items {
51 | return self.mutableItems.copy;
52 | }
53 |
54 | - (void)intrinsicContentSizeInvalidatedForItem:(id)item {
55 | [self updateArrangementConstraints];
56 | }
57 |
58 | - (void)updateArrangementConstraints {
59 | [self updateCanvasConnectionConstraintsIfNecessary];
60 | }
61 |
62 | @end
63 |
--------------------------------------------------------------------------------
/FDStackView/FDStackView.h:
--------------------------------------------------------------------------------
1 | // The MIT License (MIT)
2 | //
3 | // Copyright (c) 2015-2016 forkingdog ( https://github.com/forkingdog )
4 | //
5 | // Permission is hereby granted, free of charge, to any person obtaining a copy
6 | // of this software and associated documentation files (the "Software"), to deal
7 | // in the Software without restriction, including without limitation the rights
8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | // copies of the Software, and to permit persons to whom the Software is
10 | // furnished to do so, subject to the following conditions:
11 | //
12 | // The above copyright notice and this permission notice shall be included in all
13 | // copies or substantial portions of the Software.
14 | //
15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | // SOFTWARE.
22 |
23 | #import
24 |
25 | #if __IPHONE_OS_VERSION_MAX_ALLOWED < 90000
26 | #error "FDStackView must be compiled under iOS9 SDK at least"
27 | #endif
28 |
29 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 90000
30 | #warning "No need for FDStackView with a deploy iOS version greater than 9.0"
31 | #endif
32 |
33 | // No need to use this class directly, it is the internal class that actually works before iOS9.
34 | @interface FDStackView : UIView
35 |
36 | - (instancetype)initWithArrangedSubviews:(NSArray<__kindof UIView *> *)views;
37 |
38 | @property (nonatomic, copy, readonly) NSArray<__kindof UIView *> *arrangedSubviews;
39 |
40 | - (void)addArrangedSubview:(UIView *)view;
41 | - (void)removeArrangedSubview:(UIView *)view;
42 | - (void)insertArrangedSubview:(UIView *)view atIndex:(NSUInteger)stackIndex;
43 |
44 | @property (nonatomic, assign) UILayoutConstraintAxis axis;
45 | @property (nonatomic, assign) UIStackViewDistribution distribution;
46 | @property (nonatomic, assign) UIStackViewAlignment alignment;
47 | @property (nonatomic, assign) CGFloat spacing;
48 | @property (nonatomic, assign, getter=isBaselineRelativeArrangement) BOOL baselineRelativeArrangement;
49 | @property (nonatomic, assign, getter=isLayoutMarginsRelativeArrangement) BOOL layoutMarginsRelativeArrangement;
50 |
51 | @end
52 |
--------------------------------------------------------------------------------
/FDStackView/FDStackViewExtensions.m:
--------------------------------------------------------------------------------
1 | // The MIT License (MIT)
2 | //
3 | // Copyright (c) 2015-2016 forkingdog ( https://github.com/forkingdog )
4 | //
5 | // Permission is hereby granted, free of charge, to any person obtaining a copy
6 | // of this software and associated documentation files (the "Software"), to deal
7 | // in the Software without restriction, including without limitation the rights
8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | // copies of the Software, and to permit persons to whom the Software is
10 | // furnished to do so, subject to the following conditions:
11 | //
12 | // The above copyright notice and this permission notice shall be included in all
13 | // copies or substantial portions of the Software.
14 | //
15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | // SOFTWARE.
22 |
23 | #import "FDStackViewExtensions.h"
24 | #import
25 |
26 | @implementation NSMapTable (FDAllObjects)
27 |
28 | - (NSArray *)fd_allObjects {
29 | return self.objectEnumerator.allObjects ?: @[];
30 | }
31 |
32 | @end
33 |
34 | @implementation NSLayoutConstraint (FDStackViewExtensions)
35 |
36 | + (void)load {
37 | static dispatch_once_t onceToken;
38 | dispatch_once(&onceToken, ^{
39 | // iOS6 patch
40 | if(!class_getProperty(self, "identifier")) {
41 | SEL getterSelector = sel_registerName("identifier");
42 | class_addMethod(self, getterSelector, imp_implementationWithBlock(^(id self) {
43 | return objc_getAssociatedObject(self, getterSelector);
44 | }), "@@");
45 | class_addMethod(self, sel_registerName("setIdentifier:"), imp_implementationWithBlock(^(id self, id value) {
46 | objc_setAssociatedObject(self, getterSelector, value, OBJC_ASSOCIATION_COPY_NONATOMIC);
47 | }), "v@:@");
48 | }
49 | });
50 | }
51 |
52 | @end
53 |
54 | @implementation NSArray (FDCarAndCdr)
55 |
56 | - (id)car {
57 | return self.firstObject;
58 | }
59 |
60 | - (NSArray *)cdr {
61 | if (self.count <= 1) return nil;
62 | return [self subarrayWithRange:(NSRange){1, self.count - 1}];
63 | }
64 |
65 | @end
66 |
--------------------------------------------------------------------------------
/FDStackView/FDStackViewLayoutArrangement.h:
--------------------------------------------------------------------------------
1 | // The MIT License (MIT)
2 | //
3 | // Copyright (c) 2015-2016 forkingdog ( https://github.com/forkingdog )
4 | //
5 | // Permission is hereby granted, free of charge, to any person obtaining a copy
6 | // of this software and associated documentation files (the "Software"), to deal
7 | // in the Software without restriction, including without limitation the rights
8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | // copies of the Software, and to permit persons to whom the Software is
10 | // furnished to do so, subject to the following conditions:
11 | //
12 | // The above copyright notice and this permission notice shall be included in all
13 | // copies or substantial portions of the Software.
14 | //
15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | // SOFTWARE.
22 |
23 | #import
24 | #import "FDStackView.h"
25 |
26 | @protocol FDStackViewLayoutArrangementSubclassHook
27 | @optional
28 | @property (nonatomic, assign, readonly) NSLayoutAttribute dimensionAttributeForCurrentAxis;
29 | @property (nonatomic, assign, readonly) NSLayoutAttribute minAttributeForCanvasConnections;
30 | @property (nonatomic, assign, readonly) NSLayoutAttribute maxAttributeForCanvasConnections;
31 | @property (nonatomic, assign, readonly) NSLayoutAttribute centerAttributeForCanvasConnections;
32 |
33 | - (void)removeDeprecatedConstraints;
34 | - (void)updateCanvasConnectionConstraintsIfNecessary;
35 | - (NSLayoutRelation)layoutRelationForCanvasConnectionForAttribute:(NSLayoutAttribute)attribute;
36 |
37 | @end
38 |
39 | @interface FDStackViewLayoutArrangement : NSObject
40 |
41 | @property (nonatomic, weak) UIView *canvas;
42 | @property (nonatomic, assign) UILayoutConstraintAxis axis;
43 | @property (nonatomic, strong) NSMutableArray *mutableItems;
44 | @property (nonatomic, strong) NSMutableArray *canvasConnectionConstraints;
45 |
46 | - (instancetype)initWithItems:(NSArray *)items onAxis:(UILayoutConstraintAxis)axis;
47 | - (void)insertItem:(UIView *)item atIndex:(NSUInteger)index;
48 | - (void)removeItem:(UIView *)item;
49 | - (void)addItem:(UIView *)item;
50 |
51 | @property (nonatomic, copy, readonly) NSArray *items;
52 |
53 | - (void)intrinsicContentSizeInvalidatedForItem:(id)item;
54 | - (void)updateArrangementConstraints;
55 |
56 | @end
--------------------------------------------------------------------------------
/FDStackView.podspec:
--------------------------------------------------------------------------------
1 |
2 | Pod::Spec.new do |s|
3 | s.name = "FDStackView"
4 | s.version = "1.0.1"
5 | s.summary = "Use UIStackView as if it supports iOS6+."
6 |
7 | s.description = <<-DESC
8 | # Problem
9 |
10 | UIStackView is a very handy tool to build flow layout, but it's available only when iOS9+, we've found some great compatible replacements like OAStackView, but we want more:
11 |
12 | - **Perfect downward compatible**, no infectivity, use UIStackView **directly** as if it's shipped from iOS6.
13 | - **Interface builder support**, live preview.
14 | - Keep layout constraints as closely as UIStackView constructs.
15 |
16 | # Usage
17 |
18 | **Import nothing, learn nothing, it just works.**
19 |
20 | - It will automatically replace the symbol for UIStackView into FDStackView at runtime before iOS9.
21 |
22 | ``` objc
23 | // Works in iOS6+, use it directly.
24 | UIStackView *stackView = [[UIStackView alloc] init];
25 | stackView.axis = UILayoutConstraintAxisHorizontal;
26 | stackView.distribution = UIStackViewDistributionFill;
27 | stackView.alignment = UIStackViewAlignmentTop;
28 | [stackView addArrangedSubview:[[UILabel alloc] init]];
29 | [self.view addSubview:stackView];
30 | ```
31 |
32 | - Interface Builder Support
33 |
34 | Set `Builds for` option to `iOS 9.0 and later` to eliminate the version error in Xcode:
35 |
36 | 
37 |
38 | Now, use UIStackView as you like and its reactive options and live preview:
39 |
40 | 
41 |
42 | # Requirements
43 |
44 | - Xcode 7+ (For interface builder supports and the latest Objective-C Syntax)
45 | - Base SDK iOS 9.0+ (To link UIStackView symbol in UIKit)
46 | DESC
47 |
48 | s.homepage = "https://github.com/forkingdog/FDStackView"
49 |
50 | # ――― Spec License ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
51 | s.license = { :type => "MIT", :file => "LICENSE" }
52 | # ――― Author Metadata ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
53 | s.author = { "forkingdog group" => "https://github.com/forkingdog" }
54 | # ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
55 | s.platform = :ios, "6.0"
56 | # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
57 | s.source = { :git => "https://github.com/forkingdog/FDStackView.git", :tag => "1.0.1" }
58 | # ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
59 | s.source_files = "FDStackView/*.{h,m}"
60 | # ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
61 | s.requires_arc = true
62 | end
63 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # FDStackView
2 |
3 | Use UIStackView as if it supports iOS6.
4 | 
5 |
6 | # Problem
7 |
8 | UIStackView is a very handy tool to build flow layout, but it's available only when iOS9+, we've found some great compatible replacements like OAStackView, but we want more:
9 |
10 | - **Perfect downward compatible**, no infectivity, use UIStackView **directly** as if it's shipped from iOS6.
11 | - **Interface builder support**, live preview.
12 | - Keep layout constraints as closely as UIStackView constructs.
13 |
14 | # Usage
15 |
16 | #### Podfile
17 | ```ruby
18 | platform :ios, '7.0'
19 | pod "FDStackView", "1.0"
20 | ```
21 |
22 | **Import nothing, learn nothing, it just works.**
23 |
24 | - It will automatically replace the symbol for UIStackView into FDStackView at runtime before iOS9.
25 |
26 | ``` objc
27 | // Works in iOS6+, use it directly.
28 | UIStackView *stackView = [[UIStackView alloc] init];
29 | stackView.axis = UILayoutConstraintAxisHorizontal;
30 | stackView.distribution = UIStackViewDistributionFill;
31 | stackView.alignment = UIStackViewAlignmentTop;
32 | [stackView addArrangedSubview:[[UILabel alloc] init]];
33 | [self.view addSubview:stackView];
34 | ```
35 |
36 | - Interface Builder Support
37 |
38 | Set `Builds for` option to `iOS 9.0 and later` to eliminate the version error in Xcode:
39 |
40 | 
41 |
42 | Now, use UIStackView as you like and its reactive options and live preview:
43 |
44 | 
45 |
46 | # Requirements
47 |
48 | - Xcode 7+ (For interface builder supports and the latest Objective-C Syntax)
49 | - Base SDK iOS 9.0+ (To link UIStackView symbol in UIKit)
50 |
51 | # Versions
52 |
53 | - 1.0.1 is the lastest version. We released it after we have used it in our official application. And it was successfully passed through the App Store's review. So you have no concern to use it.
54 |
55 | # License
56 |
57 | The MIT License (MIT)
58 |
59 | Copyright (c) 2015-2016 forkingdog ( https://github.com/forkingdog )
60 |
61 | Permission is hereby granted, free of charge, to any person obtaining a copy
62 | of this software and associated documentation files (the "Software"), to deal
63 | in the Software without restriction, including without limitation the rights
64 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
65 | copies of the Software, and to permit persons to whom the Software is
66 | furnished to do so, subject to the following conditions:
67 |
68 | The above copyright notice and this permission notice shall be included in all
69 | copies or substantial portions of the Software.
70 |
71 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
72 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
73 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
74 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
75 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
76 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
77 | SOFTWARE.
78 |
79 |
--------------------------------------------------------------------------------
/FDStackViewDemo/FDStoryboardBasedViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // FDStoryboardBasedViewController.m
3 | // FDStackViewDemo
4 | //
5 | // Created by sunnyxx on 15/9/15.
6 | // Copyright © 2015 forkingdog. All rights reserved.
7 | //
8 |
9 | #import "FDStoryboardBasedViewController.h"
10 |
11 | @interface FDStoryboardBasedViewController ()
12 | @property (nonatomic, weak) IBOutlet UIStackView *stackView;
13 | @property (nonatomic, weak) IBOutlet UIImageView *forkingdogImageView;
14 | @property (nonatomic, weak) IBOutlet UISegmentedControl *axisSegmentControl;
15 | @property (nonatomic, weak) IBOutlet UISegmentedControl *alignmentSegmentControl;
16 | @property (nonatomic, weak) IBOutlet UISegmentedControl *distributionSegmentControl;
17 | @property (nonatomic, weak) IBOutlet UISlider *spacingSlider;
18 | @property (nonatomic, weak) IBOutlet UILabel *spacingLabel;
19 | @property (nonatomic, strong) NSMutableArray *mutableAddingViews;
20 | @end
21 |
22 | @implementation FDStoryboardBasedViewController
23 |
24 | - (void)viewDidLoad {
25 | [super viewDidLoad];
26 | [self updateFromStackViewAttributes];
27 | }
28 |
29 | - (void)updateFromStackViewAttributes {
30 | self.axisSegmentControl.selectedSegmentIndex = self.stackView.axis;
31 | self.alignmentSegmentControl.selectedSegmentIndex = self.stackView.alignment;
32 | self.distributionSegmentControl.selectedSegmentIndex = self.stackView.distribution;
33 | self.spacingLabel.text = [NSString stringWithFormat:@"Spacing (%.1lf)", self.stackView.spacing];
34 | CGSize headerSize = [self.tableView.tableHeaderView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
35 | self.tableView.tableHeaderView.frame = CGRectMake(0, 0, headerSize.width ?: CGRectGetWidth(self.view.frame), headerSize.height);
36 | self.tableView.tableHeaderView = self.tableView.tableHeaderView;
37 | }
38 |
39 | #pragma mark - Actions
40 |
41 | - (IBAction)axisSegmentControlValueChangedAction:(UISegmentedControl *)sender {
42 | self.stackView.axis = sender.selectedSegmentIndex;
43 | [self updateFromStackViewAttributes];
44 | }
45 |
46 | - (IBAction)alignmentSegmentControlValueChangedAction:(UISegmentedControl *)sender {
47 | self.stackView.alignment = sender.selectedSegmentIndex;
48 | [self updateFromStackViewAttributes];
49 | }
50 |
51 | - (IBAction)distributionSegmentControlValueChangedAction:(UISegmentedControl *)sender {
52 | self.stackView.distribution = sender.selectedSegmentIndex;
53 | [self updateFromStackViewAttributes];
54 | }
55 |
56 | - (IBAction)spacingSliderValueChangedAction:(UISlider *)sender {
57 | self.stackView.spacing = sender.value;
58 | [self updateFromStackViewAttributes];
59 | }
60 |
61 | - (IBAction)hideAction:(id)sender {
62 | self.forkingdogImageView.hidden ^= 1;
63 | }
64 |
65 | - (IBAction)addAction:(id)sender {
66 | if (!self.mutableAddingViews) {
67 | self.mutableAddingViews = @[].mutableCopy;
68 | }
69 | UILabel *label = [[UILabel alloc] init];
70 | label.font = [UIFont systemFontOfSize:25];
71 | label.backgroundColor = [UIColor colorWithWhite:arc4random_uniform(255) / 255.0 alpha:1];
72 | label.text = @(self.mutableAddingViews.count).stringValue;
73 | [self.stackView addArrangedSubview:label];
74 |
75 | [self.mutableAddingViews addObject:label];
76 | [self updateFromStackViewAttributes];
77 | }
78 |
79 | - (IBAction)removeAction:(id)sender {
80 | if (self.mutableAddingViews.count == 0) {
81 | return;
82 | }
83 | UILabel *label = self.mutableAddingViews.lastObject;
84 | [label removeFromSuperview];
85 | [self.mutableAddingViews removeObject:label];
86 | [self updateFromStackViewAttributes];
87 | }
88 |
89 | @end
90 |
--------------------------------------------------------------------------------
/FDStackViewDemo/Base.lproj/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
21 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/FDStackView/FDStackView.m:
--------------------------------------------------------------------------------
1 | // The MIT License (MIT)
2 | //
3 | // Copyright (c) 2015-2016 forkingdog ( https://github.com/forkingdog )
4 | //
5 | // Permission is hereby granted, free of charge, to any person obtaining a copy
6 | // of this software and associated documentation files (the "Software"), to deal
7 | // in the Software without restriction, including without limitation the rights
8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | // copies of the Software, and to permit persons to whom the Software is
10 | // furnished to do so, subject to the following conditions:
11 | //
12 | // The above copyright notice and this permission notice shall be included in all
13 | // copies or substantial portions of the Software.
14 | //
15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | // SOFTWARE.
22 |
23 | #import "FDStackView.h"
24 | #import
25 | #import "FDTransformLayer.h"
26 | #import "FDStackViewAlignmentLayoutArrangement.h"
27 | #import "FDStackViewDistributionLayoutArrangement.h"
28 |
29 | @interface FDStackView ()
30 | @property (nonatomic, strong) NSMutableArray *mutableArrangedSubviews;
31 | @property (nonatomic, strong) FDStackViewAlignmentLayoutArrangement *alignmentArrangement;
32 | @property (nonatomic, strong) FDStackViewDistributionLayoutArrangement *distributionArrangement;
33 | @end
34 |
35 | @implementation FDStackView
36 |
37 | + (Class)layerClass {
38 | return FDTransformLayer.class;
39 | }
40 |
41 | - (id)initWithCoder:(NSCoder *)decoder {
42 | self = [super initWithCoder:decoder];
43 | if (self) {
44 | // Attributes of UIStackView in interface builder that archived.
45 | [self commonInitializationWithArrangedSubviews:[decoder decodeObjectForKey:@"UIStackViewArrangedSubviews"]];
46 | self.axis = [decoder decodeIntegerForKey:@"UIStackViewAxis"];
47 | self.distribution = [decoder decodeIntegerForKey:@"UIStackViewDistribution"];
48 | self.alignment = [decoder decodeIntegerForKey:@"UIStackViewAlignment"];
49 | self.spacing = [decoder decodeDoubleForKey:@"UIStackViewSpacing"];
50 | self.baselineRelativeArrangement = [decoder decodeBoolForKey:@"UIStackViewBaselineRelative"];
51 | self.layoutMarginsRelativeArrangement = [decoder decodeBoolForKey:@"UIStackViewLayoutMarginsRelative"];
52 | }
53 | return self;
54 | }
55 |
56 | - (instancetype)initWithArrangedSubviews:(NSArray<__kindof UIView *> *)views {
57 | self = [super initWithFrame:CGRectZero];
58 | if (self) {
59 | [self commonInitializationWithArrangedSubviews:views];
60 | }
61 | return self;
62 | }
63 |
64 | - (instancetype)initWithFrame:(CGRect)frame {
65 | self = [super initWithFrame:frame];
66 | if (self) {
67 | [self commonInitializationWithArrangedSubviews:nil];
68 | }
69 | return self;
70 | }
71 |
72 | - (void)commonInitializationWithArrangedSubviews:(NSArray<__kindof UIView *> *)arrangedSubviews {
73 | self.mutableArrangedSubviews = (arrangedSubviews ?: @[]).mutableCopy;
74 | for (UIView *view in self.mutableArrangedSubviews) {
75 | [self addHiddenObserverForView:view];
76 | }
77 |
78 | self.distributionArrangement = [[FDStackViewDistributionLayoutArrangement alloc] initWithItems:arrangedSubviews onAxis:self.axis];
79 | self.distributionArrangement.canvas = self;
80 | self.alignmentArrangement = [[FDStackViewAlignmentLayoutArrangement alloc] initWithItems:arrangedSubviews onAxis:self.axis];
81 | self.alignmentArrangement.canvas = self;
82 | for (UIView *view in arrangedSubviews) {
83 | view.translatesAutoresizingMaskIntoConstraints = NO;
84 | [self addSubview:view];
85 | }
86 | }
87 |
88 | #pragma mark - Public Arranged Subviews Operations
89 |
90 | - (NSArray *)arrangedSubviews {
91 | return self.mutableArrangedSubviews.copy;
92 | }
93 |
94 | - (void)addArrangedSubview:(UIView *)view {
95 | if (!view || [self.mutableArrangedSubviews containsObject:view]) {
96 | return;
97 | }
98 | [self addSubview:view];
99 | view.translatesAutoresizingMaskIntoConstraints = NO;
100 | [self.mutableArrangedSubviews addObject:view];
101 | [self.alignmentArrangement addItem:view];
102 | [self.distributionArrangement addItem:view];
103 | [self addHiddenObserverForView:view];
104 | [self updateLayoutArrangements];
105 | }
106 |
107 | - (void)removeArrangedSubview:(UIView *)view {
108 | if (![self.mutableArrangedSubviews containsObject:view] || ![view isDescendantOfView:self]) {
109 | return;
110 | }
111 | [self removeHiddenObserverForView:view];
112 | [self.mutableArrangedSubviews removeObject:view];
113 | [view removeFromSuperview];
114 | [self.alignmentArrangement removeItem:view];
115 | [self.distributionArrangement removeItem:view];
116 | [self updateLayoutArrangements];
117 | }
118 |
119 | - (void)insertArrangedSubview:(UIView *)view atIndex:(NSUInteger)stackIndex {
120 | if (!view || [self.mutableArrangedSubviews containsObject:view]) {
121 | return;
122 | }
123 | view.translatesAutoresizingMaskIntoConstraints = NO;
124 | [self insertSubview:view atIndex:stackIndex];
125 | [self.mutableArrangedSubviews insertObject:view atIndex:stackIndex];
126 | [self.alignmentArrangement insertItem:view atIndex:stackIndex];
127 | [self.distributionArrangement insertItem:view atIndex:stackIndex];
128 | [self addHiddenObserverForView:view];
129 | [self updateLayoutArrangements];
130 | }
131 |
132 | #pragma mark - Public Setters
133 |
134 | - (void)setAxis:(UILayoutConstraintAxis)axis {
135 | if (_axis != axis) {
136 | _axis = axis;
137 | self.distributionArrangement.axis = axis;
138 | self.alignmentArrangement.axis = axis;
139 | [self updateLayoutArrangements];
140 | }
141 | }
142 |
143 | - (void)setDistribution:(UIStackViewDistribution)distribution {
144 | if (_distribution != distribution) {
145 | _distribution = distribution;
146 | self.distributionArrangement.distribution = distribution;
147 | [self updateLayoutArrangements];
148 | }
149 | }
150 |
151 | - (void)setAlignment:(UIStackViewAlignment)alignment {
152 | if (_alignment != alignment) {
153 | _alignment = alignment;
154 | self.alignmentArrangement.alignment = alignment;
155 | [self updateLayoutArrangements];
156 | }
157 | }
158 |
159 | - (void)setSpacing:(CGFloat)spacing {
160 | if (_spacing != spacing) {
161 | _spacing = spacing;
162 | self.distributionArrangement.spacing = spacing;
163 | [self updateLayoutArrangements];
164 | }
165 | }
166 |
167 | #pragma mark - Intrinsic Content Size Invalidation
168 |
169 | // Use non-public API in UIView directly is dangerous, so we inject at runtime.
170 | + (void)load {
171 | static dispatch_once_t onceToken;
172 | dispatch_once(&onceToken, ^{
173 | SEL selector = NSSelectorFromString(@"_intrinsicContentSizeInvalidatedForChildView:");
174 | Method method = class_getInstanceMethod(self, @selector(intrinsicContentSizeInvalidatedForChildView:));
175 | class_addMethod(self, selector, method_getImplementation(method), method_getTypeEncoding(method));
176 | });
177 | }
178 |
179 | - (void)intrinsicContentSizeInvalidatedForChildView:(UIView *)childView {
180 | [self.distributionArrangement intrinsicContentSizeInvalidatedForItem:childView];
181 | [self.alignmentArrangement intrinsicContentSizeInvalidatedForItem:childView];
182 | }
183 |
184 | #pragma mark - Layout
185 |
186 | - (void)updateLayoutArrangements {
187 | [self.distributionArrangement removeDeprecatedConstraints];
188 | [self.alignmentArrangement removeDeprecatedConstraints];
189 | [self.distributionArrangement updateArrangementConstraints];
190 | [self.alignmentArrangement updateArrangementConstraints];
191 | }
192 |
193 | - (void)updateConstraints {
194 | [self updateLayoutArrangements];
195 | [super updateConstraints];
196 | }
197 |
198 | #pragma mark - Hidden KVO
199 |
200 | static void *FDStackViewHiddenObservingContext = &FDStackViewHiddenObservingContext;
201 |
202 | - (void)addHiddenObserverForView:(UIView *)view {
203 | [view addObserver:self forKeyPath:@"hidden" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:FDStackViewHiddenObservingContext];
204 | }
205 |
206 | - (void)removeHiddenObserverForView:(UIView *)view {
207 | [view removeObserver:self forKeyPath:@"hidden" context:FDStackViewHiddenObservingContext];
208 | }
209 |
210 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(UIView *)view change:(NSDictionary *)change context:(void *)context {
211 |
212 | if (context != FDStackViewHiddenObservingContext) {
213 | return;
214 | }
215 |
216 | BOOL oldValue = [change[NSKeyValueChangeOldKey] boolValue];
217 | BOOL newValue = [change[NSKeyValueChangeNewKey] boolValue];
218 | if (newValue == oldValue) {
219 | return;
220 | }
221 |
222 | [self.alignmentArrangement updateArrangementConstraints];
223 | [self.distributionArrangement updateArrangementConstraints];
224 | }
225 |
226 | - (void)dealloc {
227 | for (UIView *view in _mutableArrangedSubviews) {
228 | [self removeHiddenObserverForView:view];
229 | }
230 | }
231 |
232 | @end
233 |
234 | // ----------------------------------------------------
235 | // Runtime injection start.
236 | // Assemble codes below are based on:
237 | // https://github.com/0xced/NSUUID/blob/master/NSUUID.m
238 | // ----------------------------------------------------
239 |
240 | #pragma mark - Runtime Injection
241 |
242 | __asm(
243 | ".section __DATA,__objc_classrefs,regular,no_dead_strip\n"
244 | #if TARGET_RT_64_BIT
245 | ".align 3\n"
246 | "L_OBJC_CLASS_UIStackView:\n"
247 | ".quad _OBJC_CLASS_$_UIStackView\n"
248 | #else
249 | ".align 2\n"
250 | "_OBJC_CLASS_UIStackView:\n"
251 | ".long _OBJC_CLASS_$_UIStackView\n"
252 | #endif
253 | ".weak_reference _OBJC_CLASS_$_UIStackView\n"
254 | );
255 |
256 | // Constructors are called after all classes have been loaded.
257 | __attribute__((constructor)) static void FDStackViewPatchEntry(void) {
258 | static dispatch_once_t onceToken;
259 | dispatch_once(&onceToken, ^{
260 | @autoreleasepool {
261 |
262 | // >= iOS9.
263 | if (objc_getClass("UIStackView")) {
264 | return;
265 | }
266 |
267 | Class *stackViewClassLocation = NULL;
268 |
269 | #if TARGET_CPU_ARM
270 | __asm("movw %0, :lower16:(_OBJC_CLASS_UIStackView-(LPC0+4))\n"
271 | "movt %0, :upper16:(_OBJC_CLASS_UIStackView-(LPC0+4))\n"
272 | "LPC0: add %0, pc" : "=r"(stackViewClassLocation));
273 | #elif TARGET_CPU_ARM64
274 | __asm("adrp %0, L_OBJC_CLASS_UIStackView@PAGE\n"
275 | "add %0, %0, L_OBJC_CLASS_UIStackView@PAGEOFF" : "=r"(stackViewClassLocation));
276 | #elif TARGET_CPU_X86_64
277 | __asm("leaq L_OBJC_CLASS_UIStackView(%%rip), %0" : "=r"(stackViewClassLocation));
278 | #elif TARGET_CPU_X86
279 | void *pc = NULL;
280 | __asm("calll L0\n"
281 | "L0: popl %0\n"
282 | "leal _OBJC_CLASS_UIStackView-L0(%0), %1" : "=r"(pc), "=r"(stackViewClassLocation));
283 | #else
284 | #error Unsupported CPU
285 | #endif
286 |
287 | if (stackViewClassLocation && !*stackViewClassLocation) {
288 | Class class = objc_allocateClassPair(FDStackView.class, "UIStackView", 0);
289 | if (class) {
290 | objc_registerClassPair(class);
291 | *stackViewClassLocation = class;
292 | }
293 | }
294 | }
295 | });
296 | }
297 |
--------------------------------------------------------------------------------
/FDStackView/FDStackViewDistributionLayoutArrangement.m:
--------------------------------------------------------------------------------
1 | // The MIT License (MIT)
2 | //
3 | // Copyright (c) 2015-2016 forkingdog ( https://github.com/forkingdog )
4 | //
5 | // Permission is hereby granted, free of charge, to any person obtaining a copy
6 | // of this software and associated documentation files (the "Software"), to deal
7 | // in the Software without restriction, including without limitation the rights
8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | // copies of the Software, and to permit persons to whom the Software is
10 | // furnished to do so, subject to the following conditions:
11 | //
12 | // The above copyright notice and this permission notice shall be included in all
13 | // copies or substantial portions of the Software.
14 | //
15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | // SOFTWARE.
22 |
23 | #import "FDStackViewDistributionLayoutArrangement.h"
24 | #import "FDStackViewExtensions.h"
25 | #import "FDGapLayoutGuide.h"
26 |
27 | @interface FDStackViewDistributionLayoutArrangement ()
28 |
29 | @property (nonatomic, strong) NSMapTable *spacingOrCenteringGuides;
30 | @property (nonatomic, strong) NSMapTable *edgeToEdgeConstraints;
31 | @property (nonatomic, strong) NSMapTable *relatedDimensionConstraints;
32 | @property (nonatomic, strong) NSMapTable *hiddingDimensionConstraints;
33 |
34 | @end
35 |
36 | @implementation FDStackViewDistributionLayoutArrangement
37 |
38 | - (instancetype)initWithItems:(NSArray *)items onAxis:(UILayoutConstraintAxis)axis {
39 | self = [super initWithItems:items onAxis:axis];
40 | if (self) {
41 | _spacingOrCenteringGuides = [NSMapTable weakToWeakObjectsMapTable];
42 | _edgeToEdgeConstraints = [NSMapTable weakToWeakObjectsMapTable];
43 | _relatedDimensionConstraints = [NSMapTable weakToWeakObjectsMapTable];
44 | _hiddingDimensionConstraints = [NSMapTable weakToWeakObjectsMapTable];
45 | }
46 | return self;
47 | }
48 |
49 | - (void)setCanvas:(FDStackView *)canvas {
50 | [super setCanvas:canvas];
51 | }
52 |
53 | - (NSLayoutRelation)edgeToEdgeRelation {
54 | return self.distribution >= UIStackViewDistributionEqualSpacing ? NSLayoutRelationGreaterThanOrEqual : NSLayoutRelationEqual;
55 | }
56 |
57 | - (void)resetFillEffect {
58 | // spacing - edge to edge
59 | [self.canvas removeConstraints:self.edgeToEdgeConstraints.fd_allObjects];
60 | [self.edgeToEdgeConstraints removeAllObjects];
61 | [self.canvas removeConstraints:self.hiddingDimensionConstraints.fd_allObjects];
62 | [self.hiddingDimensionConstraints removeAllObjects];
63 |
64 | UIView *offset = self.items.car;
65 | UIView *last = self.items.lastObject;
66 | for (UIView *view in self.items.cdr) {
67 | NSLayoutAttribute attribute = [self minAttributeForGapConstraint];
68 | NSLayoutRelation relation = [self edgeToEdgeRelation];
69 | NSLayoutConstraint *spacing = [NSLayoutConstraint constraintWithItem:view attribute:attribute relatedBy:relation toItem:offset attribute:attribute + 1 multiplier:1 constant:self.spacing];
70 | spacing.identifier = @"FDSV-spacing";
71 | [self.canvas addConstraint:spacing];
72 | [self.edgeToEdgeConstraints setObject:spacing forKey:offset];
73 | if (offset.hidden || (view == last && view.hidden)) {
74 | spacing.constant = 0;
75 | }
76 | offset = view;
77 | }
78 | // hidding dimensions
79 | for (UIView *view in self.items) {
80 | if (view.hidden) {
81 | NSLayoutAttribute dimensionAttribute = [self dimensionAttributeForCurrentAxis];
82 | NSLayoutConstraint *dimensionConstraint = [NSLayoutConstraint constraintWithItem:view attribute:dimensionAttribute relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:0];
83 | dimensionConstraint.identifier = @"FDSV-hiding";
84 | [self.canvas addConstraint:dimensionConstraint];
85 | [self.hiddingDimensionConstraints setObject:dimensionConstraint forKey:view];
86 | }
87 | }
88 | }
89 |
90 | - (void)resetEquallyEffect {
91 | [self.canvas removeConstraints:self.relatedDimensionConstraints.fd_allObjects];
92 | [self.relatedDimensionConstraints removeAllObjects];
93 |
94 | NSArray *visiableViews = self.visiableItems;
95 | UIView *offset = visiableViews.car;
96 | CGFloat order = 0;
97 | for (UIView *view in visiableViews.cdr) {
98 | NSLayoutAttribute attribute = [self dimensionAttributeForCurrentAxis];
99 | NSLayoutRelation relation = NSLayoutRelationEqual;
100 | CGFloat multiplier = self.distribution == UIStackViewDistributionFillEqually ? 1 : ({
101 | CGSize size1 = offset.intrinsicContentSize;
102 | CGSize size2 = view.intrinsicContentSize;
103 | CGFloat multiplier = 1;
104 | if (attribute == NSLayoutAttributeWidth) {
105 | multiplier = size1.width / size2.width;
106 | } else {
107 | multiplier = size1.height / size2.height;
108 | }
109 | if (CGSizeEqualToSize(size1, CGSizeZero) ||
110 | CGSizeEqualToSize(size2, CGSizeZero)) {
111 | multiplier = 1;
112 | }
113 |
114 | multiplier;
115 | });
116 | NSLayoutConstraint *equally = [NSLayoutConstraint constraintWithItem:offset attribute:attribute relatedBy:relation toItem:view attribute:attribute multiplier:multiplier constant:0];
117 | equally.priority = UILayoutPriorityRequired - (++order);
118 | equally.identifier = self.distribution == UIStackViewDistributionFillEqually ? @"FDSV-fill-equally" : @"FDSV-fill-proportionally";
119 | [self.canvas addConstraint:equally];
120 | [self.relatedDimensionConstraints setObject:equally forKey:offset];
121 |
122 | offset = view;
123 | }
124 | }
125 |
126 | - (NSArray *)visiableItems {
127 | return [self.items filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"hidden=NO"]];
128 | }
129 |
130 | - (void)resetGapEffect {
131 | [self resetSpacingOrCenteringGuides];
132 | [self resetSpacingOrCenteringGuideRelatedDimensionConstraints];
133 | }
134 |
135 | - (void)resetSpacingOrCenteringGuides {
136 | [self.spacingOrCenteringGuides.fd_allObjects makeObjectsPerformSelector:@selector(removeFromSuperview)];
137 | [self.spacingOrCenteringGuides removeAllObjects];
138 | NSArray *visiableItems = self.visiableItems;
139 | if (visiableItems.count <= 1) {
140 | return;
141 | }
142 |
143 | [[visiableItems subarrayWithRange:(NSRange){0, visiableItems.count - 1}] enumerateObjectsUsingBlock:^(UIView *item, NSUInteger idx, BOOL *stop) {
144 | FDGapLayoutGuide *guide = [FDGapLayoutGuide new];
145 | [self.canvas addSubview:guide];
146 | guide.translatesAutoresizingMaskIntoConstraints = NO;
147 | UIView *relatedToItem = visiableItems[idx+1];
148 |
149 | NSLayoutAttribute minGapAttribute = [self minAttributeForGapConstraint];
150 | NSLayoutAttribute minContentAttribute;
151 | NSLayoutAttribute maxContentAttribute;
152 | if (self.distribution == UIStackViewDistributionEqualCentering) {
153 | minContentAttribute = self.axis == UILayoutConstraintAxisHorizontal ? NSLayoutAttributeCenterX : NSLayoutAttributeCenterY;
154 | maxContentAttribute = minContentAttribute;
155 | } else {
156 | minContentAttribute = minGapAttribute;
157 | maxContentAttribute = minGapAttribute + 1;
158 | }
159 |
160 | NSLayoutConstraint *beginGap = [NSLayoutConstraint constraintWithItem:guide attribute:minGapAttribute relatedBy:NSLayoutRelationEqual toItem:item attribute:maxContentAttribute multiplier:1 constant:0];
161 | beginGap.identifier = @"FDSV-distributing-edge";
162 | NSLayoutConstraint *endGap = [NSLayoutConstraint constraintWithItem:relatedToItem attribute:minContentAttribute relatedBy:NSLayoutRelationEqual toItem:guide attribute:minGapAttribute + 1 multiplier:1 constant:0];
163 | endGap.identifier = @"FDSV-distributing-edge";
164 | [self.canvas addConstraint:beginGap];
165 | [self.canvas addConstraint:endGap];
166 |
167 | [self.spacingOrCenteringGuides setObject:guide forKey:item];
168 | }];
169 | }
170 |
171 | - (void)resetSpacingOrCenteringGuideRelatedDimensionConstraints {
172 | [self.canvas removeConstraints:self.relatedDimensionConstraints.fd_allObjects];
173 | NSArray *visiableItems = self.visiableItems;
174 | if (visiableItems.count <= 1) return;
175 |
176 | FDGapLayoutGuide *firstGapGuide = [self.spacingOrCenteringGuides objectForKey:visiableItems.car];
177 | [self.spacingOrCenteringGuides.fd_allObjects enumerateObjectsUsingBlock:^(UIView *obj, NSUInteger idx, BOOL *stop) {
178 | if (firstGapGuide == obj) return;
179 | NSLayoutAttribute dimensionAttribute = [self dimensionAttributeForCurrentAxis];
180 | NSLayoutConstraint *related = [NSLayoutConstraint constraintWithItem:firstGapGuide attribute:dimensionAttribute relatedBy:NSLayoutRelationEqual toItem:obj attribute:dimensionAttribute multiplier:1 constant:0];
181 | related.identifier = @"FDSV-fill-equally";
182 | [self.relatedDimensionConstraints setObject:related forKey:obj];
183 | [self.canvas addConstraint:related];
184 | }];
185 | }
186 |
187 | - (void)resetCanvasConnectionsEffect {
188 | [self.canvas removeConstraints:self.canvasConnectionConstraints];
189 | if (!self.items.count) return;
190 |
191 | NSMutableArray *canvasConnectionConstraints = [NSMutableArray new];
192 | NSLayoutAttribute minAttribute = [self minAttributeForCanvasConnections];
193 | NSLayoutConstraint *head = [NSLayoutConstraint constraintWithItem:self.canvas attribute:minAttribute relatedBy:NSLayoutRelationEqual toItem:self.items.firstObject attribute:minAttribute multiplier:1 constant:0];
194 | [canvasConnectionConstraints addObject:head];
195 | head.identifier = @"FDSV-canvas-connection";
196 |
197 | NSLayoutConstraint *end = [NSLayoutConstraint constraintWithItem:self.canvas attribute:minAttribute + 1 relatedBy:NSLayoutRelationEqual toItem:self.items.lastObject attribute:minAttribute + 1 multiplier:1 constant:0];
198 | [canvasConnectionConstraints addObject:end];
199 | end.identifier = @"FDSV-canvas-connection";
200 |
201 | self.canvasConnectionConstraints = canvasConnectionConstraints;
202 | [self.canvas addConstraints:canvasConnectionConstraints];
203 | }
204 |
205 | - (void)resetAllConstraints {
206 | [self resetCanvasConnectionsEffect];
207 | [self resetFillEffect];
208 |
209 | switch (self.distribution) {
210 | case UIStackViewDistributionFillEqually:
211 | case UIStackViewDistributionFillProportionally:
212 | // related dimension
213 | [self resetEquallyEffect];
214 | break;
215 |
216 | case UIStackViewDistributionEqualCentering:
217 | case UIStackViewDistributionEqualSpacing:
218 | // spacing or centering
219 | [self resetGapEffect];
220 | break;
221 |
222 | default:
223 | break;
224 | }
225 | }
226 |
227 | - (void)removeDeprecatedConstraints {
228 | [self.canvas removeConstraints:self.edgeToEdgeConstraints.fd_allObjects];
229 | [self.edgeToEdgeConstraints removeAllObjects];
230 |
231 | [self.canvas removeConstraints:self.relatedDimensionConstraints.fd_allObjects];
232 | [self.relatedDimensionConstraints removeAllObjects];
233 |
234 | [self.canvas removeConstraints:self.hiddingDimensionConstraints.fd_allObjects];
235 | [self.hiddingDimensionConstraints removeAllObjects];
236 |
237 | [self.spacingOrCenteringGuides.fd_allObjects makeObjectsPerformSelector:@selector(removeFromSuperview)];
238 | [self.spacingOrCenteringGuides removeAllObjects];
239 | }
240 |
241 | - (NSLayoutRelation)layoutRelationForCanvasConnectionForAttribute:(NSLayoutAttribute)attribute {
242 | return NSLayoutRelationEqual;
243 | }
244 |
245 | - (NSLayoutAttribute)minAttributeForCanvasConnections {
246 | return self.axis == UILayoutConstraintAxisHorizontal ? NSLayoutAttributeLeading : NSLayoutAttributeTop;
247 | }
248 |
249 | - (NSLayoutAttribute)centerAttributeForCanvasConnections {
250 | return NSLayoutAttributeCenterY - self.axis; // wtf
251 | }
252 |
253 | - (NSLayoutAttribute)dimensionAttributeForCurrentAxis {
254 | return NSLayoutAttributeWidth + self.axis; // wtf
255 | }
256 |
257 | - (NSLayoutAttribute)minAttributeForGapConstraint {
258 | return self.axis == UILayoutConstraintAxisHorizontal ? NSLayoutAttributeLeading : NSLayoutAttributeTop;
259 | }
260 |
261 | - (void)updateCanvasConnectionConstraintsIfNecessary {
262 | [self resetAllConstraints];
263 | }
264 |
265 | @end
266 |
--------------------------------------------------------------------------------
/FDStackView/FDStackViewAlignmentLayoutArrangement.m:
--------------------------------------------------------------------------------
1 | // The MIT License (MIT)
2 | //
3 | // Copyright (c) 2015-2016 forkingdog ( https://github.com/forkingdog )
4 | //
5 | // Permission is hereby granted, free of charge, to any person obtaining a copy
6 | // of this software and associated documentation files (the "Software"), to deal
7 | // in the Software without restriction, including without limitation the rights
8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | // copies of the Software, and to permit persons to whom the Software is
10 | // furnished to do so, subject to the following conditions:
11 | //
12 | // The above copyright notice and this permission notice shall be included in all
13 | // copies or substantial portions of the Software.
14 | //
15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | // SOFTWARE.
22 |
23 | #import "FDStackViewAlignmentLayoutArrangement.h"
24 | #import "FDStackViewExtensions.h"
25 | #import "FDLayoutSpacer.h"
26 |
27 | @interface FDStackViewAlignmentLayoutArrangement ()
28 | @property (nonatomic, assign) BOOL spanningGuideConstraintsNeedUpdate;
29 | @property (nonatomic, strong) FDLayoutSpacer *spanningLayoutGuide;
30 | @end
31 |
32 | @implementation FDStackViewAlignmentLayoutArrangement
33 |
34 | #pragma mark - Setter / Getter
35 |
36 | - (NSMutableDictionary *)alignmentConstraints {
37 | if (!_alignmentConstraints) {
38 | _alignmentConstraints = [NSMutableDictionary dictionary];
39 | }
40 | return _alignmentConstraints;
41 | }
42 |
43 | - (NSMapTable *)hiddingDimensionConstraints {
44 | if (!_hiddingDimensionConstraints) {
45 | _hiddingDimensionConstraints = [NSMapTable weakToWeakObjectsMapTable];
46 | }
47 | return _hiddingDimensionConstraints;
48 | }
49 |
50 | - (NSString *)alignmentConstraintsFirstKey {
51 | if (self.axis == UILayoutConstraintAxisHorizontal) {
52 | switch (self.alignment) {
53 | case UIStackViewAlignmentFill:
54 | return @"Bottom";
55 | case UIStackViewAlignmentTop:
56 | case UIStackViewAlignmentCenter:
57 | case UIStackViewAlignmentBottom:
58 | case UIStackViewAlignmentFirstBaseline:
59 | case UIStackViewAlignmentLastBaseline:
60 | return @"Ambiguity Suppression";
61 | default:
62 | return @"Not Supported";
63 | }
64 | } else {
65 | switch (self.alignment) {
66 | case UIStackViewAlignmentFill:
67 | return @"Leading";
68 | case UIStackViewAlignmentLeading:
69 | case UIStackViewAlignmentCenter:
70 | case UIStackViewAlignmentTrailing:
71 | return @"Ambiguity Suppression";
72 | default:
73 | return @"Not Supported";
74 | }
75 | }
76 | }
77 |
78 | - (NSString *)alignmentConstraintsSecondKey {
79 | if (self.axis == UILayoutConstraintAxisHorizontal) {
80 | switch (self.alignment) {
81 | case UIStackViewAlignmentBottom:
82 | case UIStackViewAlignmentLastBaseline:
83 | return @"Bottom";
84 | case UIStackViewAlignmentCenter:
85 | return @"CenterY";
86 | case UIStackViewAlignmentTop:
87 | case UIStackViewAlignmentFill:
88 | case UIStackViewAlignmentFirstBaseline:
89 | return @"Top";
90 | default:
91 | return @"Not Supported";
92 | }
93 | } else {
94 | switch (self.alignment) {
95 | case UIStackViewAlignmentLeading:
96 | return @"Leading";
97 | case UIStackViewAlignmentCenter:
98 | return @"CenterX";
99 | case UIStackViewAlignmentTrailing:
100 | case UIStackViewAlignmentFill:
101 | return @"Trailing";
102 | default:
103 | return @"Not Supported";
104 | }
105 | }
106 | }
107 |
108 | - (NSLayoutAttribute)alignmentConstraintsFirstAttribute {
109 | if (self.axis == UILayoutConstraintAxisHorizontal) {
110 | switch (self.alignment) {
111 | case UIStackViewAlignmentFill:
112 | return NSLayoutAttributeBottom;
113 | case UIStackViewAlignmentTop:
114 | case UIStackViewAlignmentCenter:
115 | case UIStackViewAlignmentBottom:
116 | case UIStackViewAlignmentFirstBaseline:
117 | case UIStackViewAlignmentLastBaseline:
118 | return self.dimensionAttributeForCurrentAxis;
119 | default:
120 | return NSLayoutAttributeNotAnAttribute;
121 | }
122 | } else {
123 | switch (self.alignment) {
124 | case UIStackViewAlignmentFill:
125 | return NSLayoutAttributeLeading;
126 | case UIStackViewAlignmentLeading:
127 | case UIStackViewAlignmentCenter:
128 | case UIStackViewAlignmentTrailing:
129 | return self.dimensionAttributeForCurrentAxis;
130 | default:
131 | return NSLayoutAttributeNotAnAttribute;
132 | }
133 | }
134 | }
135 |
136 | - (NSLayoutAttribute)alignmentConstraintsSecondAttribute {
137 | if (self.axis == UILayoutConstraintAxisHorizontal) {
138 | switch (self.alignment) {
139 | case UIStackViewAlignmentBottom:
140 | return NSLayoutAttributeBottom;
141 | case UIStackViewAlignmentCenter:
142 | return NSLayoutAttributeCenterY;
143 | case UIStackViewAlignmentTop:
144 | case UIStackViewAlignmentFill:
145 | return NSLayoutAttributeTop;
146 | case UIStackViewAlignmentFirstBaseline:
147 | return NSLayoutAttributeFirstBaseline;
148 | case UIStackViewAlignmentLastBaseline:
149 | return NSLayoutAttributeLastBaseline;
150 | default:
151 | return NSLayoutAttributeNotAnAttribute;
152 | }
153 | } else {
154 | switch (self.alignment) {
155 | case UIStackViewAlignmentLeading:
156 | return NSLayoutAttributeLeading;
157 | case UIStackViewAlignmentCenter:
158 | return NSLayoutAttributeCenterX;
159 | case UIStackViewAlignmentTrailing:
160 | case UIStackViewAlignmentFill:
161 | return NSLayoutAttributeTrailing;
162 | default:
163 | return NSLayoutAttributeNotAnAttribute;
164 | }
165 | }
166 | }
167 |
168 | - (FDLayoutSpacer *)spanningLayoutGuide {
169 | if (!_spanningLayoutGuide) {
170 | [self createSpanningLayoutGuide];
171 | _spanningGuideConstraintsNeedUpdate = YES;
172 | [self updateSpanningLayoutGuideConstraintsIfNecessary];
173 | }
174 | return _spanningLayoutGuide;
175 | }
176 |
177 | - (void)setAxis:(UILayoutConstraintAxis)axis {
178 | if (self.axis != axis) {
179 | [super setAxis:axis];
180 | [self.spanningLayoutGuide removeFromSuperview];
181 | self.spanningLayoutGuide = nil;
182 | [self configureValidAlignment:&_alignment forAxis:axis];
183 | }
184 | }
185 |
186 | - (void)setAlignment:(UIStackViewAlignment)alignment {
187 | if (_alignment != alignment) {
188 | [self configureValidAlignment:&alignment forAxis:self.axis];
189 | _alignment = alignment;
190 | _spanningGuideConstraintsNeedUpdate = YES;
191 | }
192 | }
193 |
194 | #pragma mark - Override Methods
195 |
196 | - (void)removeDeprecatedConstraints {
197 | [self.alignmentConstraints enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSMapTable *mapTable, BOOL *stop) {
198 | [self.canvas removeConstraints:mapTable.fd_allObjects];
199 | }];
200 | [self.alignmentConstraints removeAllObjects];
201 | [self.canvas removeConstraints:self.hiddingDimensionConstraints.fd_allObjects];
202 | [self.hiddingDimensionConstraints removeAllObjects];
203 | }
204 |
205 | - (NSLayoutAttribute)minAttributeForCanvasConnections {
206 | return self.axis == UILayoutConstraintAxisHorizontal ? NSLayoutAttributeTop : NSLayoutAttributeLeading;
207 | }
208 |
209 | - (NSLayoutAttribute)centerAttributeForCanvasConnections {
210 | return self.axis == UILayoutConstraintAxisHorizontal ? NSLayoutAttributeCenterY : NSLayoutAttributeCenterX;
211 | }
212 |
213 | - (NSLayoutAttribute)maxAttributeForCanvasConnections {
214 | return self.axis == UILayoutConstraintAxisHorizontal ? NSLayoutAttributeBottom : NSLayoutAttributeTrailing;
215 | }
216 |
217 | - (NSLayoutAttribute)dimensionAttributeForCurrentAxis {
218 | return self.axis == UILayoutConstraintAxisHorizontal ? NSLayoutAttributeHeight : NSLayoutAttributeWidth;
219 | }
220 |
221 | - (NSLayoutRelation)layoutRelationForCanvasConnectionForAttribute:(NSLayoutAttribute)attribute {
222 | switch (self.alignment) {
223 | case UIStackViewAlignmentFirstBaseline: {
224 | if (attribute == self.minAttributeForCanvasConnections) {
225 | return NSLayoutRelationGreaterThanOrEqual;
226 | }
227 | break;
228 | }
229 | case UIStackViewAlignmentLastBaseline: {
230 | if (attribute == self.maxAttributeForCanvasConnections) {
231 | return NSLayoutRelationLessThanOrEqual;
232 | }
233 | break;
234 | }
235 | default:
236 | break;
237 | }
238 | return NSLayoutRelationEqual;
239 | }
240 |
241 | - (NSLayoutRelation)layoutRelationForItemConnectionForAttribute:(NSLayoutAttribute)attribute {
242 | switch (self.alignment) {
243 | case UIStackViewAlignmentCenter:
244 | case UIStackViewAlignmentFirstBaseline:
245 | case UIStackViewAlignmentLastBaseline: {
246 | if (attribute == self.minAttributeForCanvasConnections) {
247 | return NSLayoutRelationLessThanOrEqual;
248 | } else if (attribute == self.maxAttributeForCanvasConnections) {
249 | return NSLayoutRelationGreaterThanOrEqual;
250 | }
251 | break;
252 | }
253 | case UIStackViewAlignmentTop: {
254 | if (attribute == self.maxAttributeForCanvasConnections) {
255 | return NSLayoutRelationGreaterThanOrEqual;
256 | }
257 | break;
258 | }
259 | case UIStackViewAlignmentBottom: {
260 | if (attribute == self.minAttributeForCanvasConnections) {
261 | return NSLayoutRelationLessThanOrEqual;
262 | }
263 | break;
264 | }
265 | default:
266 | break;
267 | }
268 | return NSLayoutRelationEqual;
269 | }
270 |
271 | - (void)updateArrangementConstraints {
272 | [self updateSpanningLayoutGuideConstraintsIfNecessary];
273 | [super updateArrangementConstraints];
274 | [self updateAlignmentItemsConstraintsIfNecessary];
275 | }
276 |
277 | - (void)updateCanvasConnectionConstraintsIfNecessary {
278 | if (self.mutableItems.count == 0) {
279 | return;
280 | }
281 |
282 | [self.canvas removeConstraints:self.canvasConnectionConstraints];
283 | [self.canvasConnectionConstraints removeAllObjects];
284 |
285 | NSArray *canvasAttributes = @[@(self.minAttributeForCanvasConnections), @(self.maxAttributeForCanvasConnections)];
286 | if (self.alignment == UIStackViewAlignmentCenter) {
287 | canvasAttributes = [canvasAttributes arrayByAddingObject:@(self.centerAttributeForCanvasConnections)];
288 | } else if (self.isBaselineAlignment) {
289 | NSLayoutConstraint *canvasFitConstraint = [NSLayoutConstraint constraintWithItem:self.canvas attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:0];
290 | canvasFitConstraint.identifier = @"FDSV-canvas-fit";
291 | canvasFitConstraint.priority = 49;
292 | [self.canvas addConstraint:canvasFitConstraint];
293 | [self.canvasConnectionConstraints addObject:canvasFitConstraint];
294 | }
295 |
296 | [canvasAttributes enumerateObjectsUsingBlock:^(NSNumber *canvasAttribute, NSUInteger idx, BOOL *stop) {
297 | NSLayoutAttribute attribute = canvasAttribute.integerValue;
298 | NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:[self viewOrGuideForLocationAttribute:attribute] attribute:attribute relatedBy:[self layoutRelationForCanvasConnectionForAttribute:attribute] toItem:self.canvas attribute:attribute multiplier:1 constant:0];
299 | constraint.identifier = @"FDSV-canvas-connection";
300 | [self.canvas addConstraint:constraint];
301 | [self.canvasConnectionConstraints addObject:constraint];
302 | }];
303 | }
304 |
305 | - (UIView *)viewOrGuideForLocationAttribute:(NSLayoutAttribute)attribute {
306 | switch (self.alignment) {
307 | case UIStackViewAlignmentFill:
308 | return self.mutableItems.firstObject;
309 | case UIStackViewAlignmentTop:
310 | case UIStackViewAlignmentFirstBaseline: {
311 | if (attribute == self.minAttributeForCanvasConnections) {
312 | return self.mutableItems.firstObject;
313 | }
314 | break;
315 | }
316 | case UIStackViewAlignmentCenter: {
317 | if (attribute == self.centerAttributeForCanvasConnections) {
318 | return self.mutableItems.firstObject;
319 | }
320 | break;
321 | }
322 | case UIStackViewAlignmentBottom:
323 | case UIStackViewAlignmentLastBaseline: {
324 | if (attribute == self.maxAttributeForCanvasConnections) {
325 | return self.mutableItems.firstObject;
326 | }
327 | break;
328 | }
329 | default:
330 | break;
331 | }
332 | return self.spanningLayoutGuide;
333 | }
334 |
335 | #pragma mark - Private Methods
336 |
337 | - (void)createSpanningLayoutGuide {
338 | [_spanningLayoutGuide removeFromSuperview];
339 | _spanningLayoutGuide = [FDLayoutSpacer new];
340 | _spanningLayoutGuide.translatesAutoresizingMaskIntoConstraints = NO;
341 | [self.canvas addSubview:_spanningLayoutGuide];
342 | _spanningLayoutGuide.horizontal = self.axis == UILayoutConstraintAxisHorizontal;
343 | }
344 |
345 | - (BOOL)spanningGuideConstraintsNeedUpdate {
346 | if (self.alignment != UIStackViewAlignmentFill && _spanningGuideConstraintsNeedUpdate) {
347 | _spanningGuideConstraintsNeedUpdate = NO;
348 | return YES;
349 | }
350 | return NO;
351 | }
352 |
353 | - (BOOL)isBaselineAlignment {
354 | return self.axis == UILayoutConstraintAxisHorizontal && (self.alignment == UIStackViewAlignmentFirstBaseline || self.alignment == UIStackViewAlignmentLastBaseline);
355 | }
356 |
357 | - (void)configureValidAlignment:(UIStackViewAlignment *)alignment forAxis:(UILayoutConstraintAxis)axis {
358 | if (axis == UILayoutConstraintAxisVertical && (*alignment == UIStackViewAlignmentFirstBaseline || *alignment == UIStackViewAlignmentLastBaseline)) {
359 | NSLog(@"Invalid for vertical axis. Use Leading or Trailing instead.");
360 | *alignment = *alignment == UIStackViewAlignmentFirstBaseline ? UIStackViewAlignmentLeading : UIStackViewAlignmentTrailing;
361 | }
362 | }
363 |
364 | - (void)updateSpanningLayoutGuideConstraintsIfNecessary {
365 | if (self.mutableItems.count == 0) {
366 | return;
367 | }
368 |
369 | if (self.spanningLayoutGuide && self.spanningGuideConstraintsNeedUpdate) {
370 | [self.canvas removeConstraints:self.spanningLayoutGuide.systemConstraints];
371 | [self.spanningLayoutGuide.systemConstraints removeAllObjects];
372 |
373 | //FDSV-spanning-fit
374 | NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:self.spanningLayoutGuide attribute:self.spanningLayoutGuide.isHorizontal ? NSLayoutAttributeWidth : NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:0];
375 | constraint.priority = 51;
376 | constraint.identifier = @"FDSV-spanning-fit";
377 | [self.canvas addConstraint:constraint];
378 | [self.spanningLayoutGuide.systemConstraints addObject:constraint];
379 |
380 | //FDSV-spanning-boundary
381 | [self.mutableItems enumerateObjectsUsingBlock:^(UIView *item, NSUInteger idx, BOOL *stop) {
382 | NSLayoutConstraint *minConstraint = [NSLayoutConstraint constraintWithItem:self.spanningLayoutGuide attribute:self.minAttributeForCanvasConnections relatedBy:[self layoutRelationForItemConnectionForAttribute:self.minAttributeForCanvasConnections] toItem:item attribute:self.minAttributeForCanvasConnections multiplier:1 constant:0];
383 | minConstraint.identifier = @"FDSV-spanning-boundary";
384 | minConstraint.priority = 999.5;
385 | [self.canvas addConstraint:minConstraint];
386 | [self.spanningLayoutGuide.systemConstraints addObject:minConstraint];
387 |
388 | NSLayoutConstraint *maxConstraint = [NSLayoutConstraint constraintWithItem:self.spanningLayoutGuide attribute:self.maxAttributeForCanvasConnections relatedBy:[self layoutRelationForItemConnectionForAttribute:self.maxAttributeForCanvasConnections] toItem:item attribute:self.maxAttributeForCanvasConnections multiplier:1 constant:0];
389 | maxConstraint.identifier = @"FDSV-spanning-boundary";
390 | maxConstraint.priority = 999.5;
391 | [self.canvas addConstraint:maxConstraint];
392 | [self.spanningLayoutGuide.systemConstraints addObject:maxConstraint];
393 | }];
394 | }
395 | }
396 |
397 | - (void)updateAlignmentItemsConstraintsIfNecessary {
398 | if (self.mutableItems.count == 0) {
399 | return;
400 | }
401 |
402 | [self.alignmentConstraints setObject:[NSMapTable weakToWeakObjectsMapTable] forKey:self.alignmentConstraintsFirstKey];
403 | [self.alignmentConstraints setObject:[NSMapTable weakToWeakObjectsMapTable] forKey:self.alignmentConstraintsSecondKey];
404 | [self.canvas removeConstraints:self.hiddingDimensionConstraints.fd_allObjects];
405 | [self.hiddingDimensionConstraints removeAllObjects];
406 |
407 | UIView *guardView = self.mutableItems.firstObject;
408 | [self.mutableItems enumerateObjectsUsingBlock:^(UIView *item, NSUInteger idx, BOOL *stop) {
409 | if (self.alignment != UIStackViewAlignmentFill) {
410 | NSLayoutConstraint *ambiguitySuppressionConstraint = [NSLayoutConstraint constraintWithItem:item attribute:self.alignmentConstraintsFirstAttribute relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:0];
411 | ambiguitySuppressionConstraint.identifier = @"FDSV-ambiguity-suppression";
412 | ambiguitySuppressionConstraint.priority = 25;
413 | [item addConstraint:ambiguitySuppressionConstraint];
414 | [self.alignmentConstraints[self.alignmentConstraintsFirstKey] setObject:ambiguitySuppressionConstraint forKey:item];
415 | } else {
416 | if (item != guardView) {
417 | NSLayoutConstraint *firstConstraint = [NSLayoutConstraint constraintWithItem:guardView attribute:self.alignmentConstraintsFirstAttribute relatedBy:NSLayoutRelationEqual toItem:item attribute:self.alignmentConstraintsFirstAttribute multiplier:1 constant:0];
418 | firstConstraint.identifier = @"FDSV-alignment";
419 | [self.canvas addConstraint:firstConstraint];
420 | [self.alignmentConstraints[self.alignmentConstraintsFirstKey] setObject:firstConstraint forKey:item];
421 | }
422 | }
423 | if (item != guardView) {
424 | NSLayoutConstraint *secondConstraint = [NSLayoutConstraint constraintWithItem:guardView attribute:self.alignmentConstraintsSecondAttribute relatedBy:NSLayoutRelationEqual toItem:item attribute:self.alignmentConstraintsSecondAttribute multiplier:1 constant:0];
425 | secondConstraint.identifier = @"FDSV-alignment";
426 | [self.canvas addConstraint:secondConstraint];
427 | [self.alignmentConstraints[self.alignmentConstraintsSecondKey] setObject:secondConstraint forKey:item];
428 | }
429 | if (item.hidden) {
430 | NSLayoutConstraint *hiddenConstraint = [NSLayoutConstraint constraintWithItem:item attribute:self.axis == UILayoutConstraintAxisHorizontal ? NSLayoutAttributeHeight : NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:0];
431 | hiddenConstraint.priority = [item contentCompressionResistancePriorityForAxis:self.axis == UILayoutConstraintAxisHorizontal ? UILayoutConstraintAxisVertical : UILayoutConstraintAxisHorizontal];
432 | hiddenConstraint.identifier = @"FDSV-hiding";
433 | [self.canvas addConstraint:hiddenConstraint];
434 | [self.hiddingDimensionConstraints setObject:hiddenConstraint forKey:item];
435 | }
436 | }];
437 | }
438 |
439 | @end
440 |
--------------------------------------------------------------------------------
/FDStackViewDemo.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 484BAB3E1BC67ACA00D86EBB /* FDGapLayoutGuide.h in Headers */ = {isa = PBXBuildFile; fileRef = 484BAB2E1BC67ACA00D86EBB /* FDGapLayoutGuide.h */; };
11 | 484BAB3F1BC67ACA00D86EBB /* FDGapLayoutGuide.m in Sources */ = {isa = PBXBuildFile; fileRef = 484BAB2F1BC67ACA00D86EBB /* FDGapLayoutGuide.m */; };
12 | 484BAB401BC67ACA00D86EBB /* FDGapLayoutGuide.m in Sources */ = {isa = PBXBuildFile; fileRef = 484BAB2F1BC67ACA00D86EBB /* FDGapLayoutGuide.m */; };
13 | 484BAB411BC67ACA00D86EBB /* FDLayoutSpacer.h in Headers */ = {isa = PBXBuildFile; fileRef = 484BAB301BC67ACA00D86EBB /* FDLayoutSpacer.h */; };
14 | 484BAB421BC67ACA00D86EBB /* FDLayoutSpacer.m in Sources */ = {isa = PBXBuildFile; fileRef = 484BAB311BC67ACA00D86EBB /* FDLayoutSpacer.m */; };
15 | 484BAB431BC67ACA00D86EBB /* FDLayoutSpacer.m in Sources */ = {isa = PBXBuildFile; fileRef = 484BAB311BC67ACA00D86EBB /* FDLayoutSpacer.m */; };
16 | 484BAB441BC67ACA00D86EBB /* FDStackView.h in Headers */ = {isa = PBXBuildFile; fileRef = 484BAB321BC67ACA00D86EBB /* FDStackView.h */; };
17 | 484BAB451BC67ACA00D86EBB /* FDStackView.m in Sources */ = {isa = PBXBuildFile; fileRef = 484BAB331BC67ACA00D86EBB /* FDStackView.m */; };
18 | 484BAB461BC67ACA00D86EBB /* FDStackView.m in Sources */ = {isa = PBXBuildFile; fileRef = 484BAB331BC67ACA00D86EBB /* FDStackView.m */; };
19 | 484BAB471BC67ACA00D86EBB /* FDStackViewAlignmentLayoutArrangement.h in Headers */ = {isa = PBXBuildFile; fileRef = 484BAB341BC67ACA00D86EBB /* FDStackViewAlignmentLayoutArrangement.h */; };
20 | 484BAB481BC67ACA00D86EBB /* FDStackViewAlignmentLayoutArrangement.m in Sources */ = {isa = PBXBuildFile; fileRef = 484BAB351BC67ACA00D86EBB /* FDStackViewAlignmentLayoutArrangement.m */; };
21 | 484BAB491BC67ACA00D86EBB /* FDStackViewAlignmentLayoutArrangement.m in Sources */ = {isa = PBXBuildFile; fileRef = 484BAB351BC67ACA00D86EBB /* FDStackViewAlignmentLayoutArrangement.m */; };
22 | 484BAB4A1BC67ACA00D86EBB /* FDStackViewDistributionLayoutArrangement.h in Headers */ = {isa = PBXBuildFile; fileRef = 484BAB361BC67ACA00D86EBB /* FDStackViewDistributionLayoutArrangement.h */; };
23 | 484BAB4B1BC67ACA00D86EBB /* FDStackViewDistributionLayoutArrangement.m in Sources */ = {isa = PBXBuildFile; fileRef = 484BAB371BC67ACA00D86EBB /* FDStackViewDistributionLayoutArrangement.m */; };
24 | 484BAB4C1BC67ACA00D86EBB /* FDStackViewDistributionLayoutArrangement.m in Sources */ = {isa = PBXBuildFile; fileRef = 484BAB371BC67ACA00D86EBB /* FDStackViewDistributionLayoutArrangement.m */; };
25 | 484BAB4D1BC67ACA00D86EBB /* FDStackViewExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 484BAB381BC67ACA00D86EBB /* FDStackViewExtensions.h */; };
26 | 484BAB4E1BC67ACA00D86EBB /* FDStackViewExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 484BAB391BC67ACA00D86EBB /* FDStackViewExtensions.m */; };
27 | 484BAB4F1BC67ACA00D86EBB /* FDStackViewExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 484BAB391BC67ACA00D86EBB /* FDStackViewExtensions.m */; };
28 | 484BAB501BC67ACA00D86EBB /* FDStackViewLayoutArrangement.h in Headers */ = {isa = PBXBuildFile; fileRef = 484BAB3A1BC67ACA00D86EBB /* FDStackViewLayoutArrangement.h */; };
29 | 484BAB511BC67ACA00D86EBB /* FDStackViewLayoutArrangement.m in Sources */ = {isa = PBXBuildFile; fileRef = 484BAB3B1BC67ACA00D86EBB /* FDStackViewLayoutArrangement.m */; };
30 | 484BAB521BC67ACA00D86EBB /* FDStackViewLayoutArrangement.m in Sources */ = {isa = PBXBuildFile; fileRef = 484BAB3B1BC67ACA00D86EBB /* FDStackViewLayoutArrangement.m */; };
31 | 484BAB531BC67ACA00D86EBB /* FDTransformLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 484BAB3C1BC67ACA00D86EBB /* FDTransformLayer.h */; };
32 | 484BAB541BC67ACA00D86EBB /* FDTransformLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 484BAB3D1BC67ACA00D86EBB /* FDTransformLayer.m */; };
33 | 484BAB551BC67ACA00D86EBB /* FDTransformLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 484BAB3D1BC67ACA00D86EBB /* FDTransformLayer.m */; };
34 | 484BAB681BC8BDBC00D86EBB /* FDCodeBasedViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 484BAB671BC8BDBC00D86EBB /* FDCodeBasedViewController.m */; };
35 | 48A1298A1B9BE5E500EF9265 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 48A129891B9BE5E500EF9265 /* main.m */; };
36 | 48A1298D1B9BE5E500EF9265 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 48A1298C1B9BE5E500EF9265 /* AppDelegate.m */; };
37 | 48A129931B9BE5E500EF9265 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 48A129911B9BE5E500EF9265 /* Main.storyboard */; };
38 | 48A129951B9BE5E500EF9265 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 48A129941B9BE5E500EF9265 /* Images.xcassets */; };
39 | 48A129981B9BE5E500EF9265 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 48A129961B9BE5E500EF9265 /* LaunchScreen.xib */; };
40 | E153018E1BA8110C00C857EF /* FDStoryboardBasedViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E153018D1BA8110C00C857EF /* FDStoryboardBasedViewController.m */; };
41 | /* End PBXBuildFile section */
42 |
43 | /* Begin PBXCopyFilesBuildPhase section */
44 | 484BAAEF1BC66FC100D86EBB /* CopyFiles */ = {
45 | isa = PBXCopyFilesBuildPhase;
46 | buildActionMask = 2147483647;
47 | dstPath = "include/$(PRODUCT_NAME)";
48 | dstSubfolderSpec = 16;
49 | files = (
50 | );
51 | runOnlyForDeploymentPostprocessing = 0;
52 | };
53 | /* End PBXCopyFilesBuildPhase section */
54 |
55 | /* Begin PBXFileReference section */
56 | 484BAAF11BC66FC100D86EBB /* libFDStackViewPatch.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libFDStackViewPatch.a; sourceTree = BUILT_PRODUCTS_DIR; };
57 | 484BAB2E1BC67ACA00D86EBB /* FDGapLayoutGuide.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FDGapLayoutGuide.h; sourceTree = ""; };
58 | 484BAB2F1BC67ACA00D86EBB /* FDGapLayoutGuide.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FDGapLayoutGuide.m; sourceTree = ""; };
59 | 484BAB301BC67ACA00D86EBB /* FDLayoutSpacer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FDLayoutSpacer.h; sourceTree = ""; };
60 | 484BAB311BC67ACA00D86EBB /* FDLayoutSpacer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FDLayoutSpacer.m; sourceTree = ""; };
61 | 484BAB321BC67ACA00D86EBB /* FDStackView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FDStackView.h; sourceTree = ""; };
62 | 484BAB331BC67ACA00D86EBB /* FDStackView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FDStackView.m; sourceTree = ""; };
63 | 484BAB341BC67ACA00D86EBB /* FDStackViewAlignmentLayoutArrangement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FDStackViewAlignmentLayoutArrangement.h; sourceTree = ""; };
64 | 484BAB351BC67ACA00D86EBB /* FDStackViewAlignmentLayoutArrangement.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FDStackViewAlignmentLayoutArrangement.m; sourceTree = ""; };
65 | 484BAB361BC67ACA00D86EBB /* FDStackViewDistributionLayoutArrangement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FDStackViewDistributionLayoutArrangement.h; sourceTree = ""; };
66 | 484BAB371BC67ACA00D86EBB /* FDStackViewDistributionLayoutArrangement.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FDStackViewDistributionLayoutArrangement.m; sourceTree = ""; };
67 | 484BAB381BC67ACA00D86EBB /* FDStackViewExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FDStackViewExtensions.h; sourceTree = ""; };
68 | 484BAB391BC67ACA00D86EBB /* FDStackViewExtensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FDStackViewExtensions.m; sourceTree = ""; };
69 | 484BAB3A1BC67ACA00D86EBB /* FDStackViewLayoutArrangement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FDStackViewLayoutArrangement.h; sourceTree = ""; };
70 | 484BAB3B1BC67ACA00D86EBB /* FDStackViewLayoutArrangement.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FDStackViewLayoutArrangement.m; sourceTree = ""; };
71 | 484BAB3C1BC67ACA00D86EBB /* FDTransformLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FDTransformLayer.h; sourceTree = ""; };
72 | 484BAB3D1BC67ACA00D86EBB /* FDTransformLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FDTransformLayer.m; sourceTree = ""; };
73 | 484BAB661BC8BDBC00D86EBB /* FDCodeBasedViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FDCodeBasedViewController.h; sourceTree = ""; };
74 | 484BAB671BC8BDBC00D86EBB /* FDCodeBasedViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FDCodeBasedViewController.m; sourceTree = ""; };
75 | 48A129841B9BE5E500EF9265 /* FDStackViewDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FDStackViewDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
76 | 48A129881B9BE5E500EF9265 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
77 | 48A129891B9BE5E500EF9265 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
78 | 48A1298B1B9BE5E500EF9265 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
79 | 48A1298C1B9BE5E500EF9265 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
80 | 48A129921B9BE5E500EF9265 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
81 | 48A129941B9BE5E500EF9265 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
82 | 48A129971B9BE5E500EF9265 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; };
83 | E153018C1BA8110C00C857EF /* FDStoryboardBasedViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FDStoryboardBasedViewController.h; sourceTree = ""; };
84 | E153018D1BA8110C00C857EF /* FDStoryboardBasedViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FDStoryboardBasedViewController.m; sourceTree = ""; };
85 | /* End PBXFileReference section */
86 |
87 | /* Begin PBXFrameworksBuildPhase section */
88 | 484BAAEE1BC66FC100D86EBB /* Frameworks */ = {
89 | isa = PBXFrameworksBuildPhase;
90 | buildActionMask = 2147483647;
91 | files = (
92 | );
93 | runOnlyForDeploymentPostprocessing = 0;
94 | };
95 | 48A129811B9BE5E500EF9265 /* Frameworks */ = {
96 | isa = PBXFrameworksBuildPhase;
97 | buildActionMask = 2147483647;
98 | files = (
99 | );
100 | runOnlyForDeploymentPostprocessing = 0;
101 | };
102 | /* End PBXFrameworksBuildPhase section */
103 |
104 | /* Begin PBXGroup section */
105 | 484BAB2D1BC67ACA00D86EBB /* FDStackView */ = {
106 | isa = PBXGroup;
107 | children = (
108 | 484BAB2E1BC67ACA00D86EBB /* FDGapLayoutGuide.h */,
109 | 484BAB2F1BC67ACA00D86EBB /* FDGapLayoutGuide.m */,
110 | 484BAB301BC67ACA00D86EBB /* FDLayoutSpacer.h */,
111 | 484BAB311BC67ACA00D86EBB /* FDLayoutSpacer.m */,
112 | 484BAB321BC67ACA00D86EBB /* FDStackView.h */,
113 | 484BAB331BC67ACA00D86EBB /* FDStackView.m */,
114 | 484BAB341BC67ACA00D86EBB /* FDStackViewAlignmentLayoutArrangement.h */,
115 | 484BAB351BC67ACA00D86EBB /* FDStackViewAlignmentLayoutArrangement.m */,
116 | 484BAB361BC67ACA00D86EBB /* FDStackViewDistributionLayoutArrangement.h */,
117 | 484BAB371BC67ACA00D86EBB /* FDStackViewDistributionLayoutArrangement.m */,
118 | 484BAB381BC67ACA00D86EBB /* FDStackViewExtensions.h */,
119 | 484BAB391BC67ACA00D86EBB /* FDStackViewExtensions.m */,
120 | 484BAB3A1BC67ACA00D86EBB /* FDStackViewLayoutArrangement.h */,
121 | 484BAB3B1BC67ACA00D86EBB /* FDStackViewLayoutArrangement.m */,
122 | 484BAB3C1BC67ACA00D86EBB /* FDTransformLayer.h */,
123 | 484BAB3D1BC67ACA00D86EBB /* FDTransformLayer.m */,
124 | );
125 | path = FDStackView;
126 | sourceTree = SOURCE_ROOT;
127 | };
128 | 48A1297B1B9BE5E500EF9265 = {
129 | isa = PBXGroup;
130 | children = (
131 | 48A129861B9BE5E500EF9265 /* FDStackViewDemo */,
132 | 48A129851B9BE5E500EF9265 /* Products */,
133 | );
134 | sourceTree = "";
135 | };
136 | 48A129851B9BE5E500EF9265 /* Products */ = {
137 | isa = PBXGroup;
138 | children = (
139 | 48A129841B9BE5E500EF9265 /* FDStackViewDemo.app */,
140 | 484BAAF11BC66FC100D86EBB /* libFDStackViewPatch.a */,
141 | );
142 | name = Products;
143 | sourceTree = "";
144 | };
145 | 48A129861B9BE5E500EF9265 /* FDStackViewDemo */ = {
146 | isa = PBXGroup;
147 | children = (
148 | 484BAB2D1BC67ACA00D86EBB /* FDStackView */,
149 | 48A1298B1B9BE5E500EF9265 /* AppDelegate.h */,
150 | 48A1298C1B9BE5E500EF9265 /* AppDelegate.m */,
151 | 48A129911B9BE5E500EF9265 /* Main.storyboard */,
152 | E153018C1BA8110C00C857EF /* FDStoryboardBasedViewController.h */,
153 | E153018D1BA8110C00C857EF /* FDStoryboardBasedViewController.m */,
154 | 484BAB661BC8BDBC00D86EBB /* FDCodeBasedViewController.h */,
155 | 484BAB671BC8BDBC00D86EBB /* FDCodeBasedViewController.m */,
156 | 48A129941B9BE5E500EF9265 /* Images.xcassets */,
157 | 48A129961B9BE5E500EF9265 /* LaunchScreen.xib */,
158 | 48A129871B9BE5E500EF9265 /* Supporting Files */,
159 | );
160 | path = FDStackViewDemo;
161 | sourceTree = "";
162 | };
163 | 48A129871B9BE5E500EF9265 /* Supporting Files */ = {
164 | isa = PBXGroup;
165 | children = (
166 | 48A129881B9BE5E500EF9265 /* Info.plist */,
167 | 48A129891B9BE5E500EF9265 /* main.m */,
168 | );
169 | name = "Supporting Files";
170 | sourceTree = "";
171 | };
172 | /* End PBXGroup section */
173 |
174 | /* Begin PBXHeadersBuildPhase section */
175 | 484BAB291BC6740400D86EBB /* Headers */ = {
176 | isa = PBXHeadersBuildPhase;
177 | buildActionMask = 2147483647;
178 | files = (
179 | 484BAB411BC67ACA00D86EBB /* FDLayoutSpacer.h in Headers */,
180 | 484BAB471BC67ACA00D86EBB /* FDStackViewAlignmentLayoutArrangement.h in Headers */,
181 | 484BAB4D1BC67ACA00D86EBB /* FDStackViewExtensions.h in Headers */,
182 | 484BAB531BC67ACA00D86EBB /* FDTransformLayer.h in Headers */,
183 | 484BAB501BC67ACA00D86EBB /* FDStackViewLayoutArrangement.h in Headers */,
184 | 484BAB441BC67ACA00D86EBB /* FDStackView.h in Headers */,
185 | 484BAB4A1BC67ACA00D86EBB /* FDStackViewDistributionLayoutArrangement.h in Headers */,
186 | 484BAB3E1BC67ACA00D86EBB /* FDGapLayoutGuide.h in Headers */,
187 | );
188 | runOnlyForDeploymentPostprocessing = 0;
189 | };
190 | /* End PBXHeadersBuildPhase section */
191 |
192 | /* Begin PBXNativeTarget section */
193 | 484BAAF01BC66FC100D86EBB /* FDStackViewPatch */ = {
194 | isa = PBXNativeTarget;
195 | buildConfigurationList = 484BAAF71BC66FC100D86EBB /* Build configuration list for PBXNativeTarget "FDStackViewPatch" */;
196 | buildPhases = (
197 | 484BAAED1BC66FC100D86EBB /* Sources */,
198 | 484BAAEE1BC66FC100D86EBB /* Frameworks */,
199 | 484BAAEF1BC66FC100D86EBB /* CopyFiles */,
200 | 484BAB291BC6740400D86EBB /* Headers */,
201 | );
202 | buildRules = (
203 | );
204 | dependencies = (
205 | );
206 | name = FDStackViewPatch;
207 | productName = FDStackViewPatch;
208 | productReference = 484BAAF11BC66FC100D86EBB /* libFDStackViewPatch.a */;
209 | productType = "com.apple.product-type.library.static";
210 | };
211 | 48A129831B9BE5E500EF9265 /* FDStackViewDemo */ = {
212 | isa = PBXNativeTarget;
213 | buildConfigurationList = 48A129A71B9BE5E500EF9265 /* Build configuration list for PBXNativeTarget "FDStackViewDemo" */;
214 | buildPhases = (
215 | 48A129801B9BE5E500EF9265 /* Sources */,
216 | 48A129811B9BE5E500EF9265 /* Frameworks */,
217 | 48A129821B9BE5E500EF9265 /* Resources */,
218 | );
219 | buildRules = (
220 | );
221 | dependencies = (
222 | );
223 | name = FDStackViewDemo;
224 | productName = FDStackViewDemo;
225 | productReference = 48A129841B9BE5E500EF9265 /* FDStackViewDemo.app */;
226 | productType = "com.apple.product-type.application";
227 | };
228 | /* End PBXNativeTarget section */
229 |
230 | /* Begin PBXProject section */
231 | 48A1297C1B9BE5E500EF9265 /* Project object */ = {
232 | isa = PBXProject;
233 | attributes = {
234 | KnownAssetTags = (
235 | demo,
236 | );
237 | LastSwiftUpdateCheck = 0700;
238 | LastUpgradeCheck = 0700;
239 | ORGANIZATIONNAME = forkingdog;
240 | TargetAttributes = {
241 | 484BAAF01BC66FC100D86EBB = {
242 | CreatedOnToolsVersion = 7.0.1;
243 | };
244 | 48A129831B9BE5E500EF9265 = {
245 | CreatedOnToolsVersion = 6.4;
246 | DevelopmentTeam = Q3443S8FFW;
247 | };
248 | };
249 | };
250 | buildConfigurationList = 48A1297F1B9BE5E500EF9265 /* Build configuration list for PBXProject "FDStackViewDemo" */;
251 | compatibilityVersion = "Xcode 3.2";
252 | developmentRegion = English;
253 | hasScannedForEncodings = 0;
254 | knownRegions = (
255 | en,
256 | Base,
257 | );
258 | mainGroup = 48A1297B1B9BE5E500EF9265;
259 | productRefGroup = 48A129851B9BE5E500EF9265 /* Products */;
260 | projectDirPath = "";
261 | projectRoot = "";
262 | targets = (
263 | 48A129831B9BE5E500EF9265 /* FDStackViewDemo */,
264 | 484BAAF01BC66FC100D86EBB /* FDStackViewPatch */,
265 | );
266 | };
267 | /* End PBXProject section */
268 |
269 | /* Begin PBXResourcesBuildPhase section */
270 | 48A129821B9BE5E500EF9265 /* Resources */ = {
271 | isa = PBXResourcesBuildPhase;
272 | buildActionMask = 2147483647;
273 | files = (
274 | 48A129931B9BE5E500EF9265 /* Main.storyboard in Resources */,
275 | 48A129981B9BE5E500EF9265 /* LaunchScreen.xib in Resources */,
276 | 48A129951B9BE5E500EF9265 /* Images.xcassets in Resources */,
277 | );
278 | runOnlyForDeploymentPostprocessing = 0;
279 | };
280 | /* End PBXResourcesBuildPhase section */
281 |
282 | /* Begin PBXSourcesBuildPhase section */
283 | 484BAAED1BC66FC100D86EBB /* Sources */ = {
284 | isa = PBXSourcesBuildPhase;
285 | buildActionMask = 2147483647;
286 | files = (
287 | 484BAB551BC67ACA00D86EBB /* FDTransformLayer.m in Sources */,
288 | 484BAB401BC67ACA00D86EBB /* FDGapLayoutGuide.m in Sources */,
289 | 484BAB461BC67ACA00D86EBB /* FDStackView.m in Sources */,
290 | 484BAB491BC67ACA00D86EBB /* FDStackViewAlignmentLayoutArrangement.m in Sources */,
291 | 484BAB4C1BC67ACA00D86EBB /* FDStackViewDistributionLayoutArrangement.m in Sources */,
292 | 484BAB431BC67ACA00D86EBB /* FDLayoutSpacer.m in Sources */,
293 | 484BAB4F1BC67ACA00D86EBB /* FDStackViewExtensions.m in Sources */,
294 | 484BAB521BC67ACA00D86EBB /* FDStackViewLayoutArrangement.m in Sources */,
295 | );
296 | runOnlyForDeploymentPostprocessing = 0;
297 | };
298 | 48A129801B9BE5E500EF9265 /* Sources */ = {
299 | isa = PBXSourcesBuildPhase;
300 | buildActionMask = 2147483647;
301 | files = (
302 | 48A1298D1B9BE5E500EF9265 /* AppDelegate.m in Sources */,
303 | 484BAB451BC67ACA00D86EBB /* FDStackView.m in Sources */,
304 | 484BAB4E1BC67ACA00D86EBB /* FDStackViewExtensions.m in Sources */,
305 | 484BAB4B1BC67ACA00D86EBB /* FDStackViewDistributionLayoutArrangement.m in Sources */,
306 | 484BAB511BC67ACA00D86EBB /* FDStackViewLayoutArrangement.m in Sources */,
307 | 48A1298A1B9BE5E500EF9265 /* main.m in Sources */,
308 | 484BAB421BC67ACA00D86EBB /* FDLayoutSpacer.m in Sources */,
309 | 484BAB541BC67ACA00D86EBB /* FDTransformLayer.m in Sources */,
310 | 484BAB481BC67ACA00D86EBB /* FDStackViewAlignmentLayoutArrangement.m in Sources */,
311 | 484BAB681BC8BDBC00D86EBB /* FDCodeBasedViewController.m in Sources */,
312 | E153018E1BA8110C00C857EF /* FDStoryboardBasedViewController.m in Sources */,
313 | 484BAB3F1BC67ACA00D86EBB /* FDGapLayoutGuide.m in Sources */,
314 | );
315 | runOnlyForDeploymentPostprocessing = 0;
316 | };
317 | /* End PBXSourcesBuildPhase section */
318 |
319 | /* Begin PBXVariantGroup section */
320 | 48A129911B9BE5E500EF9265 /* Main.storyboard */ = {
321 | isa = PBXVariantGroup;
322 | children = (
323 | 48A129921B9BE5E500EF9265 /* Base */,
324 | );
325 | name = Main.storyboard;
326 | sourceTree = "";
327 | };
328 | 48A129961B9BE5E500EF9265 /* LaunchScreen.xib */ = {
329 | isa = PBXVariantGroup;
330 | children = (
331 | 48A129971B9BE5E500EF9265 /* Base */,
332 | );
333 | name = LaunchScreen.xib;
334 | sourceTree = "";
335 | };
336 | /* End PBXVariantGroup section */
337 |
338 | /* Begin XCBuildConfiguration section */
339 | 484BAAF81BC66FC100D86EBB /* Debug */ = {
340 | isa = XCBuildConfiguration;
341 | buildSettings = {
342 | DEBUG_INFORMATION_FORMAT = dwarf;
343 | IPHONEOS_DEPLOYMENT_TARGET = 6.0;
344 | OTHER_LDFLAGS = "-ObjC";
345 | PRODUCT_NAME = "$(TARGET_NAME)";
346 | SKIP_INSTALL = YES;
347 | };
348 | name = Debug;
349 | };
350 | 484BAAF91BC66FC100D86EBB /* Release */ = {
351 | isa = XCBuildConfiguration;
352 | buildSettings = {
353 | IPHONEOS_DEPLOYMENT_TARGET = 6.0;
354 | OTHER_LDFLAGS = "-ObjC";
355 | PRODUCT_NAME = "$(TARGET_NAME)";
356 | SKIP_INSTALL = YES;
357 | };
358 | name = Release;
359 | };
360 | 48A129A51B9BE5E500EF9265 /* Debug */ = {
361 | isa = XCBuildConfiguration;
362 | buildSettings = {
363 | ALWAYS_SEARCH_USER_PATHS = NO;
364 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
365 | CLANG_CXX_LIBRARY = "libc++";
366 | CLANG_ENABLE_MODULES = YES;
367 | CLANG_ENABLE_OBJC_ARC = YES;
368 | CLANG_WARN_BOOL_CONVERSION = YES;
369 | CLANG_WARN_CONSTANT_CONVERSION = YES;
370 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
371 | CLANG_WARN_EMPTY_BODY = YES;
372 | CLANG_WARN_ENUM_CONVERSION = YES;
373 | CLANG_WARN_INT_CONVERSION = YES;
374 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
375 | CLANG_WARN_UNREACHABLE_CODE = YES;
376 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
377 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
378 | COPY_PHASE_STRIP = NO;
379 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
380 | ENABLE_STRICT_OBJC_MSGSEND = YES;
381 | ENABLE_TESTABILITY = YES;
382 | GCC_C_LANGUAGE_STANDARD = gnu99;
383 | GCC_DYNAMIC_NO_PIC = NO;
384 | GCC_NO_COMMON_BLOCKS = YES;
385 | GCC_OPTIMIZATION_LEVEL = 0;
386 | GCC_PREPROCESSOR_DEFINITIONS = (
387 | "DEBUG=1",
388 | "$(inherited)",
389 | );
390 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
391 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
392 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
393 | GCC_WARN_UNDECLARED_SELECTOR = YES;
394 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
395 | GCC_WARN_UNUSED_FUNCTION = YES;
396 | GCC_WARN_UNUSED_VARIABLE = YES;
397 | IPHONEOS_DEPLOYMENT_TARGET = 7.0;
398 | MTL_ENABLE_DEBUG_INFO = YES;
399 | ONLY_ACTIVE_ARCH = YES;
400 | SDKROOT = iphoneos;
401 | };
402 | name = Debug;
403 | };
404 | 48A129A61B9BE5E500EF9265 /* Release */ = {
405 | isa = XCBuildConfiguration;
406 | buildSettings = {
407 | ALWAYS_SEARCH_USER_PATHS = NO;
408 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
409 | CLANG_CXX_LIBRARY = "libc++";
410 | CLANG_ENABLE_MODULES = YES;
411 | CLANG_ENABLE_OBJC_ARC = YES;
412 | CLANG_WARN_BOOL_CONVERSION = YES;
413 | CLANG_WARN_CONSTANT_CONVERSION = YES;
414 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
415 | CLANG_WARN_EMPTY_BODY = YES;
416 | CLANG_WARN_ENUM_CONVERSION = YES;
417 | CLANG_WARN_INT_CONVERSION = YES;
418 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
419 | CLANG_WARN_UNREACHABLE_CODE = YES;
420 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
421 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
422 | COPY_PHASE_STRIP = NO;
423 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
424 | ENABLE_NS_ASSERTIONS = NO;
425 | ENABLE_STRICT_OBJC_MSGSEND = YES;
426 | GCC_C_LANGUAGE_STANDARD = gnu99;
427 | GCC_NO_COMMON_BLOCKS = YES;
428 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
429 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
430 | GCC_WARN_UNDECLARED_SELECTOR = YES;
431 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
432 | GCC_WARN_UNUSED_FUNCTION = YES;
433 | GCC_WARN_UNUSED_VARIABLE = YES;
434 | IPHONEOS_DEPLOYMENT_TARGET = 7.0;
435 | MTL_ENABLE_DEBUG_INFO = NO;
436 | SDKROOT = iphoneos;
437 | VALIDATE_PRODUCT = YES;
438 | };
439 | name = Release;
440 | };
441 | 48A129A81B9BE5E500EF9265 /* Debug */ = {
442 | isa = XCBuildConfiguration;
443 | buildSettings = {
444 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
445 | CLANG_ENABLE_MODULES = YES;
446 | CODE_SIGN_IDENTITY = "iPhone Developer";
447 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
448 | INFOPLIST_FILE = FDStackViewDemo/Info.plist;
449 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
450 | PRODUCT_BUNDLE_IDENTIFIER = "com.forkingdog.$(PRODUCT_NAME:rfc1034identifier)";
451 | PRODUCT_NAME = "$(TARGET_NAME)";
452 | PROVISIONING_PROFILE = "f3885f66-1ec2-4718-b197-0dc5422cb085";
453 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
454 | };
455 | name = Debug;
456 | };
457 | 48A129A91B9BE5E500EF9265 /* Release */ = {
458 | isa = XCBuildConfiguration;
459 | buildSettings = {
460 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
461 | CLANG_ENABLE_MODULES = YES;
462 | CODE_SIGN_IDENTITY = "iPhone Developer";
463 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
464 | INFOPLIST_FILE = FDStackViewDemo/Info.plist;
465 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
466 | PRODUCT_BUNDLE_IDENTIFIER = "com.forkingdog.$(PRODUCT_NAME:rfc1034identifier)";
467 | PRODUCT_NAME = "$(TARGET_NAME)";
468 | PROVISIONING_PROFILE = "f3885f66-1ec2-4718-b197-0dc5422cb085";
469 | };
470 | name = Release;
471 | };
472 | /* End XCBuildConfiguration section */
473 |
474 | /* Begin XCConfigurationList section */
475 | 484BAAF71BC66FC100D86EBB /* Build configuration list for PBXNativeTarget "FDStackViewPatch" */ = {
476 | isa = XCConfigurationList;
477 | buildConfigurations = (
478 | 484BAAF81BC66FC100D86EBB /* Debug */,
479 | 484BAAF91BC66FC100D86EBB /* Release */,
480 | );
481 | defaultConfigurationIsVisible = 0;
482 | defaultConfigurationName = Release;
483 | };
484 | 48A1297F1B9BE5E500EF9265 /* Build configuration list for PBXProject "FDStackViewDemo" */ = {
485 | isa = XCConfigurationList;
486 | buildConfigurations = (
487 | 48A129A51B9BE5E500EF9265 /* Debug */,
488 | 48A129A61B9BE5E500EF9265 /* Release */,
489 | );
490 | defaultConfigurationIsVisible = 0;
491 | defaultConfigurationName = Release;
492 | };
493 | 48A129A71B9BE5E500EF9265 /* Build configuration list for PBXNativeTarget "FDStackViewDemo" */ = {
494 | isa = XCConfigurationList;
495 | buildConfigurations = (
496 | 48A129A81B9BE5E500EF9265 /* Debug */,
497 | 48A129A91B9BE5E500EF9265 /* Release */,
498 | );
499 | defaultConfigurationIsVisible = 0;
500 | defaultConfigurationName = Release;
501 | };
502 | /* End XCConfigurationList section */
503 | };
504 | rootObject = 48A1297C1B9BE5E500EF9265 /* Project object */;
505 | }
506 |
--------------------------------------------------------------------------------
/FDStackViewDemo/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
107 |
108 |
109 |
110 |
111 |
119 |
127 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
360 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
393 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
--------------------------------------------------------------------------------