├── .gitattributes ├── .github └── workflows │ └── github-actions-ci.yml ├── .gitignore ├── .jazzy.yaml ├── .swiftlint.yml ├── .swiftpm └── xcode │ └── package.xcworkspace │ └── contents.xcworkspacedata ├── CHANGELOG.md ├── Example ├── .gitignore ├── .swiftlint.yml ├── FlexLayoutSample │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ ├── Supporting Files │ │ ├── Assets.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ ├── Contents.json │ │ │ │ ├── Icon-App-60x60@2x.png │ │ │ │ ├── Icon-App-60x60@3x.png │ │ │ │ ├── Icon-App-76x76@1x.png │ │ │ │ ├── Icon-App-76x76@2x.png │ │ │ │ ├── Icon-App-83.5x83.5@2x.png │ │ │ │ └── iTunesArtwork@2x.png │ │ │ ├── Contents.json │ │ │ ├── filter-box-check.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── filter-box-check@2x.png │ │ │ │ └── filter-box-check@3x.png │ │ │ ├── flexlayout-logo.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── flexlayout-logo.png │ │ │ ├── method.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── method.png │ │ │ └── raywenderlich │ │ │ │ ├── Contents.json │ │ │ │ ├── add.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── add.png │ │ │ │ └── add@2x.png │ │ │ │ ├── download.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── download.png │ │ │ │ └── download@2x.png │ │ │ │ ├── share.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── share.png │ │ │ │ └── share@2x.png │ │ │ │ └── sherlock.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── sherlock.png │ │ ├── Base.lproj │ │ │ └── LaunchScreen.storyboard │ │ ├── Info.plist │ │ └── flexlayout-logo.png │ └── UI │ │ ├── Common │ │ ├── BaseViewController.swift │ │ ├── BasicView.swift │ │ ├── Stylesheet.swift │ │ └── UIImageView+Download.swift │ │ ├── Examples │ │ ├── CollectionViewExample │ │ │ ├── CollectionViewExampleView.swift │ │ │ ├── CollectionViewExampleViewController.swift │ │ │ └── HouseCell.swift │ │ ├── Example1 │ │ │ ├── Example1View.swift │ │ │ └── Example1ViewController.swift │ │ ├── Flexbox │ │ │ ├── FlexboxViewController.swift │ │ │ ├── MyTestView.swift │ │ │ └── MyTestViewController.swift │ │ ├── Intro │ │ │ ├── IntroView.swift │ │ │ └── IntroViewController.swift │ │ ├── RaywenderlichTutorial │ │ │ ├── Data │ │ │ │ ├── Show.swift │ │ │ │ └── Shows.plist │ │ │ ├── RaywenderlichTutorialView.swift │ │ │ ├── RaywenderlichTutorialViewController.swift │ │ │ └── Subviews │ │ │ │ ├── ExpandedTableView.swift │ │ │ │ └── ShowTableViewCell.swift │ │ ├── TableViewExample │ │ │ ├── Subviews │ │ │ │ ├── MethodCell.swift │ │ │ │ └── MethodGroupHeader.swift │ │ │ ├── TableViewExampleView.swift │ │ │ └── TableViewExampleViewController.swift │ │ ├── UnitTests │ │ │ └── UnitTestsViewController.swift │ │ ├── YogaExampleA │ │ │ ├── YogaExampleAView.swift │ │ │ └── YogaExampleAViewController.swift │ │ ├── YogaExampleB │ │ │ ├── YogaExampleBView.swift │ │ │ └── YogaExampleBViewController.swift │ │ ├── YogaExampleC │ │ │ ├── YogaExampleCView.swift │ │ │ └── YogaExampleCViewController.swift │ │ ├── YogaExampleD │ │ │ ├── YogaExampleDView.swift │ │ │ └── YogaExampleDViewController.swift │ │ ├── YogaExampleE │ │ │ ├── YogaExampleEView.swift │ │ │ └── YogaExampleEViewController.swift │ │ └── YogaExampleF │ │ │ ├── YogaExampleFView.swift │ │ │ └── YogaExampleFViewController.swift │ │ └── Menu │ │ ├── MenuView.swift │ │ └── MenuViewController.swift ├── SPM │ └── FlexLayoutSample-SPM.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcshareddata │ │ └── xcschemes │ │ └── FlexLayoutSample-SPM.xcscheme └── cocoapods │ └── FlexLayoutSample.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ └── xcschemes │ └── FlexLayoutSample.xcscheme ├── FlexLayout.podspec ├── FlexLayout.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── FlexLayout.xcscmblueprint │ │ └── IDEWorkspaceChecks.plist ├── xcshareddata │ └── xcschemes │ │ └── FlexLayoutInner.xcscheme └── xcuserdata │ └── dionlu.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist ├── FlexLayout.xcworkspace ├── contents.xcworkspacedata └── xcshareddata │ └── IDEWorkspaceChecks.plist ├── Gemfile ├── Gemfile.lock ├── LICENSE ├── Package.resolved ├── Package.swift ├── Podfile ├── Podfile.lock ├── README.md ├── Sources ├── Swift │ ├── FlexLayout.swift │ ├── Impl │ │ ├── FlexLayout+Enum.swift │ │ ├── FlexLayout+Private.swift │ │ └── UIView+FlexLayout.swift │ ├── Percent.swift │ ├── Public │ │ └── FlexLayout.h │ └── YGLayoutExtensions.swift └── YogaKit │ ├── UIView+Yoga.mm │ ├── YGLayout.mm │ └── include │ └── YogaKit │ ├── UIView+Yoga.h │ ├── YGLayout+Private.h │ └── YGLayout.h ├── Tests └── FlexLayoutTests │ ├── FlexLayoutTests.swift │ ├── InsetTests.swift │ ├── JustifyContentTests.swift │ ├── MarginTests.swift │ ├── PaddingTests.swift │ └── WidthSizeContentTests.swift ├── docs └── 1.1 │ ├── Classes.html │ ├── Classes │ ├── Flex.html │ └── Flex │ │ ├── AlignContent.html │ │ ├── AlignItems.html │ │ ├── AlignSelf.html │ │ ├── Direction.html │ │ ├── JustifyContent.html │ │ ├── LayoutDirection.html │ │ ├── LayoutMode.html │ │ ├── Position.html │ │ └── Wrap.html │ ├── badge.svg │ ├── css │ ├── highlight.css │ └── jazzy.css │ ├── docsets │ ├── FlexLayout.docset │ │ └── Contents │ │ │ ├── Info.plist │ │ │ └── Resources │ │ │ ├── Documents │ │ │ ├── Classes.html │ │ │ ├── Classes │ │ │ │ ├── Flex.html │ │ │ │ └── Flex │ │ │ │ │ ├── AlignContent.html │ │ │ │ │ ├── AlignItems.html │ │ │ │ │ ├── AlignSelf.html │ │ │ │ │ ├── Direction.html │ │ │ │ │ ├── JustifyContent.html │ │ │ │ │ ├── LayoutDirection.html │ │ │ │ │ ├── LayoutMode.html │ │ │ │ │ ├── Position.html │ │ │ │ │ └── Wrap.html │ │ │ ├── css │ │ │ │ ├── highlight.css │ │ │ │ └── jazzy.css │ │ │ ├── img │ │ │ │ ├── carat.png │ │ │ │ ├── dash.png │ │ │ │ └── gh.png │ │ │ ├── index.html │ │ │ ├── js │ │ │ │ ├── jazzy.js │ │ │ │ └── jquery.min.js │ │ │ └── search.json │ │ │ └── docSet.dsidx │ └── FlexLayout.tgz │ ├── img │ ├── carat.png │ ├── dash.png │ └── gh.png │ ├── index.html │ ├── js │ ├── jazzy.js │ └── jquery.min.js │ ├── search.json │ └── undocumented.json ├── docs_markdown ├── benchmark.md ├── benchmark │ └── benchmark_comparison_all_small.png ├── contributing.md ├── examples.md └── images │ ├── axis-column.png │ ├── axis-row.png │ ├── examples │ ├── flexlayout_example_collectionview.png │ ├── flexlayout_exampleapp_intro_all.png │ ├── flexlayout_exampleapp_intro_landscape.png │ ├── flexlayout_exampleapp_intro_portrait.png │ ├── flexlayout_exampleapp_ray_wenderlich_tutorial.png │ ├── flexlayout_exampleapp_uitableview.png │ ├── flexlayout_exampleapp_yoga_android.png │ ├── flexlayout_exampleapp_yoga_c.png │ ├── flexlayout_exampleapp_yoga_csharp.png │ ├── flexlayout_exampleapp_yoga_java.png │ └── flexlayout_exampleapp_yoga_objc.png │ ├── flexlayout-align-column-center.png │ ├── flexlayout-align-column-flexEnd.png │ ├── flexlayout-align-column-flexStart.png │ ├── flexlayout-align-column-stretch.png │ ├── flexlayout-align-row-baseline.png │ ├── flexlayout-align-row-center.png │ ├── flexlayout-align-row-flexEnd.png │ ├── flexlayout-align-row-flexStart.png │ ├── flexlayout-align-row-stretch.png │ ├── flexlayout-align-row-stretch2.png │ ├── flexlayout-alignItems-column-center.png │ ├── flexlayout-alignItems-column-flexEnd.png │ ├── flexlayout-alignItems-column-flexStart.png │ ├── flexlayout-alignItems-column-spaceAround.png │ ├── flexlayout-alignItems-column-spaceBetween.png │ ├── flexlayout-alignItems-column-stretch.png │ ├── flexlayout-alignItems-row-center.png │ ├── flexlayout-alignItems-row-flexEnd.png │ ├── flexlayout-alignItems-row-flexStart.png │ ├── flexlayout-alignItems-row-spaceAround.png │ ├── flexlayout-alignItems-row-spaceBetween.png │ ├── flexlayout-alignItems-row-stretch.png │ ├── flexlayout-direction-column.png │ ├── flexlayout-direction-columnReverse.png │ ├── flexlayout-direction-row.png │ ├── flexlayout-direction-rowReverse.png │ ├── flexlayout-justify-column-center.png │ ├── flexlayout-justify-column-flexend.png │ ├── flexlayout-justify-column-flexstart.png │ ├── flexlayout-justify-column-spacearound.png │ ├── flexlayout-justify-column-spacebetween.png │ ├── flexlayout-justify-column-spaceevenly.png │ ├── flexlayout-justify-row-center.png │ ├── flexlayout-justify-row-flexend.png │ ├── flexlayout-justify-row-flexstart.png │ ├── flexlayout-justify-row-spacearound.png │ ├── flexlayout-justify-row-spacebetween.png │ ├── flexlayout-justify-row-spaceevenly.png │ ├── flexlayout-logo-2.png │ ├── flexlayout-logo-text.png │ ├── flexlayout-wrap-column-nowrap.png │ ├── flexlayout-wrap-column-wrap.png │ ├── flexlayout-wrap-column-wrapReverse.png │ ├── flexlayout-wrap-row-nowrap.png │ ├── flexlayout-wrap-row-wrap.png │ ├── flexlayout-wrap-row-wrapReverse.png │ ├── flexlayout_example_column_center.png │ ├── flexlayout_plus_pinlayout_small.png │ ├── pinlayout_plus_flexlayout_small.png │ └── pinlayout_plus_flexlayout_smaller.png └── fastlane └── Fastfile /.gitattributes: -------------------------------------------------------------------------------- 1 | Sources/yoga/* linguist-vendored 2 | core-tests/* linguist-vendored 3 | lib/* linguist-vendored 4 | -------------------------------------------------------------------------------- /.github/workflows/github-actions-ci.yml: -------------------------------------------------------------------------------- 1 | name: Run CI 2 | on: [push, pull_request] 3 | 4 | jobs: 5 | CI: 6 | # ℹ️ Available GitHub Actions Runner Images 7 | # https://github.com/actions/runner-images 8 | runs-on: macos-13 9 | 10 | steps: 11 | - name: Checkout 12 | uses: actions/checkout@v2 13 | 14 | - run: bundle install 15 | - run: pod install --repo-update 16 | 17 | - name: Set Xcode Version 15.1.0 (iOS 17) 18 | run: sudo xcode-select -s /Applications/Xcode_15.1.app 19 | 20 | - name: fastlane 21 | run: set -o pipefail && bundle exec fastlane travis 22 | 23 | - run: bash <(curl -s https://codecov.io/bash) -J 'FlexLayout' -J 'FlexLayoutTests' 24 | 25 | - run: echo "🍏 This job's status is ${{ job.status }}." 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | 4 | .versions 5 | .build/ 6 | xcuserdata 7 | Data/ 8 | Pods/ 9 | FlexLayout.xcodeproj/project.xcworkspace/xcuserdata 10 | 11 | # Carthage 12 | Carthage/Build/.*.version 13 | Carthage/Build/iOS/*.dSYM 14 | Carthage/Build/iOS/*.bcsymbolmap 15 | Carthage/Build/tvOS 16 | Carthage/Checkouts 17 | 18 | # Buck 19 | /buck-cache/ 20 | /buck-out/ 21 | /.buckconfig.local 22 | /.buckd 23 | /gentest/test.html 24 | .buckversion 25 | 26 | fastlane/report.xml 27 | fastlane/test_output 28 | 29 | # SwiftPM 30 | swiftpm/ 31 | 32 | # Mac 33 | .DS_Store -------------------------------------------------------------------------------- /.jazzy.yaml: -------------------------------------------------------------------------------- 1 | clean: true 2 | output: docs/1.1 3 | module_version: 1.1 4 | 5 | # framework_root: Sources/ 6 | # podspec: FlexLayout.podspec 7 | author: lucdion 8 | author_url: https://github.com/lucdion 9 | module: FlexLayout 10 | # readme: README.md 11 | # documentation: docs/benchmark/*.md 12 | github_url: https://github.com/lucdion/FlexLayout 13 | github_file_prefix: https://github.com/lucdion/FlexLayout/tree/master 14 | xcodebuild_arguments: [-scheme,FlexLayout] 15 | theme: apple 16 | exclude: [Sources/Percent.swift, Sources/YogaKit/*, Sources/Impl/UIView+FlexLayout.swift] 17 | # exclude: README.md 18 | readme: docs_api/API.md 19 | # root_url: 20 | -------------------------------------------------------------------------------- /.swiftlint.yml: -------------------------------------------------------------------------------- 1 | opt_in_rules: # some rules are only opt-in 2 | - closure_end_indentation 3 | - closure_spacing 4 | - explicit_init 5 | - number_separator 6 | - operator_usage_whitespace 7 | - overridden_super_call 8 | - private_outlet 9 | - prohibited_super_call 10 | - redundant_nil_coalescing 11 | 12 | disabled_rules: # rule identifiers to exclude from running 13 | - function_body_length 14 | - trailing_whitespace 15 | - force_cast 16 | - type_name 17 | - file_length 18 | - type_body_length 19 | - cyclomatic_complexity 20 | - identifier_name 21 | - line_length 22 | 23 | excluded: # paths to ignore during linting. overridden by `included`. 24 | - Pods 25 | - Carthage 26 | - fastlane 27 | -------------------------------------------------------------------------------- /.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | 4 | xcuserdata -------------------------------------------------------------------------------- /Example/.swiftlint.yml: -------------------------------------------------------------------------------- 1 | opt_in_rules: # some rules are only opt-in 2 | - closure_end_indentation 3 | - closure_spacing 4 | - explicit_init 5 | - number_separator 6 | - operator_usage_whitespace 7 | - overridden_super_call 8 | - private_outlet 9 | - prohibited_super_call 10 | - redundant_nil_coalescing 11 | 12 | disabled_rules: # rule identifiers to exclude from running 13 | - function_body_length 14 | - trailing_whitespace 15 | - force_cast 16 | - type_name 17 | - file_length 18 | - type_body_length 19 | - cyclomatic_complexity 20 | - identifier_name 21 | - line_length 22 | 23 | excluded: # paths to ignore during linting. overridden by `included`. 24 | - Pods 25 | - Carthage 26 | - fastlane 27 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | // 13 | // Created by Luc Dion on 2017-07-17. 14 | 15 | import UIKit 16 | 17 | @UIApplicationMain 18 | class AppDelegate: UIResponder, UIApplicationDelegate { 19 | var window: UIWindow? 20 | 21 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 22 | 23 | window = UIWindow(frame: UIScreen.main.bounds) 24 | window!.backgroundColor = UIColor.white 25 | window!.rootViewController = UINavigationController(rootViewController: MenuViewController()) 26 | window!.makeKeyAndVisible() 27 | 28 | return true 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "scale" : "2x", 46 | "size" : "20x20" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "scale" : "1x", 51 | "size" : "29x29" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "scale" : "2x", 56 | "size" : "29x29" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "scale" : "1x", 61 | "size" : "40x40" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "scale" : "2x", 66 | "size" : "40x40" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "scale" : "1x", 71 | "size" : "76x76" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "scale" : "2x", 76 | "size" : "76x76" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "scale" : "2x", 81 | "size" : "83.5x83.5" 82 | }, 83 | { 84 | "idiom" : "ios-marketing", 85 | "scale" : "1x", 86 | "size" : "1024x1024" 87 | } 88 | ], 89 | "info" : { 90 | "author" : "xcode", 91 | "version" : 1 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/Base.lproj/LaunchScreen.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 | 28 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "60x60", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-60x60@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "60x60", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-60x60@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "idiom" : "ipad", 47 | "size" : "20x20", 48 | "scale" : "1x" 49 | }, 50 | { 51 | "idiom" : "ipad", 52 | "size" : "20x20", 53 | "scale" : "2x" 54 | }, 55 | { 56 | "idiom" : "ipad", 57 | "size" : "29x29", 58 | "scale" : "1x" 59 | }, 60 | { 61 | "idiom" : "ipad", 62 | "size" : "29x29", 63 | "scale" : "2x" 64 | }, 65 | { 66 | "idiom" : "ipad", 67 | "size" : "40x40", 68 | "scale" : "1x" 69 | }, 70 | { 71 | "idiom" : "ipad", 72 | "size" : "40x40", 73 | "scale" : "2x" 74 | }, 75 | { 76 | "size" : "76x76", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-76x76@1x.png", 79 | "scale" : "1x" 80 | }, 81 | { 82 | "size" : "76x76", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-76x76@2x.png", 85 | "scale" : "2x" 86 | }, 87 | { 88 | "size" : "83.5x83.5", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-83.5x83.5@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "1024x1024", 95 | "idiom" : "ios-marketing", 96 | "filename" : "iTunesArtwork@2x.png", 97 | "scale" : "1x" 98 | } 99 | ], 100 | "info" : { 101 | "version" : 1, 102 | "author" : "xcode" 103 | } 104 | } -------------------------------------------------------------------------------- /Example/FlexLayoutSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/Example/FlexLayoutSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /Example/FlexLayoutSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/Example/FlexLayoutSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /Example/FlexLayoutSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/Example/FlexLayoutSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /Example/FlexLayoutSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/Example/FlexLayoutSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /Example/FlexLayoutSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/Example/FlexLayoutSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /Example/FlexLayoutSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/iTunesArtwork@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/Example/FlexLayoutSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/iTunesArtwork@2x.png -------------------------------------------------------------------------------- /Example/FlexLayoutSample/Supporting Files/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Example/FlexLayoutSample/Supporting Files/Assets.xcassets/filter-box-check.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "filter-box-check@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "filter-box-check@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Example/FlexLayoutSample/Supporting Files/Assets.xcassets/filter-box-check.imageset/filter-box-check@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/Example/FlexLayoutSample/Supporting Files/Assets.xcassets/filter-box-check.imageset/filter-box-check@2x.png -------------------------------------------------------------------------------- /Example/FlexLayoutSample/Supporting Files/Assets.xcassets/filter-box-check.imageset/filter-box-check@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/Example/FlexLayoutSample/Supporting Files/Assets.xcassets/filter-box-check.imageset/filter-box-check@3x.png -------------------------------------------------------------------------------- /Example/FlexLayoutSample/Supporting Files/Assets.xcassets/flexlayout-logo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "flexlayout-logo.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/FlexLayoutSample/Supporting Files/Assets.xcassets/flexlayout-logo.imageset/flexlayout-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/Example/FlexLayoutSample/Supporting Files/Assets.xcassets/flexlayout-logo.imageset/flexlayout-logo.png -------------------------------------------------------------------------------- /Example/FlexLayoutSample/Supporting Files/Assets.xcassets/method.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "method.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/FlexLayoutSample/Supporting Files/Assets.xcassets/method.imageset/method.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/Example/FlexLayoutSample/Supporting Files/Assets.xcassets/method.imageset/method.png -------------------------------------------------------------------------------- /Example/FlexLayoutSample/Supporting Files/Assets.xcassets/raywenderlich/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Example/FlexLayoutSample/Supporting Files/Assets.xcassets/raywenderlich/add.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "add@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "add.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Example/FlexLayoutSample/Supporting Files/Assets.xcassets/raywenderlich/add.imageset/add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/Example/FlexLayoutSample/Supporting Files/Assets.xcassets/raywenderlich/add.imageset/add.png -------------------------------------------------------------------------------- /Example/FlexLayoutSample/Supporting Files/Assets.xcassets/raywenderlich/add.imageset/add@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/Example/FlexLayoutSample/Supporting Files/Assets.xcassets/raywenderlich/add.imageset/add@2x.png -------------------------------------------------------------------------------- /Example/FlexLayoutSample/Supporting Files/Assets.xcassets/raywenderlich/download.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "download@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "download.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Example/FlexLayoutSample/Supporting Files/Assets.xcassets/raywenderlich/download.imageset/download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/Example/FlexLayoutSample/Supporting Files/Assets.xcassets/raywenderlich/download.imageset/download.png -------------------------------------------------------------------------------- /Example/FlexLayoutSample/Supporting Files/Assets.xcassets/raywenderlich/download.imageset/download@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/Example/FlexLayoutSample/Supporting Files/Assets.xcassets/raywenderlich/download.imageset/download@2x.png -------------------------------------------------------------------------------- /Example/FlexLayoutSample/Supporting Files/Assets.xcassets/raywenderlich/share.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "share@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "share.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Example/FlexLayoutSample/Supporting Files/Assets.xcassets/raywenderlich/share.imageset/share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/Example/FlexLayoutSample/Supporting Files/Assets.xcassets/raywenderlich/share.imageset/share.png -------------------------------------------------------------------------------- /Example/FlexLayoutSample/Supporting Files/Assets.xcassets/raywenderlich/share.imageset/share@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/Example/FlexLayoutSample/Supporting Files/Assets.xcassets/raywenderlich/share.imageset/share@2x.png -------------------------------------------------------------------------------- /Example/FlexLayoutSample/Supporting Files/Assets.xcassets/raywenderlich/sherlock.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "sherlock.png", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/FlexLayoutSample/Supporting Files/Assets.xcassets/raywenderlich/sherlock.imageset/sherlock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/Example/FlexLayoutSample/Supporting Files/Assets.xcassets/raywenderlich/sherlock.imageset/sherlock.png -------------------------------------------------------------------------------- /Example/FlexLayoutSample/Supporting Files/Base.lproj/LaunchScreen.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 | 28 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/Supporting Files/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 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIRequiredDeviceCapabilities 26 | 27 | armv7 28 | 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | UIInterfaceOrientationPortraitUpsideDown 35 | 36 | UISupportedInterfaceOrientations~ipad 37 | 38 | UIInterfaceOrientationPortrait 39 | UIInterfaceOrientationPortraitUpsideDown 40 | UIInterfaceOrientationLandscapeLeft 41 | UIInterfaceOrientationLandscapeRight 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/Supporting Files/flexlayout-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/Example/FlexLayoutSample/Supporting Files/flexlayout-logo.png -------------------------------------------------------------------------------- /Example/FlexLayoutSample/UI/Common/BaseViewController.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | 13 | import UIKit 14 | 15 | class BaseViewController: UIViewController { 16 | 17 | init() { 18 | super.init(nibName: nil, bundle: nil) 19 | navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil) 20 | } 21 | 22 | required init?(coder aDecoder: NSCoder) { 23 | fatalError("init(coder:) has not been implemented") 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/UI/Common/BasicView.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | 13 | import UIKit 14 | 15 | class BasicView: UIView { 16 | fileprivate let label = UILabel() 17 | 18 | init(text: String? = nil) { 19 | super.init(frame: .zero) 20 | 21 | backgroundColor = UIColor(red: 0.58, green: 0.78, blue: 0.95, alpha: 1.00) 22 | layer.borderColor = UIColor(red: 0.37, green: 0.67, blue: 0.94, alpha: 1.00).cgColor 23 | layer.borderWidth = 2 24 | 25 | label.text = text 26 | label.font = .systemFont(ofSize: 14) 27 | label.textColor = .white 28 | label.numberOfLines = 0 29 | label.sizeToFit() 30 | addSubview(label) 31 | } 32 | 33 | required init?(coder aDecoder: NSCoder) { 34 | fatalError("init(coder:) has not been implemented") 35 | } 36 | 37 | override func layoutSubviews() { 38 | super.layoutSubviews() 39 | 40 | label.pin.center() 41 | } 42 | 43 | var sizeThatFitsExpectedArea: CGFloat = 40 * 40 44 | 45 | override func sizeThatFits(_ size: CGSize) -> CGSize { 46 | var newSize = CGSize() 47 | if size.width != CGFloat.greatestFiniteMagnitude { 48 | newSize.width = size.width 49 | newSize.height = sizeThatFitsExpectedArea / newSize.width 50 | } else if size.height != CGFloat.greatestFiniteMagnitude { 51 | newSize.height = size.height 52 | newSize.width = sizeThatFitsExpectedArea / newSize.height 53 | } else { 54 | newSize.width = 40 55 | newSize.height = sizeThatFitsExpectedArea / newSize.width 56 | } 57 | 58 | return newSize 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/UI/Common/Stylesheet.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | 13 | import UIKit 14 | 15 | extension UIColor { 16 | class var flexLayoutColor: UIColor { 17 | return UIColor(red: 90.0 / 255.0, green: 171.0 / 255.0, blue: 243.0 / 255.0, alpha: 1.0) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/UI/Common/UIImageView+Download.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | // 13 | // Created by Luc Dion on 2017-10-31. 14 | 15 | import UIKit 16 | 17 | extension UIImageView { 18 | func download(url: URL) { 19 | URLSession.shared.dataTask(with: url) { data, response, error in 20 | guard 21 | let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200, 22 | let mimeType = response?.mimeType, mimeType.hasPrefix("image"), 23 | let data = data, error == nil, 24 | let image = UIImage(data: data) 25 | else { return } 26 | DispatchQueue.main.async { 27 | self.image = image 28 | } 29 | }.resume() 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/UI/Examples/CollectionViewExample/CollectionViewExampleView.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | // 13 | // Created by Luc Dion on 2017-10-31. 14 | 15 | import UIKit 16 | 17 | class CollectionViewExampleView: UIView { 18 | 19 | fileprivate let collectionView: UICollectionView 20 | fileprivate let flowLayout = UICollectionViewFlowLayout() 21 | fileprivate let cellTemplate = HouseCell() 22 | 23 | fileprivate var houses: [House] = [] 24 | 25 | init() { 26 | collectionView = UICollectionView(frame: .zero, collectionViewLayout: flowLayout) 27 | 28 | super.init(frame: .zero) 29 | 30 | flowLayout.minimumLineSpacing = 8 31 | flowLayout.minimumInteritemSpacing = 0 32 | 33 | if #available(iOS 11.0, *) { 34 | flowLayout.sectionInsetReference = .fromSafeArea 35 | } 36 | 37 | collectionView.backgroundColor = .white 38 | collectionView.dataSource = self 39 | collectionView.delegate = self 40 | collectionView.register(HouseCell.self, forCellWithReuseIdentifier: HouseCell.reuseIdentifier) 41 | addSubview(collectionView) 42 | } 43 | 44 | required init?(coder aDecoder: NSCoder) { 45 | fatalError("init(coder:) has not been implemented") 46 | } 47 | 48 | func configure(houses: [House]) { 49 | self.houses = houses 50 | collectionView.reloadData() 51 | } 52 | 53 | func viewOrientationDidChange() { 54 | flowLayout.invalidateLayout() 55 | } 56 | 57 | override func layoutSubviews() { 58 | super.layoutSubviews() 59 | collectionView.pin.vertically().horizontally(pin.safeArea) 60 | } 61 | } 62 | 63 | // MARK: UICollectionViewDelegate, UICollectionViewDataSource 64 | extension CollectionViewExampleView: UICollectionViewDelegateFlowLayout, UICollectionViewDataSource { 65 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 66 | return houses.count 67 | } 68 | 69 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 70 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: HouseCell.reuseIdentifier, for: indexPath) as! HouseCell 71 | cell.configure(house: houses[indexPath.row]) 72 | return cell 73 | } 74 | 75 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { 76 | cellTemplate.configure(house: houses[indexPath.row]) 77 | return cellTemplate.sizeThatFits(CGSize(width: collectionView.bounds.width, height: .greatestFiniteMagnitude)) 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/UI/Examples/CollectionViewExample/CollectionViewExampleViewController.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | // 13 | // Created by Luc Dion on 2017-10-31. 14 | 15 | import UIKit 16 | 17 | struct House { 18 | let name: String 19 | let price: String 20 | let distance: Int 21 | let mainImageURL: URL 22 | } 23 | 24 | class CollectionViewExampleViewController: BaseViewController { 25 | fileprivate var mainView: CollectionViewExampleView { 26 | return self.view as! CollectionViewExampleView 27 | } 28 | 29 | init(pageType: PageType) { 30 | super.init() 31 | 32 | title = pageType.text 33 | } 34 | 35 | required init?(coder aDecoder: NSCoder) { 36 | super.init(coder: aDecoder) 37 | } 38 | 39 | override func loadView() { 40 | view = CollectionViewExampleView() 41 | mainView.configure(houses: [ 42 | House(name: "Castlecrag House", 43 | price: "1,500,000$", 44 | distance: 12, 45 | mainImageURL: URL(string: "https://i.pinimg.com/736x/76/cc/b4/76ccb45bc61b098c7b9b75de62fcf533--house-design-campo-grande.jpg")!), 46 | House(name: "Port Ludlow House", 47 | price: "1,240,000$", 48 | distance: 15, 49 | mainImageURL: URL(string: "https://st.hzcdn.com/simgs/f271957f001074d1_4-3434/modern-exterior.jpg")!), 50 | House(name: "Modern Facade boxes House", 51 | price: "950,000$", 52 | distance: 22, 53 | mainImageURL: URL(string: "https://i.pinimg.com/originals/10/b2/cd/10b2cdbf28cef49281463998dda20796.jpg")!), 54 | House(name: "Contemporary Modern Home", 55 | price: "1,456,000$", 56 | distance: 32, 57 | mainImageURL: URL(string: "https://i.pinimg.com/736x/5e/8f/0b/5e8f0b24f19624754d2aa37968217d5d--architecture-house-design-modern-house-design.jpg")!), 58 | House(name: "Angel House", 59 | price: "932,000$", 60 | distance: 82, 61 | mainImageURL: URL(string: "https://i.pinimg.com/736x/6d/6c/ab/6d6cab9db70117727e3eb2adf0dbc080--small-modern-house-plans-modern-houses.jpg")!) 62 | ]) 63 | } 64 | 65 | override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { 66 | super.viewWillTransition(to: size, with: coordinator) 67 | mainView.viewOrientationDidChange() 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/UI/Examples/CollectionViewExample/HouseCell.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | // 13 | // Created by Luc Dion on 2017-10-31. 14 | 15 | import UIKit 16 | import FlexLayout 17 | 18 | class HouseCell: UICollectionViewCell { 19 | static let reuseIdentifier = "HouseCell" 20 | fileprivate let nameLabel = UILabel() 21 | fileprivate let mainImage = UIImageView() 22 | fileprivate let priceLabel = UILabel() 23 | fileprivate let distanceLabel = UILabel() 24 | 25 | fileprivate let padding: CGFloat = 8 26 | 27 | override init(frame: CGRect) { 28 | super.init(frame: frame) 29 | 30 | let footerBackgroundColor = UIColor.flexLayoutColor.withAlphaComponent(0.2) 31 | backgroundColor = .white 32 | 33 | nameLabel.font = UIFont.systemFont(ofSize: 24) 34 | nameLabel.textColor = .white 35 | 36 | mainImage.backgroundColor = .black 37 | mainImage.contentMode = .scaleAspectFill 38 | mainImage.clipsToBounds = true 39 | 40 | distanceLabel.textAlignment = .right 41 | 42 | contentView.flex.define { (flex) in 43 | flex.addItem().backgroundColor(.flexLayoutColor).paddingHorizontal(padding).define({ (flex) in 44 | flex.addItem(nameLabel).grow(1) 45 | }) 46 | 47 | flex.addItem(mainImage).height(300) 48 | 49 | flex.addItem().direction(.row).justifyContent(.spaceBetween).padding(6, padding, 6, padding).backgroundColor(footerBackgroundColor) 50 | .define({ (flex) in 51 | flex.addItem(priceLabel) 52 | flex.addItem(distanceLabel).grow(1) 53 | }) 54 | } 55 | } 56 | 57 | required init?(coder aDecoder: NSCoder) { 58 | fatalError("init(coder:) has not been implemented") 59 | } 60 | 61 | func configure(house: House) { 62 | nameLabel.text = house.name 63 | nameLabel.flex.markDirty() 64 | 65 | mainImage.download(url: house.mainImageURL) 66 | 67 | priceLabel.text = house.price 68 | priceLabel.flex.markDirty() 69 | 70 | distanceLabel.text = "\(house.distance) KM" 71 | distanceLabel.flex.markDirty() 72 | 73 | setNeedsLayout() 74 | } 75 | 76 | override func layoutSubviews() { 77 | super.layoutSubviews() 78 | layout() 79 | } 80 | 81 | override func sizeThatFits(_ size: CGSize) -> CGSize { 82 | contentView.pin.width(size.width) 83 | layout() 84 | return contentView.frame.size 85 | } 86 | private func layout() { 87 | contentView.flex.layout(mode: .adjustHeight) 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/UI/Examples/Example1/Example1View.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | // 13 | // Created by Luc Dion on 2017-07-17. 14 | 15 | import UIKit 16 | import FlexLayout 17 | import PinLayout 18 | 19 | class Example1View: UIView { 20 | fileprivate let rootFlexContainer = UIView() 21 | 22 | init() { 23 | super.init(frame: .zero) 24 | backgroundColor = .white 25 | 26 | let view1 = BasicView(text: "View 1") 27 | let view2 = BasicView(text: "View 2") 28 | let view3 = BasicView(text: "View 3") 29 | 30 | rootFlexContainer.flex.justifyContent(.center).padding(10).define { (flex) in 31 | flex.addItem(view1).height(40) 32 | flex.addItem(view2).height(40).marginTop(10) 33 | flex.addItem(view3).height(40).marginTop(10) 34 | } 35 | 36 | addSubview(rootFlexContainer) 37 | } 38 | 39 | required init?(coder aDecoder: NSCoder) { 40 | super.init(coder: aDecoder) 41 | } 42 | 43 | override func layoutSubviews() { 44 | super.layoutSubviews() 45 | 46 | // Layout the flexbox container using PinLayout 47 | // NOTE: Could be also layouted by setting directly rootFlexContainer.frame 48 | rootFlexContainer.pin.all(pin.safeArea) 49 | 50 | // Then let the flexbox container layout itself 51 | rootFlexContainer.flex.layout() 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/UI/Examples/Example1/Example1ViewController.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | // 13 | // Created by Luc Dion on 2017-07-17. 14 | 15 | import UIKit 16 | 17 | class Example1ViewController: BaseViewController { 18 | fileprivate var mainView: Example1View { 19 | return self.view as! Example1View 20 | } 21 | 22 | init(pageType: PageType) { 23 | super.init() 24 | title = pageType.text 25 | } 26 | 27 | required init?(coder aDecoder: NSCoder) { 28 | super.init(coder: aDecoder) 29 | } 30 | 31 | override func loadView() { 32 | view = Example1View() 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/UI/Examples/Flexbox/FlexboxViewController.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | 13 | import UIKit 14 | import FlexLayout 15 | 16 | class FlexboxViewController: BaseViewController { 17 | fileprivate var mainView: MyTestView { 18 | return self.view as! MyTestView 19 | } 20 | 21 | init(pageType: PageType) { 22 | super.init() 23 | title = pageType.text 24 | } 25 | 26 | required init?(coder aDecoder: NSCoder) { 27 | super.init(coder: aDecoder) 28 | } 29 | 30 | override func loadView() { 31 | view = MyTestView() 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/UI/Examples/Flexbox/MyTestView.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | 13 | import Foundation 14 | import UIKit 15 | import FlexLayout 16 | import PinLayout 17 | 18 | class MyTestView: BaseView { 19 | 20 | fileprivate let rootFlexContainer = UIView() 21 | 22 | override init() { 23 | super.init() 24 | 25 | backgroundColor = UIColor(red: 0.90, green: 0.97, blue: 0.98, alpha: 1.00) 26 | 27 | initCenteredButtons() 28 | 29 | rootFlexContainer.layer.borderWidth = 2 30 | rootFlexContainer.layer.borderColor = UIColor(red: 0.52, green: 0.53, blue: 0.55, alpha: 1.00).cgColor 31 | addSubview(rootFlexContainer) 32 | } 33 | 34 | required init?(coder aDecoder: NSCoder) { 35 | super.init(coder: aDecoder) 36 | } 37 | 38 | func initCenteredButtons() { 39 | let view1 = BasicView(text: "View 1") 40 | let view2 = BasicView(text: "View 2") 41 | let view3 = BasicView(text: "View 3") 42 | 43 | rootFlexContainer.flex.justifyContent(.center).padding(10).define { (flex) in 44 | flex.addItem(view1).height(40) 45 | flex.addItem(view2).height(40).marginTop(10) 46 | flex.addItem(view3).height(40).marginTop(10) 47 | } 48 | } 49 | 50 | override func layoutSubviews() { 51 | super.layoutSubviews() 52 | 53 | rootFlexContainer.pin.top(topLayoutGuide).width(300).height(400) 54 | // rootFlexContainer.pin.top(topLayoutGuide).bottom().width(100%) 55 | rootFlexContainer.flex.layout() 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/UI/Examples/Flexbox/MyTestViewController.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | 13 | import UIKit 14 | import FlexLayout 15 | 16 | class MyTestViewController: BaseViewController { 17 | fileprivate var mainView: MyTestView { 18 | return self.view as! MyTestView 19 | } 20 | 21 | init(pageType: PageType) { 22 | super.init() 23 | title = pageType.text 24 | } 25 | 26 | required init?(coder aDecoder: NSCoder) { 27 | super.init(coder: aDecoder) 28 | } 29 | 30 | override func loadView() { 31 | view = MyTestView() 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/UI/Examples/Intro/IntroView.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | // 13 | // Created by Luc Dion on 2017-07-17. 14 | 15 | import UIKit 16 | import FlexLayout 17 | import PinLayout 18 | 19 | class IntroView: UIView { 20 | fileprivate let rootFlexContainer = UIView() 21 | 22 | init() { 23 | super.init(frame: .zero) 24 | backgroundColor = .white 25 | 26 | let imageView = UIImageView(image: UIImage(named: "flexlayout-logo")) 27 | 28 | let segmentedControl = UISegmentedControl(items: ["Intro", "FlexLayout", "PinLayout"]) 29 | segmentedControl.selectedSegmentIndex = 0 30 | 31 | let label = UILabel() 32 | label.text = "Flexbox layouting is simple, powerfull and fast.\n\nFlexLayout syntax is concise and chainable." 33 | label.numberOfLines = 0 34 | 35 | let bottomLabel = UILabel() 36 | bottomLabel.text = "FlexLayout/yoga is incredibly fast, its even faster than manual layout." 37 | bottomLabel.numberOfLines = 0 38 | 39 | rootFlexContainer.flex.direction(.column).padding(12).define { (flex) in 40 | flex.addItem().direction(.row).define { (flex) in 41 | flex.addItem(imageView).width(100).aspectRatio(of: imageView) 42 | 43 | flex.addItem().direction(.column).paddingLeft(12).grow(1).shrink(1).define { (flex) in 44 | flex.addItem(segmentedControl).marginBottom(12).grow(1) 45 | flex.addItem(label) 46 | } 47 | } 48 | 49 | flex.addItem().height(1).marginTop(12).backgroundColor(.lightGray) 50 | flex.addItem(bottomLabel).marginTop(12) 51 | } 52 | 53 | addSubview(rootFlexContainer) 54 | } 55 | 56 | required init?(coder aDecoder: NSCoder) { 57 | super.init(coder: aDecoder) 58 | } 59 | 60 | override func layoutSubviews() { 61 | super.layoutSubviews() 62 | 63 | // Layout the flexbox container using PinLayout 64 | // NOTE: Could be also layouted by setting directly rootFlexContainer.frame 65 | rootFlexContainer.pin.top().horizontally().margin(pin.safeArea) 66 | 67 | // Then let the flexbox container layout itself 68 | rootFlexContainer.flex.layout(mode: .adjustHeight) 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/UI/Examples/Intro/IntroViewController.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | // 13 | // Created by Luc Dion on 2017-07-17. 14 | 15 | import UIKit 16 | 17 | class IntroViewController: BaseViewController { 18 | fileprivate var mainView: IntroView { 19 | return self.view as! IntroView 20 | } 21 | 22 | init(pageType: PageType) { 23 | super.init() 24 | title = pageType.text 25 | } 26 | 27 | required init?(coder aDecoder: NSCoder) { 28 | super.init(coder: aDecoder) 29 | } 30 | 31 | override func loadView() { 32 | view = IntroView() 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/UI/Examples/RaywenderlichTutorial/Data/Show.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | // 13 | // Created by Luc Dion on 2017-08-23. 14 | 15 | import Foundation 16 | 17 | struct Series { 18 | let image = "sherlock" 19 | let showPopularity = 5 20 | let showYear = "2010" 21 | let showRating = "TV-14" 22 | let showLength = "3 Series" 23 | let selectedShow = "S3:E3" 24 | let showCast = "Benedict Cumberbatch, Martin Freeman, Una Stubbs" 25 | let showCreators = "Mark Gatiss, Steven Moffat" 26 | 27 | let shows: [Show] 28 | } 29 | 30 | struct Show { 31 | let title: String 32 | let length: String 33 | let detail: String 34 | let image: String 35 | let showPopularity = 5 36 | } 37 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/UI/Examples/RaywenderlichTutorial/Data/Shows.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | title 7 | The Empty Hearse 8 | length 9 | 1h 26m 10 | detail 11 | Two years after Shelock's "death". Watson has moved on. But when Long is threatened by a terrorrist attack, Sherlock decides it's time to return. 12 | image 13 | sherlock 14 | 15 | 16 | title 17 | The Sign of Three 18 | length 19 | 1h 26m 20 | detail 21 | While mortal danger stalks Watson's wedding reception, Sherlock faces his biggest challenge of all: delivering a best man's speech! 22 | image 23 | sherlock 24 | 25 | 26 | title 27 | His Last Vow 28 | length 29 | 1h 29m 30 | detail 31 | A case of stoeln letters leads Sherlock Holmes to engage in a long conflict with the powerful Chales Augustus Magnussen, the Napolean of blackmail. 32 | image 33 | sherlock 34 | 35 | 36 | title 37 | The Abominable Bride 38 | length 39 | 1h 29m 40 | detail 41 | In this special set in 1895, Holmes and Watson investigate a vengeful apparition in a wedding dress, reportedly the ghost of a suicide victim. 42 | image 43 | sherlock 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/UI/Examples/RaywenderlichTutorial/RaywenderlichTutorialViewController.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | // 13 | // Created by Luc Dion on 2017-08-23. 14 | 15 | import UIKit 16 | 17 | class RayWenderlichTutorialViewController: BaseViewController { 18 | fileprivate var mainView: RayWenderlichTutorialView { 19 | return self.view as! RayWenderlichTutorialView 20 | } 21 | 22 | init(pageType: PageType) { 23 | super.init() 24 | title = pageType.text 25 | } 26 | 27 | required init?(coder aDecoder: NSCoder) { 28 | super.init(coder: aDecoder) 29 | } 30 | 31 | override func loadView() { 32 | let shows = loadShows() 33 | let series = Series(shows: shows) 34 | view = RayWenderlichTutorialView(series: series) 35 | } 36 | 37 | fileprivate func loadShows() -> [Show] { 38 | guard let path = Bundle.main.path(forResource: "Shows", ofType: "plist"), 39 | let dictArray = NSArray(contentsOfFile: path) as? [[String: AnyObject]] else { 40 | return [] 41 | } 42 | 43 | var shows: [Show] = [] 44 | 45 | dictArray.forEach { (dict) in 46 | guard 47 | let title = dict["title"] as? String, 48 | let length = dict["length"] as? String, 49 | let detail = dict["detail"] as? String, 50 | let image = dict["image"] as? String 51 | else { 52 | fatalError("Error parsing dict \(dict)") 53 | } 54 | 55 | let show = Show(title: title, length: length, detail: detail, image: image) 56 | shows.append(show) 57 | } 58 | 59 | return shows 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/UI/Examples/RaywenderlichTutorial/Subviews/ExpandedTableView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // File.swift 3 | // FlexLayoutSample 4 | // 5 | // Created by DION, Luc (MTL) on 2017-08-23. 6 | // Copyright © 2017 Mirego. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | // TableView that the method sizeThatFits() returns the size of all its cells. 12 | // Support only cells with fixed height 13 | class ExpandedTableView: UITableView { 14 | override func sizeThatFits(_ size: CGSize) -> CGSize { 15 | let nbOfCells = numberOfRows(inSection: 0) 16 | let cellsHeight = delegate?.tableView?(self, heightForRowAt: IndexPath(row: 0, section: 0)) ?? 0 17 | return CGSize(width: size.width, height: CGFloat(nbOfCells) * cellsHeight) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/UI/Examples/RaywenderlichTutorial/Subviews/ShowTableViewCell.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | // 13 | // Created by Luc Dion on 2017-08-23. 14 | import UIKit 15 | 16 | class ShowTableViewCell: UITableViewCell { 17 | static var reuseIdentifier = "ShowTableViewCell" 18 | 19 | override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { 20 | super.init(style: .subtitle, reuseIdentifier: reuseIdentifier) 21 | 22 | self.textLabel?.textColor = .white 23 | self.textLabel?.font = .systemFont(ofSize: 14.0) 24 | self.textLabel?.numberOfLines = 2 25 | self.textLabel?.adjustsFontSizeToFitWidth = true 26 | self.textLabel?.minimumScaleFactor = 0.8 27 | self.detailTextLabel?.textColor = .lightGray 28 | 29 | let accessoryView = UIImageView(frame: CGRect(x: 0, y: 0, width: 25, height: 25)) 30 | accessoryView.image = UIImage(named: "download") 31 | self.accessoryView = accessoryView 32 | 33 | self.backgroundColor = .clear 34 | self.separatorInset = .zero 35 | } 36 | 37 | required init?(coder aDecoder: NSCoder) { 38 | super.init(coder: aDecoder) 39 | } 40 | 41 | func configure(show: Show) { 42 | self.textLabel?.text = show.title 43 | self.detailTextLabel?.text = show.length 44 | self.imageView?.image = UIImage(named: show.image) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/UI/Examples/TableViewExample/Subviews/MethodCell.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | // 13 | // Created by Luc Dion on 2017-07-17. 14 | 15 | import UIKit 16 | import PinLayout 17 | import FlexLayout 18 | 19 | class MethodCell: UITableViewCell { 20 | static let reuseIdentifier = "MethodCell" 21 | fileprivate let padding: CGFloat = 10 22 | 23 | fileprivate let nameLabel = UILabel() 24 | fileprivate let descriptionLabel = UILabel() 25 | 26 | override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { 27 | super.init(style: style, reuseIdentifier: reuseIdentifier) 28 | 29 | selectionStyle = .none 30 | separatorInset = .zero 31 | 32 | let iconImageView = UIImageView(image: UIImage(named: "method")) 33 | 34 | nameLabel.font = UIFont.boldSystemFont(ofSize: 14) 35 | nameLabel.lineBreakMode = .byTruncatingTail 36 | 37 | descriptionLabel.font = UIFont.systemFont(ofSize: 12) 38 | descriptionLabel.numberOfLines = 0 39 | 40 | // Use contentView as the root flex container 41 | contentView.flex.padding(12).define { (flex) in 42 | flex.addItem().direction(.row).define { (flex) in 43 | flex.addItem(iconImageView).size(30) 44 | flex.addItem(nameLabel).marginLeft(padding).grow(1) 45 | } 46 | 47 | flex.addItem(descriptionLabel).marginTop(padding) 48 | } 49 | } 50 | 51 | required init?(coder aDecoder: NSCoder) { 52 | fatalError("init(coder:) has not been implemented") 53 | } 54 | 55 | func configure(method: Method) { 56 | // WARNING: After a control size may have been modified after a change, you must call flex.markDirty() 57 | // to force flex to relayout the view. This is due to the high level of optimization of FlexLayout. 58 | nameLabel.text = method.name 59 | nameLabel.flex.markDirty() 60 | 61 | descriptionLabel.text = method.description 62 | descriptionLabel.flex.markDirty() 63 | } 64 | 65 | override func layoutSubviews() { 66 | super.layoutSubviews() 67 | layout() 68 | } 69 | 70 | fileprivate func layout() { 71 | contentView.flex.layout(mode: .adjustHeight) 72 | } 73 | 74 | override func sizeThatFits(_ size: CGSize) -> CGSize { 75 | // 1) Set the contentView's width to the specified size parameter 76 | contentView.pin.width(size.width) 77 | 78 | // 2) Layout contentView flex container 79 | layout() 80 | 81 | // Return the flex container new size 82 | return contentView.frame.size 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/UI/Examples/TableViewExample/Subviews/MethodGroupHeader.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | // 13 | // Created by Luc Dion on 2017-07-17. 14 | 15 | import UIKit 16 | 17 | class MethodGroupHeader: UITableViewHeaderFooterView { 18 | static let reuseIdentifier = "MethodGroupHeader" 19 | static let height: CGFloat = 50 20 | 21 | fileprivate let titleLabel = UILabel() 22 | 23 | override init(reuseIdentifier: String?) { 24 | super.init(reuseIdentifier: reuseIdentifier) 25 | 26 | titleLabel.font = UIFont.systemFont(ofSize: 20) 27 | titleLabel.sizeToFit() 28 | addSubview(titleLabel) 29 | } 30 | 31 | required init?(coder aDecoder: NSCoder) { 32 | fatalError("init(coder:) has not been implemented") 33 | } 34 | 35 | func configure(title: String) { 36 | titleLabel.text = title 37 | titleLabel.sizeToFit() 38 | } 39 | 40 | override func layoutSubviews() { 41 | super.layoutSubviews() 42 | 43 | // Center the label vertically. Note that we don't need to specify the size, it has already be adjusted in init(). 44 | titleLabel.pin.horizontally(pin.safeArea.left + 12).vCenter() 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/UI/Examples/TableViewExample/TableViewExampleView.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | // 13 | // Created by Luc Dion on 2017-07-17. 14 | 15 | import UIKit 16 | 17 | class TableViewExampleView: UIView { 18 | 19 | fileprivate let tableView = UITableView() 20 | fileprivate let methodCellTemplate = MethodCell() 21 | 22 | fileprivate var methods: [Method] = [] 23 | 24 | init() { 25 | super.init(frame: .zero) 26 | 27 | tableView.dataSource = self 28 | tableView.delegate = self 29 | tableView.tableFooterView = UIView() 30 | tableView.estimatedRowHeight = 10 31 | tableView.register(MethodCell.self, forCellReuseIdentifier: MethodCell.reuseIdentifier) 32 | tableView.register(MethodGroupHeader.self, forHeaderFooterViewReuseIdentifier: MethodGroupHeader.reuseIdentifier) 33 | addSubview(tableView) 34 | } 35 | 36 | required init?(coder aDecoder: NSCoder) { 37 | super.init(coder: aDecoder) 38 | } 39 | 40 | func configure(methods: [Method]) { 41 | self.methods = methods 42 | tableView.reloadData() 43 | } 44 | 45 | override func layoutSubviews() { 46 | super.layoutSubviews() 47 | tableView.pin.all() 48 | } 49 | } 50 | 51 | // MARK: UITableViewDataSource, UITableViewDelegate 52 | extension TableViewExampleView: UITableViewDataSource, UITableViewDelegate { 53 | func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { 54 | return MethodGroupHeader.height 55 | } 56 | 57 | func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { 58 | let header = tableView.dequeueReusableHeaderFooterView(withIdentifier: MethodGroupHeader.reuseIdentifier) as! MethodGroupHeader 59 | header.configure(title: "Flex container methods") 60 | return header 61 | } 62 | 63 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 64 | return methods.count 65 | } 66 | 67 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 68 | let cell = tableView.dequeueReusableCell(withIdentifier: MethodCell.reuseIdentifier, for: indexPath) as! MethodCell 69 | cell.configure(method: methods[indexPath.row]) 70 | 71 | return cell 72 | } 73 | 74 | func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 75 | // The UITableView will call the cell's sizeThatFit() method to compute the height. 76 | // WANRING: You must also set the UITableView.estimatedRowHeight for this to work. 77 | return UITableView.automaticDimension 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/UI/Examples/TableViewExample/TableViewExampleViewController.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | // 13 | // Created by Luc Dion on 2017-07-17. 14 | 15 | import UIKit 16 | 17 | struct Method { 18 | let name: String 19 | let description: String 20 | } 21 | 22 | class TableViewExampleViewController: BaseViewController { 23 | fileprivate var mainView: TableViewExampleView { 24 | return self.view as! TableViewExampleView 25 | } 26 | 27 | init(pageType: PageType) { 28 | super.init() 29 | 30 | title = pageType.text 31 | } 32 | 33 | required init?(coder aDecoder: NSCoder) { 34 | super.init(coder: aDecoder) 35 | } 36 | 37 | override func loadView() { 38 | view = TableViewExampleView() 39 | mainView.configure(methods: [ 40 | Method(name: "direction(_: Direction)", description: "The direction property establishes the main-axis, thus defining the direction flex items are placed in the flex container container container."), 41 | 42 | Method(name: "wrap(_: Wrap)", description: "The `wrap` property controls whether the flex container is single-lined or multi-lined, and the direction of the cross-axis, which determines the direction in which the new lines are stacked in.\n\nBy default, the flex container fits all flex items into one line. Using this property we can change that. We can tell the container to lay out its items in single or multiple lines, and the direction the new lines are stacked in."), 43 | 44 | Method(name: "justifyContent(_: JustifyContent)", description: "The `justifyContent` property defines the alignment along the main-axis of the current line of the flex container. It helps distribute extra free space leftover when either all the flex items on a line have reached their maximum size. "), 45 | 46 | Method(name: "alignItems(_: AlignItems)", description: "The `alignItems` property defines how flex items are laid out along the cross axis on the current line. Similar to `justifyContent` but for the cross-axis (perpendicular to the main-axis)."), 47 | 48 | Method(name: "alignSelf(_: AlignSelf)", description: "The `alignSelf` property controls how a child aligns in the cross direction, overriding the `alignItems` of the parent. For example, if children are flowing vertically, `alignSelf` will control how the flex item will align horizontally.\n\n The \"auto\" value means use the flex container `alignItems` property. See `alignItems` for documentation of the other values."), 49 | 50 | Method(name: "alignContent(_: AlignContent)", description: "The align-content property aligns a flex container’s lines within the flex container when there is extra space in the cross-axis, similar to how justifyContent aligns individual items within the main-axis.\n\nNote, alignContent has no effect when the flexbox has only a single line."), 51 | 52 | Method(name: "layoutDirection(_: LayoutDirection)", description: "The layoutDirection property controls the flex container layout direction.\n\nValues:\n-`.inherit`\n Direction defaults to Inherit on all nodes except the root which defaults to LTR. It is up to you to detect the user’s preferred direction (most platforms have a standard way of doing this) and setting this direction on the root of your layout tree.\n-.ltr: Layout views from left to right. (Default)\n-.rtl: Layout views from right to left.") 53 | 54 | ]) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/UI/Examples/UnitTests/UnitTestsViewController.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | 13 | import UIKit 14 | 15 | class UnitTestsViewController: BaseViewController { 16 | fileprivate var mainView: UnitTestsView { 17 | return self.view as! UnitTestsView 18 | } 19 | 20 | init(pageType: PageType) { 21 | super.init() 22 | title = pageType.text 23 | } 24 | 25 | required init?(coder aDecoder: NSCoder) { 26 | super.init(coder: aDecoder) 27 | } 28 | 29 | override func loadView() { 30 | view = UnitTestsView() 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/UI/Examples/YogaExampleA/YogaExampleAView.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | // 13 | // Created by Luc Dion on 2017-07-17. 14 | 15 | import UIKit 16 | import FlexLayout 17 | import PinLayout 18 | 19 | class YogaExampleAView: UIView { 20 | fileprivate let rootFlexContainer = UIView() 21 | 22 | init() { 23 | super.init(frame: .zero) 24 | backgroundColor = .white 25 | 26 | // Yoga's C Example 27 | rootFlexContainer.flex.direction(.row).padding(20).define { (flex) in 28 | flex.addItem().width(80).marginEnd(20).backgroundColor(.flexLayoutColor) 29 | flex.addItem().height(25).alignSelf(.center).grow(1).backgroundColor(.black) 30 | } 31 | addSubview(rootFlexContainer) 32 | } 33 | 34 | required init?(coder aDecoder: NSCoder) { 35 | super.init(coder: aDecoder) 36 | } 37 | 38 | override func layoutSubviews() { 39 | super.layoutSubviews() 40 | 41 | // Layout the flexbox container using PinLayout 42 | // NOTE: Could be also layouted by setting directly rootFlexContainer.frame 43 | rootFlexContainer.pin.top(pin.safeArea).horizontally(pin.safeArea).height(120) 44 | 45 | // Then let the flexbox container layout itself 46 | rootFlexContainer.flex.layout() 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/UI/Examples/YogaExampleA/YogaExampleAViewController.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | // 13 | // Created by Luc Dion on 2017-07-17. 14 | 15 | import UIKit 16 | 17 | class YogaExampleAViewController: BaseViewController { 18 | fileprivate var mainView: YogaExampleAView { 19 | return self.view as! YogaExampleAView 20 | } 21 | 22 | init(pageType: PageType) { 23 | super.init() 24 | title = pageType.text 25 | } 26 | 27 | required init?(coder aDecoder: NSCoder) { 28 | super.init(coder: aDecoder) 29 | } 30 | 31 | override func loadView() { 32 | view = YogaExampleAView() 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/UI/Examples/YogaExampleB/YogaExampleBView.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | // 13 | // Created by Luc Dion on 2017-07-17. 14 | 15 | import UIKit 16 | import FlexLayout 17 | import PinLayout 18 | 19 | class YogaExampleBView: UIView { 20 | fileprivate let rootFlexContainer = UIView() 21 | 22 | init() { 23 | super.init(frame: .zero) 24 | backgroundColor = .white 25 | 26 | let imageView = UIView() 27 | imageView.backgroundColor = .flexLayoutColor 28 | 29 | let label = UIView() 30 | label.backgroundColor = .black 31 | 32 | // Yoga's Objective-C Example 33 | rootFlexContainer.flex.alignItems(.center).justifyContent(.center).padding(20).define { (flex) in 34 | flex.addItem(imageView).size(150).aspectRatio(1).marginBottom(20) 35 | flex.addItem(label).width(100).height(25) 36 | } 37 | addSubview(rootFlexContainer) 38 | } 39 | 40 | required init?(coder aDecoder: NSCoder) { 41 | super.init(coder: aDecoder) 42 | } 43 | 44 | override func layoutSubviews() { 45 | super.layoutSubviews() 46 | 47 | // Layout the flexbox container using PinLayout 48 | // NOTE: Could be also layouted by setting directly rootFlexContainer.frame 49 | rootFlexContainer.pin.top(pin.safeArea).horizontally(pin.safeArea).height(200) 50 | 51 | // Then let the flexbox container layout itself 52 | rootFlexContainer.flex.layout() 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/UI/Examples/YogaExampleB/YogaExampleBViewController.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | // 13 | // Created by Luc Dion on 2017-07-17. 14 | 15 | import UIKit 16 | 17 | class YogaExampleBViewController: BaseViewController { 18 | fileprivate var mainView: YogaExampleBView { 19 | return self.view as! YogaExampleBView 20 | } 21 | 22 | init(pageType: PageType) { 23 | super.init() 24 | title = pageType.text 25 | } 26 | 27 | required init?(coder aDecoder: NSCoder) { 28 | super.init(coder: aDecoder) 29 | } 30 | 31 | override func loadView() { 32 | view = YogaExampleBView() 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/UI/Examples/YogaExampleC/YogaExampleCView.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | // 13 | // Created by Luc Dion on 2017-07-17. 14 | 15 | import UIKit 16 | import FlexLayout 17 | import PinLayout 18 | 19 | class YogaExampleCView: UIView { 20 | fileprivate let rootFlexContainer = UIView() 21 | 22 | init() { 23 | super.init(frame: .zero) 24 | backgroundColor = .white 25 | 26 | let label = UIView() 27 | label.backgroundColor = .black 28 | 29 | let imageView = UIView() 30 | imageView.backgroundColor = .flexLayoutColor 31 | 32 | // Yoga's Java Example 33 | rootFlexContainer.flex.alignItems(.center).justifyContent(.center).padding(20).define { (flex) in 34 | flex.addItem(label).width(200).height(25) 35 | flex.addItem(imageView).position(.absolute).top(20).end(20).size(50) 36 | } 37 | addSubview(rootFlexContainer) 38 | } 39 | 40 | required init?(coder aDecoder: NSCoder) { 41 | super.init(coder: aDecoder) 42 | } 43 | 44 | override func layoutSubviews() { 45 | super.layoutSubviews() 46 | 47 | // Layout the flexbox container using PinLayout 48 | // NOTE: Could be also layouted by setting directly rootFlexContainer.frame 49 | rootFlexContainer.pin.top(pin.safeArea).horizontally(pin.safeArea).height(300) 50 | 51 | // Then let the flexbox container layout itself 52 | rootFlexContainer.flex.layout() 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/UI/Examples/YogaExampleC/YogaExampleCViewController.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | // 13 | // Created by Luc Dion on 2017-07-17. 14 | 15 | import UIKit 16 | 17 | class YogaExampleCViewController: BaseViewController { 18 | fileprivate var mainView: YogaExampleCView { 19 | return self.view as! YogaExampleCView 20 | } 21 | 22 | init(pageType: PageType) { 23 | super.init() 24 | title = pageType.text 25 | } 26 | 27 | required init?(coder aDecoder: NSCoder) { 28 | super.init(coder: aDecoder) 29 | } 30 | 31 | override func loadView() { 32 | view = YogaExampleCView() 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/UI/Examples/YogaExampleD/YogaExampleDView.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | // 13 | // Created by Luc Dion on 2017-07-17. 14 | 15 | import UIKit 16 | import FlexLayout 17 | import PinLayout 18 | 19 | class YogaExampleDView: UIView { 20 | fileprivate let rootFlexContainer = UIView() 21 | 22 | init() { 23 | super.init(frame: .zero) 24 | backgroundColor = .white 25 | 26 | let imageView = UIView() 27 | imageView.backgroundColor = .flexLayoutColor 28 | 29 | let label = UIView() 30 | label.backgroundColor = .black 31 | 32 | // Yoga's C# example 33 | rootFlexContainer.flex.justifyContent(.start).alignItems(.start).define { (flex) in 34 | flex.addItem(imageView).alignSelf(.stretch).grow(1) 35 | flex.addItem(label).width(300).height(25).margin(20) 36 | } 37 | addSubview(rootFlexContainer) 38 | } 39 | 40 | required init?(coder aDecoder: NSCoder) { 41 | super.init(coder: aDecoder) 42 | } 43 | 44 | override func layoutSubviews() { 45 | super.layoutSubviews() 46 | 47 | // Layout the flexbox container using PinLayout 48 | // NOTE: Could be also layouted by setting directly rootFlexContainer.frame 49 | rootFlexContainer.pin.top(pin.safeArea).horizontally(pin.safeArea).height(300) 50 | 51 | // Then let the flexbox container layout itself 52 | rootFlexContainer.flex.layout() 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/UI/Examples/YogaExampleD/YogaExampleDViewController.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | // 13 | // Created by Luc Dion on 2017-07-17. 14 | 15 | import UIKit 16 | 17 | class YogaExampleDViewController: BaseViewController { 18 | fileprivate var mainView: YogaExampleDView { 19 | return self.view as! YogaExampleDView 20 | } 21 | 22 | init(pageType: PageType) { 23 | super.init() 24 | title = pageType.text 25 | } 26 | 27 | required init?(coder aDecoder: NSCoder) { 28 | super.init(coder: aDecoder) 29 | } 30 | 31 | override func loadView() { 32 | view = YogaExampleDView() 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/UI/Examples/YogaExampleE/YogaExampleEView.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | // 13 | // Created by Luc Dion on 2017-07-17. 14 | 15 | import UIKit 16 | import FlexLayout 17 | import PinLayout 18 | 19 | class YogaExampleEView: UIView { 20 | fileprivate let rootFlexContainer = UIView() 21 | 22 | init() { 23 | super.init(frame: .zero) 24 | backgroundColor = .white 25 | 26 | let imageView = UIView() 27 | imageView.backgroundColor = .flexLayoutColor 28 | 29 | // Yoga's Android example 30 | rootFlexContainer.flex.define { (flex) in 31 | flex.addItem(imageView).grow(1) 32 | 33 | flex.addItem().direction(.row).padding(20).alignItems(.center).define { (flex) in 34 | flex.addItem().size(50).backgroundColor(.flexLayoutColor) 35 | flex.addItem().height(25).marginStart(20).grow(1).backgroundColor(.black) 36 | } 37 | } 38 | addSubview(rootFlexContainer) 39 | } 40 | 41 | required init?(coder aDecoder: NSCoder) { 42 | super.init(coder: aDecoder) 43 | } 44 | 45 | override func layoutSubviews() { 46 | super.layoutSubviews() 47 | 48 | // Layout the flexbox container using PinLayout 49 | // NOTE: Could be also layouted by setting directly rootFlexContainer.frame 50 | rootFlexContainer.pin.top(pin.safeArea).horizontally(pin.safeArea).height(300) 51 | 52 | // Then let the flexbox container layout itself 53 | rootFlexContainer.flex.layout() 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/UI/Examples/YogaExampleE/YogaExampleEViewController.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | // 13 | // Created by Luc Dion on 2017-07-17. 14 | 15 | import UIKit 16 | 17 | class YogaExampleEViewController: BaseViewController { 18 | fileprivate var mainView: YogaExampleEView { 19 | return self.view as! YogaExampleEView 20 | } 21 | 22 | init(pageType: PageType) { 23 | super.init() 24 | title = pageType.text 25 | } 26 | 27 | required init?(coder aDecoder: NSCoder) { 28 | super.init(coder: aDecoder) 29 | } 30 | 31 | override func loadView() { 32 | view = YogaExampleEView() 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/UI/Examples/YogaExampleF/YogaExampleFViewController.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | // 13 | // Created by Michael Ong on 2020-05-27. 14 | 15 | import UIKit 16 | 17 | class YogaExampleFViewController: BaseViewController { 18 | fileprivate var mainView: YogaExampleFView { 19 | return self.view as! YogaExampleFView 20 | } 21 | 22 | init(pageType: PageType) { 23 | super.init() 24 | title = pageType.text 25 | } 26 | 27 | required init?(coder aDecoder: NSCoder) { 28 | super.init(coder: aDecoder) 29 | } 30 | 31 | override func loadView() { 32 | view = YogaExampleFView() 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/UI/Menu/MenuView.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | 13 | import UIKit 14 | 15 | protocol MenuViewDelegate: AnyObject { 16 | func didSelect(pageType: PageType) 17 | } 18 | 19 | class MenuView: UIView { 20 | weak var delegate: MenuViewDelegate? 21 | 22 | fileprivate let tableView = UITableView() 23 | fileprivate let cellIdentifier = "MenuViewCell" 24 | 25 | init() { 26 | super.init(frame: .zero) 27 | 28 | backgroundColor = .red 29 | 30 | tableView.dataSource = self 31 | tableView.delegate = self 32 | tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellIdentifier) 33 | tableView.tableFooterView = UIView() 34 | addSubview(tableView) 35 | } 36 | 37 | required init(coder aDecoder: NSCoder) { 38 | fatalError("init(coder:) has not been implemented") 39 | } 40 | 41 | override func layoutSubviews() { 42 | super.layoutSubviews() 43 | 44 | tableView.pin.size(frame.size) 45 | } 46 | } 47 | 48 | // MARK: UITableViewDataSource 49 | extension MenuView: UITableViewDataSource { 50 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 51 | return PageType.count.rawValue 52 | } 53 | 54 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 55 | let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) 56 | cell.textLabel?.text = PageType(rawValue: indexPath.row)?.text ?? "FlexLayout Example" 57 | cell.textLabel?.font = .systemFont(ofSize: 12) 58 | return cell 59 | } 60 | } 61 | 62 | // MARK: UITableViewDelegate 63 | extension MenuView: UITableViewDelegate { 64 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 65 | if let pageType = PageType(rawValue: indexPath.row) { 66 | delegate?.didSelect(pageType: pageType) 67 | } 68 | tableView.deselectRow(at: indexPath, animated: true) 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Example/FlexLayoutSample/UI/Menu/MenuViewController.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | 13 | import UIKit 14 | 15 | enum PageType: Int { 16 | case intro 17 | case rayWenderlich 18 | case tableview 19 | case collectionView 20 | case exampleColumn 21 | case yogaExampleA 22 | case yogaExampleB 23 | case yogaExampleC 24 | case yogaExampleD 25 | case yogaExampleE 26 | case yogaExampleF 27 | // case flex 28 | 29 | case count 30 | 31 | var text: String { 32 | switch self { 33 | case .intro: return "Intro Example" 34 | case .rayWenderlich: return "Raywenderlich Tutorial" 35 | case .tableview: return "UITableView with variable cell's height" 36 | case .collectionView: return "UICollectionView with variable cell's height" 37 | case .exampleColumn: return "Example 1 - Column" 38 | case .yogaExampleA: return "Yoga C Example" 39 | case .yogaExampleB: return "Yoga Obj-C Example" 40 | case .yogaExampleC: return "Yoga Java Example" 41 | case .yogaExampleD: return "Yoga C# Example" 42 | case .yogaExampleE: return "Yoga Android Example" 43 | case .yogaExampleF: return "Yoga Baseline Example" 44 | // case .flex: return "Flexbox" 45 | case .count: return "" 46 | } 47 | } 48 | 49 | var viewController: UIViewController { 50 | switch self { 51 | case .intro: return IntroViewController(pageType: self) 52 | case .rayWenderlich: return RayWenderlichTutorialViewController(pageType: self) 53 | case .tableview: return TableViewExampleViewController(pageType: self) 54 | case .collectionView: return CollectionViewExampleViewController(pageType: self) 55 | case .exampleColumn: return Example1ViewController(pageType: self) 56 | case .yogaExampleA: return YogaExampleAViewController(pageType: self) 57 | case .yogaExampleB: return YogaExampleBViewController(pageType: self) 58 | case .yogaExampleC: return YogaExampleCViewController(pageType: self) 59 | case .yogaExampleD: return YogaExampleDViewController(pageType: self) 60 | case .yogaExampleE: return YogaExampleEViewController(pageType: self) 61 | case .yogaExampleF: return YogaExampleFViewController(pageType: self) 62 | // case .flex: return FlexboxViewController(pageType: self) 63 | case .count: return UIViewController() 64 | } 65 | } 66 | } 67 | 68 | class MenuViewController: BaseViewController { 69 | fileprivate var mainView: MenuView { 70 | return self.view as! MenuView 71 | } 72 | 73 | override init() { 74 | super.init() 75 | title = "FlexLayout Examples" 76 | } 77 | 78 | required init(coder aDecoder: NSCoder) { 79 | fatalError("init(coder:) has not been implemented") 80 | } 81 | 82 | override func loadView() { 83 | view = MenuView() 84 | mainView.delegate = self 85 | } 86 | 87 | // override func viewDidAppear(_ animated: Bool) { 88 | // super.viewDidAppear(true) 89 | // didSelect(pageType: .collectionView) 90 | // } 91 | } 92 | 93 | // MARK: MenuViewDelegate 94 | extension MenuViewController: MenuViewDelegate { 95 | func didSelect(pageType: PageType) { 96 | navigationController?.pushViewController(pageType.viewController, animated: true) 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Example/SPM/FlexLayoutSample-SPM.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/SPM/FlexLayoutSample-SPM.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/SPM/FlexLayoutSample-SPM.xcodeproj/xcshareddata/xcschemes/FlexLayoutSample-SPM.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 42 | 44 | 50 | 51 | 52 | 53 | 59 | 61 | 67 | 68 | 69 | 70 | 72 | 73 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /Example/cocoapods/FlexLayoutSample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/cocoapods/FlexLayoutSample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/cocoapods/FlexLayoutSample.xcodeproj/xcshareddata/xcschemes/FlexLayoutSample.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 42 | 48 | 49 | 50 | 51 | 52 | 62 | 64 | 70 | 71 | 72 | 73 | 79 | 81 | 87 | 88 | 89 | 90 | 92 | 93 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /FlexLayout.podspec: -------------------------------------------------------------------------------- 1 | 2 | Pod::Spec.new do |spec| 3 | spec.name = "FlexLayout" 4 | spec.version = "2.2.2" 5 | spec.summary = "FlexLayout" 6 | spec.homepage = "https://github.com/lucdion/FlexLayout.git" 7 | spec.license = "MIT license" 8 | spec.author = { "Luc Dion" => "luc_dion@yahoo.com" } 9 | 10 | spec.platform = :ios, "13.4" 11 | spec.source = { :git => "https://github.com/lucdion/FlexLayout.git", :tag => "#{spec.version}" } 12 | spec.source_files = "Sources/**/*.{swift,h,m,mm,cpp,c}" 13 | spec.public_header_files = "Sources/YogaKit/include/YogaKit/*.h" 14 | spec.libraries = 'c++' 15 | 16 | 17 | # Should match yoga_defs.bzl + BUCK configuration 18 | spec.compiler_flags = [ 19 | '-fno-omit-frame-pointer', 20 | '-fexceptions', 21 | '-Wall', 22 | '-Werror', 23 | '-std=c++20', 24 | '-fPIC' 25 | ] 26 | 27 | spec.dependency 'Yoga', '3.2.1' 28 | end 29 | -------------------------------------------------------------------------------- /FlexLayout.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /FlexLayout.xcodeproj/project.xcworkspace/xcshareddata/FlexLayout.xcscmblueprint: -------------------------------------------------------------------------------- 1 | { 2 | "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "2FE8061FBEA35DD9041E45BF0834BE76C96388C3", 3 | "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : { 4 | 5 | }, 6 | "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : { 7 | "2FE8061FBEA35DD9041E45BF0834BE76C96388C3" : 9223372036854775807, 8 | "EF4E0D78BD66D72DA5A8D5BC350B60E01C5A9EF4" : 9223372036854775807 9 | }, 10 | "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "9A2BB70E-29E4-42DF-9840-D239C60C6F4B", 11 | "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : { 12 | "2FE8061FBEA35DD9041E45BF0834BE76C96388C3" : "FlexLayout\/", 13 | "EF4E0D78BD66D72DA5A8D5BC350B60E01C5A9EF4" : "FlexLayout\/Carthage\/Checkouts\/yoga\/" 14 | }, 15 | "DVTSourceControlWorkspaceBlueprintNameKey" : "FlexLayout", 16 | "DVTSourceControlWorkspaceBlueprintVersion" : 204, 17 | "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "FlexLayout.xcodeproj", 18 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [ 19 | { 20 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "github.com:lucmirego\/FlexLayout.git", 21 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", 22 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "2FE8061FBEA35DD9041E45BF0834BE76C96388C3" 23 | }, 24 | { 25 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/facebook\/yoga.git", 26 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", 27 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "EF4E0D78BD66D72DA5A8D5BC350B60E01C5A9EF4" 28 | } 29 | ] 30 | } -------------------------------------------------------------------------------- /FlexLayout.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /FlexLayout.xcodeproj/xcshareddata/xcschemes/FlexLayoutInner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 42 | 48 | 49 | 50 | 51 | 52 | 62 | 63 | 69 | 70 | 71 | 72 | 78 | 79 | 85 | 86 | 87 | 88 | 90 | 91 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /FlexLayout.xcodeproj/xcuserdata/dionlu.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | FlexLayout.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 24DA37591EF843C500D1AB2F 16 | 17 | primary 18 | 19 | 20 | 24DA37621EF843C500D1AB2F 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /FlexLayout.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /FlexLayout.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | gem 'cocoapods' 3 | gem 'fastlane' 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Luc Dion 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 | -------------------------------------------------------------------------------- /Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "object": { 3 | "pins": [ 4 | { 5 | "package": "yoga", 6 | "repositoryURL": "https://github.com/facebook/yoga.git", 7 | "state": { 8 | "branch": null, 9 | "revision": "042f5013152eb81c1552dec945b88f7b95ca350f", 10 | "version": "3.2.1" 11 | } 12 | } 13 | ] 14 | }, 15 | "version": 1 16 | } 17 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.5 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let package = Package( 7 | name: "FlexLayout", 8 | platforms: [ 9 | .iOS(.v13), 10 | ], 11 | products: [ 12 | .library(name: "FlexLayout", targets: ["FlexLayout"]), 13 | ], 14 | dependencies: [ 15 | .package(url: "https://github.com/facebook/yoga.git", .upToNextMinor(from: "3.2.1")), 16 | ], 17 | targets: [ 18 | .target( 19 | name: "FlexLayout", 20 | dependencies: ["FlexLayoutYogaKit"], 21 | path: "Sources/Swift", 22 | publicHeadersPath: "Public" 23 | ), 24 | .target( 25 | name: "FlexLayoutYogaKit", 26 | dependencies: ["yoga"], 27 | path: "Sources/YogaKit", 28 | publicHeadersPath: "include/YogaKit" 29 | ), 30 | .testTarget( 31 | name: "FlexLayoutTests", 32 | dependencies: [ 33 | "FlexLayout", 34 | ] 35 | ), 36 | ], 37 | cxxLanguageStandard: CXXLanguageStandard(rawValue: "c++20") 38 | ) 39 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | source 'https://cdn.cocoapods.org/' 2 | use_frameworks! :linkage => :static 3 | platform :ios, '13.4' 4 | 5 | workspace 'FlexLayout.xcworkspace' 6 | 7 | target 'FlexLayout' do 8 | pod 'Yoga' 9 | end 10 | 11 | target 'FlexLayoutTests' do 12 | project 'FlexLayout.xcodeproj' 13 | pod 'FlexLayout', path: './' 14 | end 15 | 16 | target 'FlexLayoutSample' do 17 | project 'Example/cocoapods/FlexLayoutSample.xcodeproj' 18 | 19 | pod 'FlexLayout', path: './' 20 | pod 'PinLayout' 21 | 22 | # Debug only 23 | pod 'SwiftLint' 24 | end 25 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - FlexLayout (2.2.1): 3 | - Yoga (= 3.2.1) 4 | - PinLayout (1.10.5) 5 | - SwiftLint (0.55.1) 6 | - Yoga (3.2.1) 7 | 8 | DEPENDENCIES: 9 | - FlexLayout (from `./`) 10 | - PinLayout 11 | - SwiftLint 12 | - Yoga 13 | 14 | SPEC REPOS: 15 | trunk: 16 | - PinLayout 17 | - SwiftLint 18 | - Yoga 19 | 20 | EXTERNAL SOURCES: 21 | FlexLayout: 22 | :path: "./" 23 | 24 | SPEC CHECKSUMS: 25 | FlexLayout: fe365fe6e4a7bf1a53b7421a75acf4c7991e3575 26 | PinLayout: f6c2b63a5a5b24864064e1d15c67de41b4e74748 27 | SwiftLint: 3fe909719babe5537c552ee8181c0031392be933 28 | Yoga: 636ce73bd247407928a7df089f3bc3675916b3ff 29 | 30 | PODFILE CHECKSUM: e95bd8fefde1bd2741249ea540133b9a4393b01f 31 | 32 | COCOAPODS: 1.16.2 33 | -------------------------------------------------------------------------------- /Sources/Swift/Impl/FlexLayout+Enum.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | // 13 | // Created by Luc Dion on 2017-07-17. 14 | 15 | import UIKit 16 | 17 | import yoga 18 | 19 | extension Flex.Direction { 20 | var yogaValue: YGFlexDirection { 21 | switch self { 22 | case .column: return YGFlexDirection.column 23 | case .columnReverse: return YGFlexDirection.columnReverse 24 | case .row: return YGFlexDirection.row 25 | case .rowReverse: return YGFlexDirection.rowReverse 26 | } 27 | } 28 | } 29 | 30 | extension Flex.JustifyContent { 31 | var yogaValue: YGJustify { 32 | switch self { 33 | case .start: return YGJustify.flexStart 34 | case .center: return YGJustify.center 35 | case .end: return YGJustify.flexEnd 36 | case .spaceBetween: return YGJustify.spaceBetween 37 | case .spaceAround: return YGJustify.spaceAround 38 | case .spaceEvenly: return YGJustify.spaceEvenly 39 | } 40 | } 41 | } 42 | 43 | extension Flex.AlignContent { 44 | var yogaValue: YGAlign { 45 | switch self { 46 | case .stretch: return YGAlign.stretch 47 | case .start: return YGAlign.flexStart 48 | case .center: return YGAlign.center 49 | case .end: return YGAlign.flexEnd 50 | case .spaceBetween: return YGAlign.spaceBetween 51 | case .spaceAround: return YGAlign.spaceAround 52 | case .spaceEvenly: return YGAlign.spaceEvenly 53 | } 54 | } 55 | } 56 | 57 | extension Flex.AlignItems { 58 | var yogaValue: YGAlign { 59 | switch self { 60 | case .stretch: return YGAlign.stretch 61 | case .start: return YGAlign.flexStart 62 | case .center: return YGAlign.center 63 | case .end: return YGAlign.flexEnd 64 | case .baseline: return YGAlign.baseline 65 | } 66 | } 67 | } 68 | 69 | extension Flex.AlignSelf { 70 | var yogaValue: YGAlign { 71 | switch self { 72 | case .auto: return YGAlign.auto 73 | case .stretch: return YGAlign.stretch 74 | case .start: return YGAlign.flexStart 75 | case .center: return YGAlign.center 76 | case .end: return YGAlign.flexEnd 77 | case .baseline: return YGAlign.baseline 78 | } 79 | } 80 | } 81 | 82 | extension Flex.Wrap { 83 | var yogaValue: YGWrap { 84 | switch self { 85 | case .noWrap: return YGWrap.noWrap 86 | case .wrap: return YGWrap.wrap 87 | case .wrapReverse: return YGWrap.wrapReverse 88 | } 89 | } 90 | } 91 | 92 | extension Flex.Position { 93 | var yogaValue: YGPositionType { 94 | switch self { 95 | case .relative: return YGPositionType.relative 96 | case .absolute: return YGPositionType.absolute 97 | case .static: return YGPositionType.static 98 | } 99 | } 100 | } 101 | 102 | extension Flex.LayoutDirection { 103 | var yogaValue: YGDirection { 104 | switch self { 105 | case .ltr: return YGDirection.LTR 106 | case .rtl: return YGDirection.RTL 107 | default: return YGDirection.inherit 108 | } 109 | } 110 | } 111 | 112 | extension Flex.Display { 113 | var yogaValue: YGDisplay { 114 | switch self { 115 | case .flex: return YGDisplay.flex 116 | case .none: return YGDisplay.none 117 | case .contents: return YGDisplay.contents 118 | } 119 | } 120 | } 121 | 122 | extension Flex.BoxSizing { 123 | var yogaValue: YGBoxSizing { 124 | switch self { 125 | case .borderBox: return YGBoxSizing.borderBox 126 | case .contentBox: return YGBoxSizing.contentBox 127 | } 128 | } 129 | } 130 | 131 | /*extension Flex.Overflow { 132 | var yogaValue: YGOverflow { 133 | switch self { 134 | case .visible: return YGOverflow.visible 135 | case .hidden: return YGOverflow.hidden 136 | case .scroll: return YGOverflow.scroll 137 | } 138 | } 139 | }*/ 140 | -------------------------------------------------------------------------------- /Sources/Swift/Impl/FlexLayout+Private.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FlexLayout+Private.swift 3 | // FlexLayout 4 | // 5 | // Created by DION, Luc (MTL) on 2017-11-23. 6 | // Copyright © 2017 Mirego. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | import yoga 12 | 13 | extension Flex { 14 | func valueOrUndefined(_ value: CGFloat?) -> YGValue { 15 | if let value = value { 16 | return YGValue(value) 17 | } else { 18 | return YGValueUndefined 19 | } 20 | } 21 | 22 | func valueOrAuto(_ value: CGFloat?) -> YGValue { 23 | if let value = value { 24 | return YGValue(value) 25 | } else { 26 | return YGValueAuto 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Sources/Swift/Impl/UIView+FlexLayout.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | // 13 | // Created by Luc Dion on 2017-07-17. 14 | 15 | import UIKit 16 | 17 | @MainActor 18 | private var flexLayoutAssociatedObjectHandle = 72_399_923 19 | 20 | extension UIView { 21 | public var flex: Flex { 22 | if let flex = objc_getAssociatedObject(self, &flexLayoutAssociatedObjectHandle) as? Flex { 23 | return flex 24 | } else { 25 | let flex = Flex(view: self) 26 | objc_setAssociatedObject(self, &flexLayoutAssociatedObjectHandle, flex, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) 27 | return flex 28 | } 29 | } 30 | 31 | public var isFlexEnabled: Bool { 32 | (objc_getAssociatedObject(self, &flexLayoutAssociatedObjectHandle) as? Flex) != nil 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Sources/Swift/Percent.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | 20 | import UIKit 21 | 22 | public struct FPercent { 23 | let value: CGFloat 24 | } 25 | 26 | postfix operator % 27 | 28 | public postfix func % (v: CGFloat) -> FPercent { 29 | return FPercent(value: v) 30 | } 31 | 32 | public postfix func % (v: Int) -> FPercent { 33 | return FPercent(value: CGFloat(v)) 34 | } 35 | 36 | prefix operator - 37 | public prefix func - (p: FPercent) -> FPercent { 38 | return FPercent(value: -p.value) 39 | } 40 | -------------------------------------------------------------------------------- /Sources/Swift/Public/FlexLayout.h: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | // 13 | // Created by Luc Dion on 2017-07-17. 14 | 15 | #import 16 | 17 | #import "UIView+Yoga.h" 18 | #import "YGLayout+Private.h" 19 | 20 | //! Project version number for FlexLayout. 21 | FOUNDATION_EXPORT double FlexLayoutVersionNumber; 22 | 23 | //! Project version string for FlexLayout. 24 | FOUNDATION_EXPORT const unsigned char FlexLayoutVersionString[]; 25 | 26 | // In this header, you should import all the public headers of your framework using 27 | #import 28 | #import 29 | #import 30 | #import 31 | -------------------------------------------------------------------------------- /Sources/Swift/YGLayoutExtensions.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import CoreGraphics 9 | 10 | import yoga 11 | 12 | extension Int { 13 | public static postfix func %(value: Int) -> YGValue { 14 | return YGValue(value: Float(value), unit: .percent) 15 | } 16 | } 17 | 18 | extension Float { 19 | public static postfix func %(value: Float) -> YGValue { 20 | return YGValue(value: value, unit: .percent) 21 | } 22 | } 23 | 24 | extension CGFloat { 25 | public static postfix func %(value: CGFloat) -> YGValue { 26 | return YGValue(value: Float(value), unit: .percent) 27 | } 28 | } 29 | 30 | extension YGValue : ExpressibleByIntegerLiteral, ExpressibleByFloatLiteral { 31 | public init(integerLiteral value: Int) { 32 | self = YGValue(value: Float(value), unit: .point) 33 | } 34 | 35 | public init(floatLiteral value: Float) { 36 | self = YGValue(value: value, unit: .point) 37 | } 38 | 39 | public init(_ value: Float) { 40 | self = YGValue(value: value, unit: .point) 41 | } 42 | 43 | public init(_ value: CGFloat) { 44 | self = YGValue(value: Float(value), unit: .point) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Sources/YogaKit/UIView+Yoga.mm: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #import 9 | #import "UIView+Yoga.h" 10 | #import "YGLayout+Private.h" 11 | 12 | static const void* kYGYogaAssociatedKey = &kYGYogaAssociatedKey; 13 | 14 | @implementation UIView (YogaKit) 15 | 16 | - (YGLayout*)yoga { 17 | YGLayout* yoga = objc_getAssociatedObject(self, kYGYogaAssociatedKey); 18 | if (!yoga) { 19 | yoga = [[YGLayout alloc] initWithView:self]; 20 | objc_setAssociatedObject( 21 | self, kYGYogaAssociatedKey, yoga, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 22 | } 23 | 24 | return yoga; 25 | } 26 | 27 | - (BOOL)isYogaEnabled { 28 | return objc_getAssociatedObject(self, kYGYogaAssociatedKey) != nil; 29 | } 30 | 31 | - (void)configureLayoutWithBlock:(YGLayoutConfigurationBlock)block { 32 | if (block != nil) { 33 | block(self.yoga); 34 | } 35 | } 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /Sources/YogaKit/include/YogaKit/UIView+Yoga.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #import 9 | #import "YGLayout.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | typedef void (^YGLayoutConfigurationBlock)(YGLayout* layout); 14 | 15 | @interface UIView (Yoga) 16 | 17 | /** 18 | The YGLayout that is attached to this view. It is lazily created. 19 | */ 20 | @property(nonatomic, readonly, strong) YGLayout* yoga; 21 | /** 22 | Indicates whether or not Yoga is enabled 23 | */ 24 | @property(nonatomic, readonly, assign) BOOL isYogaEnabled; 25 | 26 | /** 27 | In ObjC land, every time you access `view.yoga.*` you are adding another 28 | `objc_msgSend` to your code. If you plan on making multiple changes to 29 | YGLayout, it's more performant to use this method, which uses a single 30 | objc_msgSend call. 31 | */ 32 | - (void)configureLayoutWithBlock:(YGLayoutConfigurationBlock)block 33 | NS_SWIFT_NAME(configureLayout(block:)); 34 | 35 | @end 36 | 37 | NS_ASSUME_NONNULL_END 38 | -------------------------------------------------------------------------------- /Sources/YogaKit/include/YogaKit/YGLayout+Private.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #import 9 | #import "YGLayout.h" 10 | 11 | @interface YGLayout () 12 | 13 | @property(nonatomic, assign, readonly) YGNodeRef node; 14 | 15 | - (instancetype)initWithView:(UIView*)view; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Tests/FlexLayoutTests/FlexLayoutTests.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | 13 | import XCTest 14 | @testable import FlexLayout 15 | 16 | @MainActor 17 | final class FlexLayoutTests: XCTestCase { 18 | 19 | func testRetainCycle() { 20 | weak var weakView: UIView? = nil 21 | _ = { _ in 22 | let strongView = UIView() 23 | strongView.flex.direction(.column) 24 | weakView = strongView 25 | }(()) 26 | 27 | XCTAssertNil(weakView, "Creation of flex should not lead to retain cycle") 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /Tests/FlexLayoutTests/MarginTests.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | 13 | import FlexLayout 14 | import XCTest 15 | 16 | @MainActor 17 | final class MarginTests: XCTestCase, Sendable { 18 | 19 | var viewController: UIViewController! 20 | var rootFlexContainer: UIView! 21 | var aView: UIView! 22 | 23 | override func setUp() async throws { 24 | try await super.setUp() 25 | 26 | viewController = UIViewController() 27 | 28 | rootFlexContainer = UIView() 29 | rootFlexContainer.frame = CGRect(x: 0, y: 0, width: 400, height: 400) 30 | viewController.view.addSubview(rootFlexContainer) 31 | 32 | aView = UIView() 33 | } 34 | 35 | func test_adjust_the_rootFlexContainer_size_and_position() { 36 | rootFlexContainer.flex.define { _ in 37 | } 38 | rootFlexContainer.flex.layout() 39 | XCTAssertEqual(rootFlexContainer.frame, CGRect(x: 0.0, y: 0.0, width: 400.0, height: 400.0)) 40 | } 41 | 42 | func test_adjust_the_aView_size_and_position() { 43 | rootFlexContainer.flex.define { flex in 44 | flex.addItem(aView).grow(1) 45 | } 46 | rootFlexContainer.flex.layout() 47 | XCTAssertEqual(aView.frame, CGRect(x: 0.0, y: 0.0, width: 400.0, height: 400.0)) 48 | } 49 | 50 | func test_adjust_the_aView_size_and_position_with_marginLeft() { 51 | rootFlexContainer.flex.define { flex in 52 | flex.addItem(aView).grow(1).marginLeft(10) 53 | } 54 | rootFlexContainer.flex.layout() 55 | XCTAssertEqual(aView.frame, CGRect(x: 10.0, y: 0.0, width: 390.0, height: 400.0)) 56 | } 57 | 58 | func test_adjust_the_aView_size_and_position_with_marginTop() { 59 | rootFlexContainer.flex.define { flex in 60 | flex.addItem(aView).grow(1).marginTop(10) 61 | } 62 | rootFlexContainer.flex.layout() 63 | XCTAssertEqual(aView.frame, CGRect(x: 0.0, y: 10.0, width: 400.0, height: 390.0)) 64 | } 65 | 66 | func test_adjust_the_aView_size_and_position_with_marginBottom() { 67 | rootFlexContainer.flex.define { flex in 68 | flex.addItem(aView).grow(1).marginBottom(10) 69 | } 70 | rootFlexContainer.flex.layout() 71 | XCTAssertEqual(aView.frame, CGRect(x: 0.0, y: 0.0, width: 400.0, height: 390.0)) 72 | } 73 | 74 | func test_adjust_the_aView_size_and_position_with_marginStart() { 75 | rootFlexContainer.flex.define { flex in 76 | flex.addItem(aView).grow(1).marginStart(10) 77 | } 78 | rootFlexContainer.flex.layout() 79 | XCTAssertEqual(aView.frame, CGRect(x: 10.0, y: 0.0, width: 390.0, height: 400.0)) 80 | } 81 | 82 | func test_adjust_the_aView_size_and_position_with_marginEnd() { 83 | rootFlexContainer.flex.define { flex in 84 | flex.addItem(aView).grow(1).marginEnd(10) 85 | } 86 | rootFlexContainer.flex.layout() 87 | XCTAssertEqual(aView.frame, CGRect(x: 0.0, y: 0.0, width: 390.0, height: 400.0)) 88 | } 89 | 90 | func test_adjust_the_aView_size_and_position_with_margin() { 91 | rootFlexContainer.flex.define { flex in 92 | flex.addItem(aView).grow(1).margin(10, 20, 30, 40) 93 | } 94 | rootFlexContainer.flex.layout() 95 | XCTAssertEqual(aView.frame, CGRect(x: 20.0, y: 10.0, width: 340.0, height: 360.0)) 96 | } 97 | 98 | func test_adjust_the_aView_size_and_position_with_margin_all() { 99 | rootFlexContainer.flex.define { flex in 100 | flex.addItem(aView).grow(1).margin(10) 101 | } 102 | rootFlexContainer.flex.layout() 103 | XCTAssertEqual(aView.frame, CGRect(x: 10.0, y: 10.0, width: 380.0, height: 380.0)) 104 | } 105 | 106 | func test_adjust_the_aView_size_and_position_with_marginVertical() { 107 | rootFlexContainer.flex.define { flex in 108 | flex.addItem(aView).grow(1).marginVertical(10) 109 | } 110 | rootFlexContainer.flex.layout() 111 | XCTAssertEqual(aView.frame, CGRect(x: 0.0, y: 10.0, width: 400.0, height: 380.0)) 112 | } 113 | 114 | func test_adjust_the_aView_size_and_position_with_marginHorizontal() { 115 | rootFlexContainer.flex.define { flex in 116 | flex.addItem(aView).grow(1).marginHorizontal(10) 117 | } 118 | rootFlexContainer.flex.layout() 119 | XCTAssertEqual(aView.frame, CGRect(x: 10.0, y: 0.0, width: 380.0, height: 400.0)) 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /docs/1.1/Classes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Classes Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |

