{"id":1277,"url":"https://github.com/evan-liu/FormationLayout","last_synced_at":"2025-07-30T20:33:01.688Z","repository":{"id":33914333,"uuid":"37632784","full_name":"evan-liu/FormationLayout","owner":"evan-liu","description":"Yet Another Swift Auto Layout DSL","archived":false,"fork":false,"pushed_at":"2017-03-18T02:39:31.000Z","size":571,"stargazers_count":51,"open_issues_count":0,"forks_count":6,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-11-17T09:42:08.218Z","etag":null,"topics":["autolayout","swift"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/evan-liu.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-06-18T02:27:52.000Z","updated_at":"2024-03-04T04:07:40.000Z","dependencies_parsed_at":"2022-09-12T21:21:45.324Z","dependency_job_id":null,"html_url":"https://github.com/evan-liu/FormationLayout","commit_stats":null,"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evan-liu%2FFormationLayout","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evan-liu%2FFormationLayout/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evan-liu%2FFormationLayout/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evan-liu%2FFormationLayout/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/evan-liu","download_url":"https://codeload.github.com/evan-liu/FormationLayout/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228187624,"owners_count":17882335,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["autolayout","swift"],"created_at":"2024-01-05T20:15:42.773Z","updated_at":"2024-12-04T20:31:13.473Z","avatar_url":"https://github.com/evan-liu.png","language":"Swift","funding_links":[],"categories":["Layout","Libs"],"sub_categories":["Other Hardware","Other free courses","Layout"],"readme":"# FormationLayout\n\n![banner](https://github.com/evan-liu/FormationLayout/blob/master/Documentation/Doc.playground/Resources/banner.png)\n\n![Platform](https://img.shields.io/badge/platform-ios-lightgrey.svg)\n![License](https://img.shields.io/badge/license-MIT-blue.svg)\n[![CocoaPods](https://img.shields.io/cocoapods/v/FormationLayout.svg)](https://cocoapods.org/)\n[![Carthage](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)\n\n## Documentation\n \n`FormationLayout` is the top level layout class for one root view. \n\n- `FormationLayout` takes a `UIView` as its `rootView`.\n- `translatesAutoresizingMaskIntoConstraints` of `rootView` is not set to false by default but can be set in constructor.\n- `translatesAutoresizingMaskIntoConstraints` of subviews will be set to false automaticly.\n- Subviews with no `superView` will be added to `rootView` automaticly.\n \n```swift\ndemo { canvas, icon in\n    FormationLayout(rootView: canvas)[icon].center(equalTo: canvas)\n}\n ```\n \n ![FormationLayout](https://github.com/evan-liu/FormationLayout/blob/master/Documentation/Images/FormationLayout.png)\n \n### Anchors\n\nView anchors: left, right, top, bottom, leading, trailing, width, height, centerX, centerY, lastBaseline, firstBaseline, centerXWithinMargins, centerYWithinMargins\n \n- `layout[view].anchor(equalTo: view2, multiplyBy: multiplier, plus: constant)`\n  - view.anchor == view2.anchor * multiplier + constant\n- `layout[view].anchor(equalTo: anchor2, of: view2, multiplyBy: multiplier, minus: constant)`\n  - view.anchor == view2.anchor2 * multiplier - constant\n- `layout[view].anchor(greaterThanOrEqualTo: view2)`\n  - view.anchor \u003e= view2.anchor\n- `layout[view].anchor(lessThanOrEqualTo: value)` _(Only width and height)_\n  - view.anchor \u003c= value\n  \n```swift\ndemo { canvas, icon1, icon2, icon3 in\n    let layout = FormationLayout(rootView: canvas)\n    layout[icon1].top(equalTo: canvas, plus: 10).leading(equalTo: canvas, plus: 20)\n    layout[icon2].top(equalTo: icon1).leading(equalTo: .trailing, of: icon1, plus: 10)\n    layout[icon3].bottom(equalTo: canvas, minus: 10).leading(equalTo: icon1, multiplyBy: 2)\n}\n```\n\n![Anchors](https://github.com/evan-liu/FormationLayout/blob/master/Documentation/Images/Anchors.png)\n\n### Helpers\n \n- aspectRatio: `width:height`\n- size: width \u0026 height\n- center: centerX \u0026 centerY\n\n```swift\ndemo { canvas, icon1, icon2, icon3 in\n    let layout = FormationLayout(rootView: canvas)\n    layout[icon1].aspectRatio(equalTo: 1.5).width(equalTo: 30)\n    layout[icon2].size(equalTo: 30).center(equalTo: canvas, multiplyBy: 0.8)\n    layout[icon3].size(equalTo: icon2, minus: 10).center(equalTo: icon2, plus: 30)\n}\n```\n\n![Helpers](https://github.com/evan-liu/FormationLayout/blob/master/Documentation/Images/Helpers.png)\n\n### Pin\n \n`layout[view].pin(to: canvas)` will set\n \n- view.top == canvas.top\n- view.bottom == canvas.bottom\n- view.left == canvas.left\n- view.right == canvas.right\n \n`layout[view].pin(to: canvas, margin: 10)` will set\n \n- view.top == canvas.top + 10\n- view.bottom == canvas.bottom - 10\n- view.left == canvas.left + 10\n- view.right == canvas.right - 10\n\n```swift\ndemo { canvas, icon1, icon2, icon3 in\n    let layout = FormationLayout(rootView: canvas)\n    layout[icon1].pin(to: canvas, edgesWithMargin: [.top: 10, .leading: 3])\n    layout[icon2].pin(to: canvas, margin: 30)\n    layout[icon3].pin(to: canvas, edges: [.topBottom, .trailing], margin: 3)\n}\n```\n\n![Pin](https://github.com/evan-liu/FormationLayout/blob/master/Documentation/Images/Pin.png)\n\n### Abreast\n\n- layout[logo].below(topLayoutGuide, gap: 10)\n  - logo.top == topLayoutGuide.bottom + 10\n- layout[copyright].above(bottomLayoutGuide, gap: 10)\n  - copyright.bottom == bottomLayoutGuide.top - 10\n\n```swift\ndemo { canvas, icon1, icon2, icon3 in\n    let layout = FormationLayout(rootView: canvas)\n    layout[icon1].center(equalTo: canvas)\n    layout[icon2].before(icon1).above(icon1, gap: 5)\n    layout[icon3].after(icon1).below(icon1, gap: 5)\n}\n```\n\n![Abreast](https://github.com/evan-liu/FormationLayout/blob/master/Documentation/Images/Abreast.png)\n\n### Group\n \n`layout.group(view1, view2)` will create same constraints for \n \n- layout[view1]\n- layout[view2]\n\n```swift\ndemo { canvas, icon1, icon2, icon3 in\n    let layout = FormationLayout(rootView: canvas)\n    layout.group(icon1, icon2, icon3).centerY(equalTo: canvas)\n    layout[icon1].leading(equalTo: canvas, plus: 5)\n    layout[icon2].centerX(equalTo: canvas)\n    layout[icon3].trailing(equalTo: canvas, minus: 5)\n}\n```\n\n![Group](https://github.com/evan-liu/FormationLayout/blob/master/Documentation/Images/Group.png)\n\n### Condition\n \n`layout.when()` creates constraints for one condition and its `not` creates constrains for otherwise. \n\n```swift\ndemo { canvas, icon in\n    var isLoggedIn = true \n    \n    let layout = FormationLayout(rootView: canvas)\n    let loggedInLayout = layout.when { isLoggedIn }\n    \n    layout[icon].centerX(equalTo: canvas)\n    loggedInLayout[icon].top(equalTo: canvas, plus: 10)\n    loggedInLayout.not[icon].bottom(equalTo: canvas, minus: 10)\n    \n    layout.update()\n}\n```\n\n![Condition](https://github.com/evan-liu/FormationLayout/blob/master/Documentation/Images/Condition.png)\n\n`isLoggedIn = false`\n\n![ConditionNot](https://github.com/evan-liu/FormationLayout/blob/master/Documentation/Images/ConditionNot.png)\n\n### Priority\n\nAll constraints have UILayoutPriorityRequired by default.\n\n```swift\ndemo { canvas, icon in\n    let layout = FormationLayout(rootView: canvas)\n    layout[icon].centerX(equalTo: canvas).size(equalTo: 20)\n        .centerY(equalTo: canvas, at: UILayoutPriorityDefaultLow) // Try UILayoutPriorityRequired\n        .bottom(equalTo: canvas, at: UILayoutPriorityDefaultHigh)\n}\n```\n\n![PriorityLow](https://github.com/evan-liu/FormationLayout/blob/master/Documentation/Images/PriorityLow.png)\n\nUILayoutPriorityRequired: \n\n![PriorityRequired](https://github.com/evan-liu/FormationLayout/blob/master/Documentation/Images/PriorityRequired.png)\n\n## Playground\n\n- Open **Documentation/Doc.xcworkspace**.\n- Build the **FormationLayout-iOS** scheme (⌘+B).\n- Open **Doc** playground in the **Project navigator**.\n- Click \"Show Result\" button at the most right side of each `demo` line.\n\n## Install\n\n### CocoaPods \n\n```\npod 'FormationLayout', '~\u003e 0.8.5'\n```\n\n### Carthage \n\n```\ngithub \"evan-liu/FormationLayout\" \u003e= 0.8.5\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fevan-liu%2FFormationLayout","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fevan-liu%2FFormationLayout","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fevan-liu%2FFormationLayout/lists"}