{"id":13995419,"url":"https://github.com/composed-swift/ComposedLayouts","last_synced_at":"2025-07-22T21:33:02.605Z","repository":{"id":113147833,"uuid":"241958119","full_name":"composed-swift/ComposedLayouts","owner":"composed-swift","description":"A Swift framework that provides conveniences for using Composed with UICollectionViewCompositionalLayout and UICollectionViewFlowLayout.","archived":false,"fork":false,"pushed_at":"2020-08-25T17:00:40.000Z","size":153,"stargazers_count":2,"open_issues_count":1,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-11-29T17:38:35.742Z","etag":null,"topics":["composed","composition","compositional-layouts","protocol-oriented-programming","spm","swift","swift-package-manager"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/composed-swift.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"License.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2020-02-20T18:22:01.000Z","updated_at":"2023-04-14T02:31:58.000Z","dependencies_parsed_at":null,"dependency_job_id":"417f6b69-9b84-4ee1-91d3-baf8a5c18718","html_url":"https://github.com/composed-swift/ComposedLayouts","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/composed-swift/ComposedLayouts","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/composed-swift%2FComposedLayouts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/composed-swift%2FComposedLayouts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/composed-swift%2FComposedLayouts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/composed-swift%2FComposedLayouts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/composed-swift","download_url":"https://codeload.github.com/composed-swift/ComposedLayouts/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/composed-swift%2FComposedLayouts/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266578636,"owners_count":23951148,"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","status":"online","status_checked_at":"2025-07-22T02:00:09.085Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["composed","composition","compositional-layouts","protocol-oriented-programming","spm","swift","swift-package-manager"],"created_at":"2024-08-09T14:03:23.821Z","updated_at":"2025-07-22T21:33:02.302Z","avatar_url":"https://github.com/composed-swift.png","language":"Swift","readme":"\u003cimg src=\"composed.png\" width=20%/\u003e\n\n**ComposedLayouts** provides conveniences for using [Composed](http://github.com/composed-swift/composed) with `UICollectionViewCompositionalLayout` and `UICollectionViewFlowLayout`.\n\nSince its designed primarily with `UICollectionView` in mind – it includes 2 main types:\n\n```swift\nCollectionCompositionalLayoutHandler\nCollectionFlowLayoutHandler\n```\n\nHowever each has slightly different needs and therefore different requirements. Lets take a look at how we can work with each of them and _why_ we would want to.\n\n##  Compositional Layout\n\n`UICollectionViewCompositionalLayout` is generally the preferred layout to use, however if you need to support iOS \u003c13 then you're out of luck, as such checkout the flow layout example below.\n\nIf you _can_ use the latest and greatest, then lets take a look at how you can get started:\n\n```swift\nlet coordinator = CollectionCoordinator(collectionView: collectionView, sectionProvider: provider)\n\n// we can use a convenience initializer to instantiate our layout, this takes care of all the glue-work for us.\nlet layout = UICollectionViewCompositionalLayout(coordinator: coordinator)\n\n// finally just apply our layout\ncollectionView.setCollectionViewLayout(layout, animated: false)\n```\n\nNow we just need to conform our `Section` to  `CollectionCompositionalLayoutHandler`:\n\n```swift\nextension ContactsSection: CollectionCompositionalLayoutHandler {\n\n    func compositionalLayoutSection(environment: NSCollectionLayoutEnvironment) -\u003e NSCollectionLayoutSection? {\n        // return our layout section\n    }\n\n}\n```\n\nThat's it! Now we can use this section inside any collection view that's using a compositional layout and know that it will look right at all times ;)\n\n## Flow Layout\n\nIf you're using a flow layout you'll know that one of the toughest parts of working with one is building a simple table/column layout. Its not that it can't be done, but there are tiny caveates that you need to be aware of. This library attempts to remove some of those caveats and to allow you to focus on the important parts of your code instead.\n\nFirst off, you can assign your layout however you want, even leave your code as is for the moment. Composed imposes no requires on either layout, but it does provide conveniences where possible.\n\nSo similary to how we'd work with a traditional approach, we simply need to conform our `Section` to `CollectionFlowLayoutHandler`:\n\n```swift\nextension ContactsSection: CollectionFlowLayoutHandler {\n\n    func layoutMetrics(suggested: CollectionFlowLayoutMetrics, environment: CollectionFlowLayoutEnvironment) -\u003e CollectionFlowLayoutMetrics {\n        var metrics = CollectionFlowLayoutMetrics()\n        metrics.contentInsets = .init(top: 20, left: 20, bottom: 20, right: 20)\n        metrics.minimumInteritemSpacing = 10\n        return metrics \n    }\n\n    func sizeForItem(at index: Int, suggested: CGSize, metrics: CollectionFlowLayoutMetrics, environment: CollectionFlowLayoutEnvironment) -\u003e CGSize {\n        // return a size for our cell\n    }\n\n}\n```\n\nNow, there are a few conveniences we can see here:\n\n1. The `suggested` value allows us to passthrough the inherited value from UIKit or use as a reference\n2. The `metrics` value provides us with all the metrics for the current section\n3. The `environment` value includes additional values like the size of our `collectionView` and the current `traitCollection`\n\nUsing this information we should be able to more conveniently calculate our cell size.\n\n## Sizing Strategy\n\nWhat is we wanted columns though? We have enough data to calculate that but its such a common problem, surely Composed could solve this for you right? Right!\n\nIntroducing `CollectionFlowLayoutSizingStrategy`.\n\nThis is a convenience type that takes an optional `prototype` view, `columnCount`, `sizingMode` and the `metrics`, which you can then use to automatically calculate the appropriate size for each of your cells for you.\n\nIn order to use this however we need to refactor our code above slightly. We replace the manual sizing method, with a convenience instead:\n\n```swift\n    func sizingStrategy(at index: Int, metrics: CollectionFlowLayoutMetrics, environment: CollectionFlowLayoutEnvironment) -\u003e CollectionFlowLayoutSizingStrategy? {\n        return CollectionFlowLayoutSizingStrategy(prototype: .fromNib, columnCount: 3, sizingMode: .automatic(isUniform: true), metrics: metrics)\n    }\n```\n\nThat's it! Our flow layout will now size our 3 columns automatically without any additional code.\n\n\u003e Note: `isUniform: true` this tells the strategy to only size the first cell and then return that size for all cells. Its such a common scenario we baked it in to improve performance in those cases.\n","funding_links":[],"categories":["Swift"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcomposed-swift%2FComposedLayouts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcomposed-swift%2FComposedLayouts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcomposed-swift%2FComposedLayouts/lists"}