FlexLayout Docs (91% documented)

17 |

View on GitHub

18 |
19 |
20 |
21 | 26 |
27 |
28 | 67 |
68 |
69 |
70 |

Classes

71 |

The following classes are available globally.

72 | 73 |
74 |
75 |
76 |
    77 |
  • 78 |
    79 | 80 | 81 | 82 | Flex 83 | 84 |
    85 |
    86 |
    87 |
    88 |
    89 |
    90 |

    FlexLayout interface.

    91 | 92 |

    The interface is accessible from any UIView class instance:

    93 |
       label.flex.margin(10)
     94 | 
    95 | 96 | See more 97 |
    98 |
    99 |

    Declaration

    100 |
    101 |

    Swift

    102 |
    public class Flex
    103 | 104 |
    105 |
    106 |
    107 | Show on GitHub 108 |
    109 |
    110 |
    111 |
  • 112 |
113 |
114 |
115 |
116 | 120 |
121 |
122 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /docs/1.1/badge.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | documentation 17 | 18 | 19 | documentation 20 | 21 | 22 | 91% 23 | 24 | 25 | 91% 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /docs/1.1/css/highlight.css: -------------------------------------------------------------------------------- 1 | /* Credit to https://gist.github.com/wataru420/2048287 */ 2 | .highlight { 3 | /* Comment */ 4 | /* Error */ 5 | /* Keyword */ 6 | /* Operator */ 7 | /* Comment.Multiline */ 8 | /* Comment.Preproc */ 9 | /* Comment.Single */ 10 | /* Comment.Special */ 11 | /* Generic.Deleted */ 12 | /* Generic.Deleted.Specific */ 13 | /* Generic.Emph */ 14 | /* Generic.Error */ 15 | /* Generic.Heading */ 16 | /* Generic.Inserted */ 17 | /* Generic.Inserted.Specific */ 18 | /* Generic.Output */ 19 | /* Generic.Prompt */ 20 | /* Generic.Strong */ 21 | /* Generic.Subheading */ 22 | /* Generic.Traceback */ 23 | /* Keyword.Constant */ 24 | /* Keyword.Declaration */ 25 | /* Keyword.Pseudo */ 26 | /* Keyword.Reserved */ 27 | /* Keyword.Type */ 28 | /* Literal.Number */ 29 | /* Literal.String */ 30 | /* Name.Attribute */ 31 | /* Name.Builtin */ 32 | /* Name.Class */ 33 | /* Name.Constant */ 34 | /* Name.Entity */ 35 | /* Name.Exception */ 36 | /* Name.Function */ 37 | /* Name.Namespace */ 38 | /* Name.Tag */ 39 | /* Name.Variable */ 40 | /* Operator.Word */ 41 | /* Text.Whitespace */ 42 | /* Literal.Number.Float */ 43 | /* Literal.Number.Hex */ 44 | /* Literal.Number.Integer */ 45 | /* Literal.Number.Oct */ 46 | /* Literal.String.Backtick */ 47 | /* Literal.String.Char */ 48 | /* Literal.String.Doc */ 49 | /* Literal.String.Double */ 50 | /* Literal.String.Escape */ 51 | /* Literal.String.Heredoc */ 52 | /* Literal.String.Interpol */ 53 | /* Literal.String.Other */ 54 | /* Literal.String.Regex */ 55 | /* Literal.String.Single */ 56 | /* Literal.String.Symbol */ 57 | /* Name.Builtin.Pseudo */ 58 | /* Name.Variable.Class */ 59 | /* Name.Variable.Global */ 60 | /* Name.Variable.Instance */ 61 | /* Literal.Number.Integer.Long */ } 62 | .highlight .c { 63 | color: #999988; 64 | font-style: italic; } 65 | .highlight .err { 66 | color: #a61717; 67 | background-color: #e3d2d2; } 68 | .highlight .k { 69 | color: #000000; 70 | font-weight: bold; } 71 | .highlight .o { 72 | color: #000000; 73 | font-weight: bold; } 74 | .highlight .cm { 75 | color: #999988; 76 | font-style: italic; } 77 | .highlight .cp { 78 | color: #999999; 79 | font-weight: bold; } 80 | .highlight .c1 { 81 | color: #999988; 82 | font-style: italic; } 83 | .highlight .cs { 84 | color: #999999; 85 | font-weight: bold; 86 | font-style: italic; } 87 | .highlight .gd { 88 | color: #000000; 89 | background-color: #ffdddd; } 90 | .highlight .gd .x { 91 | color: #000000; 92 | background-color: #ffaaaa; } 93 | .highlight .ge { 94 | color: #000000; 95 | font-style: italic; } 96 | .highlight .gr { 97 | color: #aa0000; } 98 | .highlight .gh { 99 | color: #999999; } 100 | .highlight .gi { 101 | color: #000000; 102 | background-color: #ddffdd; } 103 | .highlight .gi .x { 104 | color: #000000; 105 | background-color: #aaffaa; } 106 | .highlight .go { 107 | color: #888888; } 108 | .highlight .gp { 109 | color: #555555; } 110 | .highlight .gs { 111 | font-weight: bold; } 112 | .highlight .gu { 113 | color: #aaaaaa; } 114 | .highlight .gt { 115 | color: #aa0000; } 116 | .highlight .kc { 117 | color: #000000; 118 | font-weight: bold; } 119 | .highlight .kd { 120 | color: #000000; 121 | font-weight: bold; } 122 | .highlight .kp { 123 | color: #000000; 124 | font-weight: bold; } 125 | .highlight .kr { 126 | color: #000000; 127 | font-weight: bold; } 128 | .highlight .kt { 129 | color: #445588; } 130 | .highlight .m { 131 | color: #009999; } 132 | .highlight .s { 133 | color: #d14; } 134 | .highlight .na { 135 | color: #008080; } 136 | .highlight .nb { 137 | color: #0086B3; } 138 | .highlight .nc { 139 | color: #445588; 140 | font-weight: bold; } 141 | .highlight .no { 142 | color: #008080; } 143 | .highlight .ni { 144 | color: #800080; } 145 | .highlight .ne { 146 | color: #990000; 147 | font-weight: bold; } 148 | .highlight .nf { 149 | color: #990000; } 150 | .highlight .nn { 151 | color: #555555; } 152 | .highlight .nt { 153 | color: #000080; } 154 | .highlight .nv { 155 | color: #008080; } 156 | .highlight .ow { 157 | color: #000000; 158 | font-weight: bold; } 159 | .highlight .w { 160 | color: #bbbbbb; } 161 | .highlight .mf { 162 | color: #009999; } 163 | .highlight .mh { 164 | color: #009999; } 165 | .highlight .mi { 166 | color: #009999; } 167 | .highlight .mo { 168 | color: #009999; } 169 | .highlight .sb { 170 | color: #d14; } 171 | .highlight .sc { 172 | color: #d14; } 173 | .highlight .sd { 174 | color: #d14; } 175 | .highlight .s2 { 176 | color: #d14; } 177 | .highlight .se { 178 | color: #d14; } 179 | .highlight .sh { 180 | color: #d14; } 181 | .highlight .si { 182 | color: #d14; } 183 | .highlight .sx { 184 | color: #d14; } 185 | .highlight .sr { 186 | color: #009926; } 187 | .highlight .s1 { 188 | color: #d14; } 189 | .highlight .ss { 190 | color: #990073; } 191 | .highlight .bp { 192 | color: #999999; } 193 | .highlight .vc { 194 | color: #008080; } 195 | .highlight .vg { 196 | color: #008080; } 197 | .highlight .vi { 198 | color: #008080; } 199 | .highlight .il { 200 | color: #009999; } 201 | -------------------------------------------------------------------------------- /docs/1.1/docsets/FlexLayout.docset/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleIdentifier 6 | com.jazzy.flexlayout 7 | CFBundleName 8 | FlexLayout 9 | DocSetPlatformFamily 10 | flexlayout 11 | isDashDocset 12 | 13 | dashIndexFilePath 14 | index.html 15 | isJavaScriptEnabled 16 | 17 | DashDocSetFamily 18 | dashtoc 19 | 20 | 21 | -------------------------------------------------------------------------------- /docs/1.1/docsets/FlexLayout.docset/Contents/Resources/Documents/Classes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Classes Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |

FlexLayout Docs (91% documented)

17 |

View on GitHub

18 |
19 |
20 |
21 | 26 |
27 |
28 | 67 |
68 |
69 |
70 |

Classes

71 |

The following classes are available globally.

72 | 73 |
74 |
75 |
76 |
    77 |
  • 78 |
    79 | 80 | 81 | 82 | Flex 83 | 84 |
    85 |
    86 |
    87 |
    88 |
    89 |
    90 |

    FlexLayout interface.

    91 | 92 |

    The interface is accessible from any UIView class instance:

    93 |
       label.flex.margin(10)
     94 | 
    95 | 96 | See more 97 |
    98 |
    99 |

    Declaration

    100 |
    101 |

    Swift

    102 |
    public class Flex
    103 | 104 |
    105 |
    106 |
    107 | Show on GitHub 108 |
    109 |
    110 |
    111 |
  • 112 |
113 |
114 |
115 |
116 | 120 |
121 |
122 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /docs/1.1/docsets/FlexLayout.docset/Contents/Resources/Documents/css/highlight.css: -------------------------------------------------------------------------------- 1 | /* Credit to https://gist.github.com/wataru420/2048287 */ 2 | .highlight { 3 | /* Comment */ 4 | /* Error */ 5 | /* Keyword */ 6 | /* Operator */ 7 | /* Comment.Multiline */ 8 | /* Comment.Preproc */ 9 | /* Comment.Single */ 10 | /* Comment.Special */ 11 | /* Generic.Deleted */ 12 | /* Generic.Deleted.Specific */ 13 | /* Generic.Emph */ 14 | /* Generic.Error */ 15 | /* Generic.Heading */ 16 | /* Generic.Inserted */ 17 | /* Generic.Inserted.Specific */ 18 | /* Generic.Output */ 19 | /* Generic.Prompt */ 20 | /* Generic.Strong */ 21 | /* Generic.Subheading */ 22 | /* Generic.Traceback */ 23 | /* Keyword.Constant */ 24 | /* Keyword.Declaration */ 25 | /* Keyword.Pseudo */ 26 | /* Keyword.Reserved */ 27 | /* Keyword.Type */ 28 | /* Literal.Number */ 29 | /* Literal.String */ 30 | /* Name.Attribute */ 31 | /* Name.Builtin */ 32 | /* Name.Class */ 33 | /* Name.Constant */ 34 | /* Name.Entity */ 35 | /* Name.Exception */ 36 | /* Name.Function */ 37 | /* Name.Namespace */ 38 | /* Name.Tag */ 39 | /* Name.Variable */ 40 | /* Operator.Word */ 41 | /* Text.Whitespace */ 42 | /* Literal.Number.Float */ 43 | /* Literal.Number.Hex */ 44 | /* Literal.Number.Integer */ 45 | /* Literal.Number.Oct */ 46 | /* Literal.String.Backtick */ 47 | /* Literal.String.Char */ 48 | /* Literal.String.Doc */ 49 | /* Literal.String.Double */ 50 | /* Literal.String.Escape */ 51 | /* Literal.String.Heredoc */ 52 | /* Literal.String.Interpol */ 53 | /* Literal.String.Other */ 54 | /* Literal.String.Regex */ 55 | /* Literal.String.Single */ 56 | /* Literal.String.Symbol */ 57 | /* Name.Builtin.Pseudo */ 58 | /* Name.Variable.Class */ 59 | /* Name.Variable.Global */ 60 | /* Name.Variable.Instance */ 61 | /* Literal.Number.Integer.Long */ } 62 | .highlight .c { 63 | color: #999988; 64 | font-style: italic; } 65 | .highlight .err { 66 | color: #a61717; 67 | background-color: #e3d2d2; } 68 | .highlight .k { 69 | color: #000000; 70 | font-weight: bold; } 71 | .highlight .o { 72 | color: #000000; 73 | font-weight: bold; } 74 | .highlight .cm { 75 | color: #999988; 76 | font-style: italic; } 77 | .highlight .cp { 78 | color: #999999; 79 | font-weight: bold; } 80 | .highlight .c1 { 81 | color: #999988; 82 | font-style: italic; } 83 | .highlight .cs { 84 | color: #999999; 85 | font-weight: bold; 86 | font-style: italic; } 87 | .highlight .gd { 88 | color: #000000; 89 | background-color: #ffdddd; } 90 | .highlight .gd .x { 91 | color: #000000; 92 | background-color: #ffaaaa; } 93 | .highlight .ge { 94 | color: #000000; 95 | font-style: italic; } 96 | .highlight .gr { 97 | color: #aa0000; } 98 | .highlight .gh { 99 | color: #999999; } 100 | .highlight .gi { 101 | color: #000000; 102 | background-color: #ddffdd; } 103 | .highlight .gi .x { 104 | color: #000000; 105 | background-color: #aaffaa; } 106 | .highlight .go { 107 | color: #888888; } 108 | .highlight .gp { 109 | color: #555555; } 110 | .highlight .gs { 111 | font-weight: bold; } 112 | .highlight .gu { 113 | color: #aaaaaa; } 114 | .highlight .gt { 115 | color: #aa0000; } 116 | .highlight .kc { 117 | color: #000000; 118 | font-weight: bold; } 119 | .highlight .kd { 120 | color: #000000; 121 | font-weight: bold; } 122 | .highlight .kp { 123 | color: #000000; 124 | font-weight: bold; } 125 | .highlight .kr { 126 | color: #000000; 127 | font-weight: bold; } 128 | .highlight .kt { 129 | color: #445588; } 130 | .highlight .m { 131 | color: #009999; } 132 | .highlight .s { 133 | color: #d14; } 134 | .highlight .na { 135 | color: #008080; } 136 | .highlight .nb { 137 | color: #0086B3; } 138 | .highlight .nc { 139 | color: #445588; 140 | font-weight: bold; } 141 | .highlight .no { 142 | color: #008080; } 143 | .highlight .ni { 144 | color: #800080; } 145 | .highlight .ne { 146 | color: #990000; 147 | font-weight: bold; } 148 | .highlight .nf { 149 | color: #990000; } 150 | .highlight .nn { 151 | color: #555555; } 152 | .highlight .nt { 153 | color: #000080; } 154 | .highlight .nv { 155 | color: #008080; } 156 | .highlight .ow { 157 | color: #000000; 158 | font-weight: bold; } 159 | .highlight .w { 160 | color: #bbbbbb; } 161 | .highlight .mf { 162 | color: #009999; } 163 | .highlight .mh { 164 | color: #009999; } 165 | .highlight .mi { 166 | color: #009999; } 167 | .highlight .mo { 168 | color: #009999; } 169 | .highlight .sb { 170 | color: #d14; } 171 | .highlight .sc { 172 | color: #d14; } 173 | .highlight .sd { 174 | color: #d14; } 175 | .highlight .s2 { 176 | color: #d14; } 177 | .highlight .se { 178 | color: #d14; } 179 | .highlight .sh { 180 | color: #d14; } 181 | .highlight .si { 182 | color: #d14; } 183 | .highlight .sx { 184 | color: #d14; } 185 | .highlight .sr { 186 | color: #009926; } 187 | .highlight .s1 { 188 | color: #d14; } 189 | .highlight .ss { 190 | color: #990073; } 191 | .highlight .bp { 192 | color: #999999; } 193 | .highlight .vc { 194 | color: #008080; } 195 | .highlight .vg { 196 | color: #008080; } 197 | .highlight .vi { 198 | color: #008080; } 199 | .highlight .il { 200 | color: #009999; } 201 | -------------------------------------------------------------------------------- /docs/1.1/docsets/FlexLayout.docset/Contents/Resources/Documents/img/carat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs/1.1/docsets/FlexLayout.docset/Contents/Resources/Documents/img/carat.png -------------------------------------------------------------------------------- /docs/1.1/docsets/FlexLayout.docset/Contents/Resources/Documents/img/dash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs/1.1/docsets/FlexLayout.docset/Contents/Resources/Documents/img/dash.png -------------------------------------------------------------------------------- /docs/1.1/docsets/FlexLayout.docset/Contents/Resources/Documents/img/gh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs/1.1/docsets/FlexLayout.docset/Contents/Resources/Documents/img/gh.png -------------------------------------------------------------------------------- /docs/1.1/docsets/FlexLayout.docset/Contents/Resources/Documents/js/jazzy.js: -------------------------------------------------------------------------------- 1 | window.jazzy = {'docset': false} 2 | if (typeof window.dash != 'undefined') { 3 | document.documentElement.className += ' dash' 4 | window.jazzy.docset = true 5 | } 6 | if (navigator.userAgent.match(/xcode/i)) { 7 | document.documentElement.className += ' xcode' 8 | window.jazzy.docset = true 9 | } 10 | 11 | // On doc load, toggle the URL hash discussion if present 12 | $(document).ready(function() { 13 | if (!window.jazzy.docset) { 14 | var linkToHash = $('a[href="' + window.location.hash +'"]'); 15 | linkToHash.trigger("click"); 16 | } 17 | }); 18 | 19 | // On token click, toggle its discussion and animate token.marginLeft 20 | $(".token").click(function(event) { 21 | if (window.jazzy.docset) { 22 | return; 23 | } 24 | var link = $(this); 25 | var animationDuration = 300; 26 | var tokenOffset = "15px"; 27 | var original = link.css('marginLeft') == tokenOffset; 28 | link.animate({'margin-left':original ? "0px" : tokenOffset}, animationDuration); 29 | $content = link.parent().parent().next(); 30 | $content.slideToggle(animationDuration); 31 | 32 | // Keeps the document from jumping to the hash. 33 | var href = $(this).attr('href'); 34 | if (history.pushState) { 35 | history.pushState({}, '', href); 36 | } else { 37 | location.hash = href; 38 | } 39 | event.preventDefault(); 40 | }); 41 | 42 | // Dumb down quotes within code blocks that delimit strings instead of quotations 43 | // https://github.com/realm/jazzy/issues/714 44 | $("code q").replaceWith(function () { 45 | return ["\"", $(this).contents(), "\""]; 46 | }); 47 | -------------------------------------------------------------------------------- /docs/1.1/docsets/FlexLayout.docset/Contents/Resources/docSet.dsidx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs/1.1/docsets/FlexLayout.docset/Contents/Resources/docSet.dsidx -------------------------------------------------------------------------------- /docs/1.1/docsets/FlexLayout.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs/1.1/docsets/FlexLayout.tgz -------------------------------------------------------------------------------- /docs/1.1/img/carat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs/1.1/img/carat.png -------------------------------------------------------------------------------- /docs/1.1/img/dash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs/1.1/img/dash.png -------------------------------------------------------------------------------- /docs/1.1/img/gh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs/1.1/img/gh.png -------------------------------------------------------------------------------- /docs/1.1/js/jazzy.js: -------------------------------------------------------------------------------- 1 | window.jazzy = {'docset': false} 2 | if (typeof window.dash != 'undefined') { 3 | document.documentElement.className += ' dash' 4 | window.jazzy.docset = true 5 | } 6 | if (navigator.userAgent.match(/xcode/i)) { 7 | document.documentElement.className += ' xcode' 8 | window.jazzy.docset = true 9 | } 10 | 11 | // On doc load, toggle the URL hash discussion if present 12 | $(document).ready(function() { 13 | if (!window.jazzy.docset) { 14 | var linkToHash = $('a[href="' + window.location.hash +'"]'); 15 | linkToHash.trigger("click"); 16 | } 17 | }); 18 | 19 | // On token click, toggle its discussion and animate token.marginLeft 20 | $(".token").click(function(event) { 21 | if (window.jazzy.docset) { 22 | return; 23 | } 24 | var link = $(this); 25 | var animationDuration = 300; 26 | var tokenOffset = "15px"; 27 | var original = link.css('marginLeft') == tokenOffset; 28 | link.animate({'margin-left':original ? "0px" : tokenOffset}, animationDuration); 29 | $content = link.parent().parent().next(); 30 | $content.slideToggle(animationDuration); 31 | 32 | // Keeps the document from jumping to the hash. 33 | var href = $(this).attr('href'); 34 | if (history.pushState) { 35 | history.pushState({}, '', href); 36 | } else { 37 | location.hash = href; 38 | } 39 | event.preventDefault(); 40 | }); 41 | 42 | // Dumb down quotes within code blocks that delimit strings instead of quotations 43 | // https://github.com/realm/jazzy/issues/714 44 | $("code q").replaceWith(function () { 45 | return ["\"", $(this).contents(), "\""]; 46 | }); 47 | -------------------------------------------------------------------------------- /docs/1.1/undocumented.json: -------------------------------------------------------------------------------- 1 | { 2 | "warnings": [ 3 | { 4 | "file": "/Users/dionlu/Dropbox (Personal)/devluc2/FlexLayout/Sources/FlexLayout.swift", 5 | "line": 581, 6 | "symbol": "Flex.marginTop(_:)", 7 | "symbol_kind": "source.lang.swift.decl.function.method.instance", 8 | "warning": "undocumented" 9 | }, 10 | { 11 | "file": "/Users/dionlu/Dropbox (Personal)/devluc2/FlexLayout/Sources/FlexLayout.swift", 12 | "line": 596, 13 | "symbol": "Flex.marginLeft(_:)", 14 | "symbol_kind": "source.lang.swift.decl.function.method.instance", 15 | "warning": "undocumented" 16 | }, 17 | { 18 | "file": "/Users/dionlu/Dropbox (Personal)/devluc2/FlexLayout/Sources/FlexLayout.swift", 19 | "line": 611, 20 | "symbol": "Flex.marginBottom(_:)", 21 | "symbol_kind": "source.lang.swift.decl.function.method.instance", 22 | "warning": "undocumented" 23 | }, 24 | { 25 | "file": "/Users/dionlu/Dropbox (Personal)/devluc2/FlexLayout/Sources/FlexLayout.swift", 26 | "line": 626, 27 | "symbol": "Flex.marginRight(_:)", 28 | "symbol_kind": "source.lang.swift.decl.function.method.instance", 29 | "warning": "undocumented" 30 | }, 31 | { 32 | "file": "/Users/dionlu/Dropbox (Personal)/devluc2/FlexLayout/Sources/FlexLayout.swift", 33 | "line": 645, 34 | "symbol": "Flex.marginStart(_:)", 35 | "symbol_kind": "source.lang.swift.decl.function.method.instance", 36 | "warning": "undocumented" 37 | }, 38 | { 39 | "file": "/Users/dionlu/Dropbox (Personal)/devluc2/FlexLayout/Sources/FlexLayout.swift", 40 | "line": 664, 41 | "symbol": "Flex.marginEnd(_:)", 42 | "symbol_kind": "source.lang.swift.decl.function.method.instance", 43 | "warning": "undocumented" 44 | }, 45 | { 46 | "file": "/Users/dionlu/Dropbox (Personal)/devluc2/FlexLayout/Sources/FlexLayout.swift", 47 | "line": 679, 48 | "symbol": "Flex.marginHorizontal(_:)", 49 | "symbol_kind": "source.lang.swift.decl.function.method.instance", 50 | "warning": "undocumented" 51 | }, 52 | { 53 | "file": "/Users/dionlu/Dropbox (Personal)/devluc2/FlexLayout/Sources/FlexLayout.swift", 54 | "line": 694, 55 | "symbol": "Flex.marginVertical(_:)", 56 | "symbol_kind": "source.lang.swift.decl.function.method.instance", 57 | "warning": "undocumented" 58 | }, 59 | { 60 | "file": "/Users/dionlu/Dropbox (Personal)/devluc2/FlexLayout/Sources/FlexLayout.swift", 61 | "line": 738, 62 | "symbol": "Flex.margin(_:)", 63 | "symbol_kind": "source.lang.swift.decl.function.method.instance", 64 | "warning": "undocumented" 65 | }, 66 | { 67 | "file": "/Users/dionlu/Dropbox (Personal)/devluc2/FlexLayout/Sources/FlexLayout.swift", 68 | "line": 788, 69 | "symbol": "Flex.margin(_:_:_:_:)", 70 | "symbol_kind": "source.lang.swift.decl.function.method.instance", 71 | "warning": "undocumented" 72 | } 73 | ], 74 | "source_directory": "/Users/dionlu/Dropbox (Personal)/devluc2/FlexLayout" 75 | } -------------------------------------------------------------------------------- /docs_markdown/benchmark.md: -------------------------------------------------------------------------------- 1 |

2 | FlexLayout and PinLayout Performance 3 |

4 | 5 | 6 |

FlexLayout Benchmark

7 | 8 | ## Methodology 9 | 10 | ### Layout Framework Benchmark 11 | FlexLayout and [PinLayout](https://github.com/layoutBox/PinLayout) performance has been benchmarked using [Layout Framework Benchmark](https://github.com/layoutBox/LayoutFrameworkBenchmark). 12 | 13 | The benchmark includes the following layout frameworks: 14 | 15 | * Auto layout 16 | * [FlexLayout](https://github.com/layoutBox/FlexLayout) 17 | * [LayoutKit](https://github.com/linkedin/LayoutKit) 18 | * Manual layout (i.e. set UIView's frame directly) 19 | * [PinLayout](https://github.com/layoutBox/PinLayout) 20 | * UIStackViews 21 | 22 |
23 | 24 | ### Benchmark details 25 | The benchmark layout UICollectionView and UITableView cells in multiple pass, each pass contains more cells than the previous one. 26 | 27 |
28 | 29 | ### Benchmark Results 30 | 31 | As you can see in the following chart, PinLayout are faster or equal to manual layouting, and **between 8x and 12x faster than auto layout**, and this for all types of iPhone (5S/6/6S/7/8/X) 32 | 33 | The benchmark layout UICollectionView and UITableView cells in multiple pass, each pass contains more cells than the previous one. 34 | 35 | PinLayout Performance 36 | 37 | See [Layout Framework Benchmark](https://github.com/layoutBox/LayoutFrameworkBenchmark) for complete details and benchmarks charts for iPhone X/8/7/6S/... 38 | 39 |
40 | 41 | 42 | ### FlexLayout benchmark source code 43 | 44 | [FlexLayout benchmark's source code](https://github.com/layoutBox/LayoutFrameworkBenchmark/blob/master/LayoutFrameworkBenchmark/Benchmarks/FlexLayout/FeedItemFlexLayoutView.swift) 45 | 46 | ```swift 47 | flex.addItem(contentView).padding(8).define { (flex) in 48 | flex.addItem(contentView).padding(8).define { (flex) in 49 | flex.addItem().direction(.row).justifyContent(.spaceBetween).define { (flex) in 50 | flex.addItem(actionLabel) 51 | flex.addItem(optionsLabel) 52 | } 53 | 54 | flex.addItem().direction(.row).alignItems(.center).define({ (flex) in 55 | flex.addItem(posterImageView).width(50).height(50).marginRight(8) 56 | 57 | flex.addItem().grow(1).define({ (flex) in 58 | flex.addItem(posterNameLabel) 59 | flex.addItem(posterHeadlineLabel) 60 | flex.addItem(posterTimeLabel) 61 | }) 62 | }) 63 | 64 | flex.addItem(posterCommentLabel) 65 | 66 | flex.addItem(contentImageView).aspectRatio(350 / 200) 67 | flex.addItem(contentTitleLabel) 68 | flex.addItem(contentDomainLabel) 69 | 70 | flex.addItem().direction(.row).justifyContent(.spaceBetween).marginTop(4).define({ (flex) in 71 | flex.addItem(likeLabel) 72 | flex.addItem(commentLabel) 73 | flex.addItem(shareLabel) 74 | }) 75 | 76 | flex.addItem().direction(.row).marginTop(2).define({ (flex) in 77 | flex.addItem(actorImageView).width(50).height(50).marginRight(8) 78 | flex.addItem(actorCommentLabel).grow(1) 79 | }) 80 | } 81 | } 82 | ``` 83 | 84 |
85 | -------------------------------------------------------------------------------- /docs_markdown/benchmark/benchmark_comparison_all_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/benchmark/benchmark_comparison_all_small.png -------------------------------------------------------------------------------- /docs_markdown/contributing.md: -------------------------------------------------------------------------------- 1 |

2 | FlexLayout and PinLayout Performance 3 |

4 | 5 | 6 |

Contributing to FlexLayout

7 | 8 | # Run Unit Tests 9 | 10 | To execute Unit Tests you must: 11 | 12 | * Install carthage modules: 13 | `carthage bootstrap --use-ssh --platform iOS` 14 | * Run Unit Test from Xcode by selecting the FlexLayout target. -------------------------------------------------------------------------------- /docs_markdown/examples.md: -------------------------------------------------------------------------------- 1 |

2 | FlexLayout and PinLayout Performance 3 |

4 | 5 | 6 |

FlexLayout Examples

7 | 8 | The FlexLayout's Example exposes some usage example of FlexLayout. 9 | 10 | The Example App is available in 2 versions: 11 | 12 | * [SPM (using Swift Package Manager)](https://github.com/layoutBox/FlexLayout/tree/master/Example/SPM) 13 | * [Cocoapods](https://github.com/layoutBox/FlexLayout/tree/master/Example/cocoapods) 14 | 15 | ### Running the SPM (Swift Package Manager) Example app 16 | 1. Open the Xcode project `Example/SPM/FlexLayoutSample-SPM.xcodeproj`. 17 | 3. Select the `FlexLayoutSample-SPM` target. 18 | 4. Run the app on your device or simulator. 19 | 20 |
21 | 22 | ### Running the Cocoapods Example app 23 | 1. Do a `pod install` from the `Example/cocoapods` directory. 24 | 2. Open the newly generated `FlexLayout.xcworkspace` Xcode workspace. 25 | 3. Select the `FlexLayoutSample` target. 26 | 4. Run the app on your device or simulator. 27 | 28 |
29 | 30 | ## Intro Example 31 | FlexLayout introduction example. 32 | [Source code](https://github.com/layoutBox/FlexLayout/blob/master/Example/FlexLayoutSample/UI/Examples/Intro/IntroView.swift) 33 | 34 | 35 | 36 | 37 | ## Ray Wenderlich Yoga Tutorial 38 | An implementation of the [Ray Wenderlich Yoga Tutorial](https://www.raywenderlich.com/161413/yoga-tutorial-using-cross-platform-layout-engine). This example is the most complete one. 39 | [Source code](https://github.com/layoutBox/FlexLayout/blob/master/Example/FlexLayoutSample/UI/Examples/RaywenderlichTutorial) 40 | 41 | 42 | 43 | ## UITableView with variable size cells. 44 | This example show how FlexLayout can be used to layout UITableView cells that have variables sizes. 45 | [Source code](https://github.com/layoutBox/FlexLayout/blob/master/Example/FlexLayoutSample/UI/Examples/TableViewExample) 46 | 47 | 48 | 49 | ## UICollectionView with variable size cells 50 | This example show how FlexLayout can be used to layout UICollectionView cells that have variables sizes. 51 | [Source code](https://github.com/layoutBox/FlexLayout/blob/master/Example/FlexLayoutSample/UI/Examples/CollectionViewExample) 52 | 53 | 54 | 55 | 56 | ## Yoga's examples Implementation 57 | 58 | Implementation of all [Yoga's examples](https://facebook.github.io/yoga/) 59 | 60 | | C | | [Source code](https://github.com/layoutBox/FlexLayout/blob/master/Example/FlexLayoutSample/UI/Examples/YogaExampleA/YogaExampleAView.swift) | 61 | |---------|:-:|:-:| 62 | | Obj-C | | [Source code](https://github.com/layoutBox/FlexLayout/blob/master/Example/FlexLayoutSample/UI/Examples/YogaExampleB/YogaExampleBView.swift) | 63 | | Java | | [Source code](https://github.com/layoutBox/FlexLayout/blob/master/Example/FlexLayoutSample/UI/Examples/YogaExampleC/YogaExampleCView.swift) | 64 | | C# | | [Source code](https://github.com/layoutBox/FlexLayout/blob/master/Example/FlexLayoutSample/UI/Examples/YogaExampleD/YogaExampleDView.swift) | 65 | | Android | | [Source code](https://github.com/layoutBox/FlexLayout/blob/master/Example/FlexLayoutSample/UI/Examples/YogaExampleE/YogaExampleEView.swift) | 66 | -------------------------------------------------------------------------------- /docs_markdown/images/axis-column.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/axis-column.png -------------------------------------------------------------------------------- /docs_markdown/images/axis-row.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/axis-row.png -------------------------------------------------------------------------------- /docs_markdown/images/examples/flexlayout_example_collectionview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/examples/flexlayout_example_collectionview.png -------------------------------------------------------------------------------- /docs_markdown/images/examples/flexlayout_exampleapp_intro_all.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/examples/flexlayout_exampleapp_intro_all.png -------------------------------------------------------------------------------- /docs_markdown/images/examples/flexlayout_exampleapp_intro_landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/examples/flexlayout_exampleapp_intro_landscape.png -------------------------------------------------------------------------------- /docs_markdown/images/examples/flexlayout_exampleapp_intro_portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/examples/flexlayout_exampleapp_intro_portrait.png -------------------------------------------------------------------------------- /docs_markdown/images/examples/flexlayout_exampleapp_ray_wenderlich_tutorial.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/examples/flexlayout_exampleapp_ray_wenderlich_tutorial.png -------------------------------------------------------------------------------- /docs_markdown/images/examples/flexlayout_exampleapp_uitableview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/examples/flexlayout_exampleapp_uitableview.png -------------------------------------------------------------------------------- /docs_markdown/images/examples/flexlayout_exampleapp_yoga_android.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/examples/flexlayout_exampleapp_yoga_android.png -------------------------------------------------------------------------------- /docs_markdown/images/examples/flexlayout_exampleapp_yoga_c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/examples/flexlayout_exampleapp_yoga_c.png -------------------------------------------------------------------------------- /docs_markdown/images/examples/flexlayout_exampleapp_yoga_csharp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/examples/flexlayout_exampleapp_yoga_csharp.png -------------------------------------------------------------------------------- /docs_markdown/images/examples/flexlayout_exampleapp_yoga_java.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/examples/flexlayout_exampleapp_yoga_java.png -------------------------------------------------------------------------------- /docs_markdown/images/examples/flexlayout_exampleapp_yoga_objc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/examples/flexlayout_exampleapp_yoga_objc.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-align-column-center.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-align-column-center.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-align-column-flexEnd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-align-column-flexEnd.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-align-column-flexStart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-align-column-flexStart.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-align-column-stretch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-align-column-stretch.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-align-row-baseline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-align-row-baseline.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-align-row-center.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-align-row-center.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-align-row-flexEnd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-align-row-flexEnd.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-align-row-flexStart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-align-row-flexStart.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-align-row-stretch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-align-row-stretch.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-align-row-stretch2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-align-row-stretch2.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-alignItems-column-center.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-alignItems-column-center.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-alignItems-column-flexEnd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-alignItems-column-flexEnd.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-alignItems-column-flexStart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-alignItems-column-flexStart.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-alignItems-column-spaceAround.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-alignItems-column-spaceAround.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-alignItems-column-spaceBetween.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-alignItems-column-spaceBetween.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-alignItems-column-stretch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-alignItems-column-stretch.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-alignItems-row-center.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-alignItems-row-center.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-alignItems-row-flexEnd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-alignItems-row-flexEnd.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-alignItems-row-flexStart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-alignItems-row-flexStart.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-alignItems-row-spaceAround.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-alignItems-row-spaceAround.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-alignItems-row-spaceBetween.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-alignItems-row-spaceBetween.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-alignItems-row-stretch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-alignItems-row-stretch.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-direction-column.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-direction-column.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-direction-columnReverse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-direction-columnReverse.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-direction-row.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-direction-row.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-direction-rowReverse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-direction-rowReverse.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-justify-column-center.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-justify-column-center.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-justify-column-flexend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-justify-column-flexend.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-justify-column-flexstart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-justify-column-flexstart.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-justify-column-spacearound.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-justify-column-spacearound.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-justify-column-spacebetween.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-justify-column-spacebetween.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-justify-column-spaceevenly.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-justify-column-spaceevenly.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-justify-row-center.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-justify-row-center.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-justify-row-flexend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-justify-row-flexend.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-justify-row-flexstart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-justify-row-flexstart.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-justify-row-spacearound.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-justify-row-spacearound.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-justify-row-spacebetween.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-justify-row-spacebetween.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-justify-row-spaceevenly.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-justify-row-spaceevenly.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-logo-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-logo-2.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-logo-text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-logo-text.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-wrap-column-nowrap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-wrap-column-nowrap.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-wrap-column-wrap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-wrap-column-wrap.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-wrap-column-wrapReverse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-wrap-column-wrapReverse.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-wrap-row-nowrap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-wrap-row-nowrap.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-wrap-row-wrap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-wrap-row-wrap.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout-wrap-row-wrapReverse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout-wrap-row-wrapReverse.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout_example_column_center.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout_example_column_center.png -------------------------------------------------------------------------------- /docs_markdown/images/flexlayout_plus_pinlayout_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/flexlayout_plus_pinlayout_small.png -------------------------------------------------------------------------------- /docs_markdown/images/pinlayout_plus_flexlayout_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/pinlayout_plus_flexlayout_small.png -------------------------------------------------------------------------------- /docs_markdown/images/pinlayout_plus_flexlayout_smaller.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/FlexLayout/fe74d5afb3c12d1d6e4dcb7595f381a3aac4229e/docs_markdown/images/pinlayout_plus_flexlayout_smaller.png -------------------------------------------------------------------------------- /fastlane/Fastfile: -------------------------------------------------------------------------------- 1 | # Change the syntax highlighting to Ruby 2 | # All lines starting with a # are ignored when running fastlane 3 | 4 | # If you want to automatically update fastlane if a new version is available: 5 | # update_fastlane 6 | 7 | # This is the minimum version number required. 8 | # Update this, if you use features of a newer version 9 | fastlane_version '2.29.0' 10 | 11 | default_platform :ios 12 | skip_docs 13 | 14 | platform :ios do 15 | before_all do 16 | end 17 | 18 | lane :install do 19 | bundle_install 20 | 21 | cocoapods( 22 | use_bundle_exec: true, 23 | try_repo_update_on_error: true 24 | ) 25 | end 26 | 27 | lane :build do 28 | swiftlint( 29 | mode: :lint, 30 | config_file: '.swiftlint.yml', 31 | executable: 'Pods/SwiftLint/swiftlint', 32 | ignore_exit_status: true 33 | ) 34 | 35 | # FlexLayout 36 | xcodebuild( 37 | workspace: 'FlexLayout.xcworkspace', 38 | scheme: 'FlexLayoutInner', 39 | configuration: 'Release', 40 | build: true, 41 | clean: true, 42 | destination: 'platform=iOS Simulator,name=iPhone 15,OS=17.2' 43 | ) 44 | 45 | # FlexLayoutSample from FlexLayout.xcworkspace 46 | xcodebuild( 47 | workspace: 'FlexLayout.xcworkspace', 48 | scheme: 'FlexLayoutSample', 49 | configuration: 'Release', 50 | build: true, 51 | # clean: true, 52 | destination: 'platform=iOS Simulator,name=iPhone 15,OS=17.2' 53 | ) 54 | 55 | # Example SPM (Swift Package Manager) 56 | xcodebuild( 57 | project: 'Example/SPM/FlexLayoutSample-SPM.xcodeproj', 58 | scheme: 'FlexLayoutSample-SPM', 59 | configuration: 'Release', 60 | build: true, 61 | clean: true, 62 | destination: 'platform=iOS Simulator,name=iPhone 15,OS=17.2' 63 | ) 64 | end 65 | 66 | lane :tests do 67 | scan(scheme: 'FlexLayoutInner', workspace: 'FlexLayout.xcworkspace', device: 'iPhone 15') 68 | end 69 | 70 | lane :doc do 71 | jazzy 72 | end 73 | 74 | lane :travis do 75 | install 76 | tests 77 | build 78 | # pod_lib_lint(allow_warnings: true, verbose: false) 79 | end 80 | 81 | lane :deploy do 82 | ensure_git_branch 83 | version = version_bump_podspec(path: 'FlexLayout.podspec') 84 | git_commit(path: ['./FlexLayout.podspec'], message: "Bumped to version #{version}") 85 | push_to_git_remote(remote_branch: 'master', force: false, tags: true) 86 | changelog = changelog_from_git_commits 87 | github_release = set_github_release( 88 | repository_name: 'layoutBox/FlexLayout', 89 | api_token: ENV['GITHUB_TOKEN'], 90 | name: version, 91 | tag_name: version, 92 | description: changelog, 93 | commitish: 'master' 94 | ) 95 | sh('git fetch --tags') 96 | pod_push(allow_warnings: true, verbose: true) 97 | end 98 | end 99 | --------------------------------------------------------------------------------