{"id":1302,"url":"https://github.com/k-o-d-e-n/CGLayout","last_synced_at":"2025-08-06T13:32:54.280Z","repository":{"id":41142751,"uuid":"104526790","full_name":"k-o-d-e-n/CGLayout","owner":"k-o-d-e-n","description":"Powerful autolayout framework, that can manage UIView(NSView), CALayer and not rendered views. Not Apple Autolayout wrapper. Provides placeholders. Linux support.","archived":false,"fork":false,"pushed_at":"2022-06-28T20:37:18.000Z","size":5355,"stargazers_count":44,"open_issues_count":0,"forks_count":6,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-12-09T04:41:53.475Z","etag":null,"topics":["anchor","autolayout-framework","calayer","constraints","frame","ios","layout","layout-engine","linux","macos","nsview","placeholder","snapshot","swift","swiftui","tvos","ui","uikit","uiview","uiview-extension"],"latest_commit_sha":null,"homepage":"https://k-o-d-e-n.github.io/CGLayout/","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/k-o-d-e-n.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-09-22T23:29:34.000Z","updated_at":"2023-09-13T14:41:05.000Z","dependencies_parsed_at":"2022-08-21T02:50:25.638Z","dependency_job_id":null,"html_url":"https://github.com/k-o-d-e-n/CGLayout","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k-o-d-e-n%2FCGLayout","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k-o-d-e-n%2FCGLayout/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k-o-d-e-n%2FCGLayout/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k-o-d-e-n%2FCGLayout/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/k-o-d-e-n","download_url":"https://codeload.github.com/k-o-d-e-n/CGLayout/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228905518,"owners_count":17989779,"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":["anchor","autolayout-framework","calayer","constraints","frame","ios","layout","layout-engine","linux","macos","nsview","placeholder","snapshot","swift","swiftui","tvos","ui","uikit","uiview","uiview-extension"],"created_at":"2024-01-05T20:15:43.324Z","updated_at":"2024-12-09T14:31:05.242Z","avatar_url":"https://github.com/k-o-d-e-n.png","language":"Swift","funding_links":[],"categories":["Layout","Libs","Layout [🔝](#readme)","uiview-extension"],"sub_categories":["Other Hardware","Layout","Other free courses"],"readme":"# CGLayout\n\n# [DEPRECATED] Replaced with new implementation - [LayoutUI](https://github.com/k-o-d-e-n/LayoutUI)\n\n[![Version](https://img.shields.io/cocoapods/v/CGLayout.svg?style=flat)](http://cocoapods.org/pods/CGLayout)\n[![License](https://img.shields.io/cocoapods/l/CGLayout.svg?style=flat)](http://cocoapods.org/pods/CGLayout)\n[![Platform](https://img.shields.io/cocoapods/p/CGLayout.svg?style=flat)](http://cocoapods.org/pods/CGLayout)\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"Resources/logo.png\"\u003e\n\u003c/p\u003e\n\nPowerful autolayout framework, that can manage UIView(NSView), CALayer and not rendered views. Has cross-hierarchy coordinate space. Implementation performed on rect-based constraints.   \nFast, asynchronous, declarative, cacheable, extensible. Supported iOS, macOS, tvOS, Linux.\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"Resources/benchmark_result.png\"\u003e\n\u003c/p\u003e\nPerformed by [LayoutBenchmarkFramework](https://github.com/lucdion/LayoutFrameworkBenchmark)\n\n## Quick tutorial\n\nLayout with `CGLayout` built using layout-blocks. To combine blocks into single unit use `LayoutScheme` entity (or other entities that has suffix `Scheme`).\n```swift\nlet subviewsScheme = LayoutScheme(blocks: [\n// ... layout blocks\n])\n```\nTo define block for \"view\" element use `LayoutBlock` entity, or just use convenience getter methods  `func layoutBlock(with:constraints:)`.\n```swift\ntitleLabel.layoutBlock(\n    with: Layout(x: .center(), y: .top(5), width: .scaled(1), height: .fixed(120)),\n    constraints: [\n        logoImageView.layoutConstraint(for: [.bottom(.limit(on: .inner))])\n    ]\n)\n/// or using anchors\ntitleLabel.layoutBlock(\n    with: Layout(x: .center(), y: .top(5), width: .scaled(1), height: .fixed(120)),\n    constraints: { anchors in\n        anchors.top.equal(to: logoImageView.layoutAnchors.bottom)\n    }\n)\n```\nFor understanding how need to built layout block, let's see layout process in `LayoutBlock`. \nFor example we have this configuration:\n```swift\nLayoutBlock(\n    with: layoutElement, \n    layout: Layout(x: .left(10), y: .top(10), width: .boxed(10), height: .boxed(10)),\n    constraints: [\n        element1.layoutConstraint(for: [\n            .bottom(.limit(on: .outer)), .right(.limit(on: .inner))\n        ]),\n        element2.layoutConstraint(for: [\n            .right(.limit(on: .outer)), .bottom(.limit(on: .inner))\n        ])\n    ]\n)\n```\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"Resources/layout1.png\"\u003e\n\u003cimg src=\"Resources/layout2.png\"\u003e\n\u003c/p\u003e\nYou have to carefully approach the creation of blocks, because anchors and based on them constraints not have priority and is applying sequentially.  \nConstraints should operate actual frames, therefore next layout block must have constraints with \"views\", that will not change frame.\n\nLayout anchors are limiters, that is oriented on frame properties (such as sides, size, position).  \nAny side-based anchors have three base implementations: alignment, limitation(cropping), pulling. Each this implementation have dependency on working space: inner and outer.  \nSize-based anchors are represented by two implementations: size, insets.  \nAll layout anchors you can find in `enum LayoutAnchor`.\n\nTo create associated layout constraints use `protocol LayoutConstraintProtocol`.  \nFramework provides such default implementations:\n- `LayoutConstraint`: simple associated constraint that uses `var frame` of passed element to constrain source rect. Use him to build dependency on external workspace.\n- `AdjustLayoutConstraint`: associated constraint to adjust size of source space. Only elements conform to `protocol AdjustableLayoutElement`  can use it.\n- `ContentLayoutConstraint`: associated constraint that uses internal bounds to constrain, defined in 'layoutBounds' property of `protocol LayoutElement`. Use it if you need to create dependency on internal workspace. For example, element inside `UIScrollView`.\n- `AnonymConstraint`: constraint to restrict source space independently from external environment.\n- `MutableLayoutConstraint`: Layout constraint that creates possibility to change active state.  \nYou can find all this constraints through convenience functions in related elements. Use him to build layout blocks.\n\nIn common case, adjust constraints should be apply after any other constraints (but not always). \n```swift\nweatherLabel.layoutBlock(\n    with: Layout(x: .left(10), y: .top(), width: .scaled(1), height: .scaled(1)),\n    constraints: [\n        weatherImageView.layoutConstraint(for: [.top(.limit(.inner)), .right(.limit(.outer)), .height()]),\n        weatherLabel.adjustLayoutConstraint(for: [.width()])\n    ]\n)\n```\n\n```swift\nAnonymConstraint(anchors: [\n    Inset(UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 15))\n])\n```\n\nFor implementing custom layout entities and save strong typed code, use `static func build(_ base: Conformed) -\u003e Self` method.\n\nEach layout-block has methods for layout, take snapshot and applying snapshot.\nConsequently you may use layout-blocks for direct layout, background layout and cached layout:\n```swift\n// layout directly\nlayoutScheme.layout()\n\n// layout in background\nlet bounds = view.bounds\n    DispatchQueue.global(qos: .background).async {\n    let snapshot = self.layoutScheme.snapshot(for: bounds)\n    DispatchQueue.main.sync {\n        self.layoutScheme.apply(snapshot: snapshot)\n    }\n}\n\n// cached layout\nif UIDevice.current.orientation.isPortrait, let snapshot = portraitSnapshot {\n    layoutScheme.apply(snapshot: snapshot)\n} else if UIDevice.current.orientation.isLandscape, let snapshot = landscapeSnapshot {\n    layoutScheme.apply(snapshot: snapshot)\n} else {\n    layoutScheme.layout()\n}\n```\n\nTypical implementation `sizeThatFits(_:)` method\n\n```swift\nfunc sizeThatFits(_ size: CGSize) -\u003e CGSize {\n    let sourceRect = CGRect(origin: .zero, size: size)\n    let snapshot = scheme.snapshot(for: sourceRect)\n    return snapshot.frame\n}\n```\n\n### LayoutGuide\n\nFramework provides `LayoutGuide` as analogue `UILayoutGuide`. It has possible to generate views and add them to hierarchy.  \n`LayoutGuide` can used as invisible limiter and also as layout container.  \nDefault layout containers:  \n- `StackLayoutGuide` - simple implementation of stack.  \n- `ScrollLayoutGuide` - has similar interface with `UIScrollView`. By use him we can enable scrolling absolutely everywhere.  \n- `LayoutPlaceholder` - single element container that can load view lazily. Has default implementations for `CALayer` - `LayerPlaceholder` and `UIView` - `ViewPlaceholder`.  \n- `UIViewPlaceholder` - single element container based on `UILayoutGuide`.  \n\n`UILayouGuide` also adopts `LayoutElement` protocol. Therefore you can safely build constraints based on `UIView.safeAreaLayoutGuide` and others.\n\n### RTL\nTo enable Righ-to-Left mode use global configuration:\n```swift\nCGLConfiguration.default.isRTLMode = true\n```\n\nFor more details, see documentation and example project.\n\n## Code documentation\n\nSee [here](https://k-o-d-e-n.github.io/CGLayout/)\n\n## Example\n\n### macOS, iOS, tvOS\nTo run the example project, clone the repo, and run `pod install` from the Example directory first.\n\n### Linux\nTo run the example project, clone the repo, and run `swift run` from the `linux_example` directory first.\n\n## Requirements\n\nSwift 5\n\n## Installation\n\nCGLayout is available through [CocoaPods](http://cocoapods.org). To install\nit, simply add the following line to your Podfile:\n\n```ruby\npod \"CGLayout\"\n```\n\n## Contributing\n\nI will be happy your feedback, advices and pull requests. For more information read [here](https://github.com/k-o-d-e-n/CGLayout/blob/master/CONTRIBUTING.md) \n\n## Author\n\nDenis Koryttsev\nEmail: koden.u8800@gmail.com\nTwitter: https://twitter.com/K_o_D_e_N\n\n## License\n\nCGLayout is available under the MIT license. See the LICENSE file for more info.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fk-o-d-e-n%2FCGLayout","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fk-o-d-e-n%2FCGLayout","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fk-o-d-e-n%2FCGLayout/lists"}