diff --git a/Examples/Examples-iOS/IGListKitExamples.xcodeproj/project.pbxproj b/Examples/Examples-iOS/IGListKitExamples.xcodeproj/project.pbxproj index 0db9bbfe3..1e55c84ad 100644 --- a/Examples/Examples-iOS/IGListKitExamples.xcodeproj/project.pbxproj +++ b/Examples/Examples-iOS/IGListKitExamples.xcodeproj/project.pbxproj @@ -79,6 +79,8 @@ 576D20102B2CEC4E0012C5B8 /* GridComposableSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 576D200F2B2CEC4E0012C5B8 /* GridComposableSectionController.swift */; }; 576D20122B2CF04F0012C5B8 /* UserComposableSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 576D20112B2CF04F0012C5B8 /* UserComposableSectionController.swift */; }; 576D20142B2CF15C0012C5B8 /* GridItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 576D20132B2CF15C0012C5B8 /* GridItem.swift */; }; + 576D20162B2CF1A50012C5B8 /* HorizontalCardsSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 576D20152B2CF1A50012C5B8 /* HorizontalCardsSection.swift */; }; + 576D20182B2CF24F0012C5B8 /* HorizontalComposableSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 576D20172B2CF24F0012C5B8 /* HorizontalComposableSectionController.swift */; }; 821BC4B61DB8B3DC00172ED0 /* StoryboardViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 821BC4B51DB8B3DC00172ED0 /* StoryboardViewController.swift */; }; 821BC4B81DB8B48300172ED0 /* StoryboardCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 821BC4B71DB8B48300172ED0 /* StoryboardCell.swift */; }; 821BC4BA1DB8B61200172ED0 /* StoryboardLabelSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 821BC4B91DB8B61200172ED0 /* StoryboardLabelSectionController.swift */; }; @@ -245,6 +247,8 @@ 576D200F2B2CEC4E0012C5B8 /* GridComposableSectionController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GridComposableSectionController.swift; sourceTree = ""; }; 576D20112B2CF04F0012C5B8 /* UserComposableSectionController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserComposableSectionController.swift; sourceTree = ""; }; 576D20132B2CF15C0012C5B8 /* GridItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GridItem.swift; sourceTree = ""; }; + 576D20152B2CF1A50012C5B8 /* HorizontalCardsSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HorizontalCardsSection.swift; sourceTree = ""; }; + 576D20172B2CF24F0012C5B8 /* HorizontalComposableSectionController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HorizontalComposableSectionController.swift; sourceTree = ""; }; 821BC4B51DB8B3DC00172ED0 /* StoryboardViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StoryboardViewController.swift; sourceTree = ""; }; 821BC4B71DB8B48300172ED0 /* StoryboardCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StoryboardCell.swift; sourceTree = ""; }; 821BC4B91DB8B61200172ED0 /* StoryboardLabelSectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StoryboardLabelSectionController.swift; sourceTree = ""; }; @@ -500,6 +504,7 @@ 296DD75C1DD21ADA00206780 /* SelectionModel.swift */, 2991F91D1D7BB30C00B0C58F /* User.swift */, 576D20132B2CF15C0012C5B8 /* GridItem.swift */, + 576D20152B2CF1A50012C5B8 /* HorizontalCardsSection.swift */, EB02899E202A11DF007E17D5 /* RemodelGeneratedModels */, 2926585C1E74A0360041B56D /* ViewModels */, ); @@ -520,6 +525,7 @@ 576D200D2B2CE9EC0012C5B8 /* ExpandableComposableSectionController.swift */, 576D200F2B2CEC4E0012C5B8 /* GridComposableSectionController.swift */, 576D20112B2CF04F0012C5B8 /* UserComposableSectionController.swift */, + 576D20172B2CF24F0012C5B8 /* HorizontalComposableSectionController.swift */, ); path = "With Composable Layout"; sourceTree = ""; @@ -823,6 +829,7 @@ 56C05B691E49B2120026DB39 /* ObjcDemoViewController.m in Sources */, 2961B3B01D68B28E001C9451 /* SearchCell.swift in Sources */, 2942FF8C1D9F39E00015D24B /* DemoSectionController.swift in Sources */, + 576D20162B2CF1A50012C5B8 /* HorizontalCardsSection.swift in Sources */, 2981BA351DB868A500A987F9 /* ImageCell.swift in Sources */, 2942FF931D9F39E00015D24B /* SearchSectionController.swift in Sources */, 297546FA1DD25384002A6F89 /* FullWidthSelfSizingCell.swift in Sources */, @@ -863,6 +870,7 @@ 2991F9281D7BB9EC00B0C58F /* EmbeddedCollectionViewCell.swift in Sources */, 13DF016A1F9D9F600092A320 /* ReorderableViewController.swift in Sources */, 576D20142B2CF15C0012C5B8 /* GridItem.swift in Sources */, + 576D20182B2CF24F0012C5B8 /* HorizontalComposableSectionController.swift in Sources */, 2942FF8F1D9F39E00015D24B /* GridSectionController.swift in Sources */, 821BC4B81DB8B48300172ED0 /* StoryboardCell.swift in Sources */, 56C05B781E49B3A50026DB39 /* PhotoCell.m in Sources */, diff --git a/Examples/Examples-iOS/IGListKitExamples/Models/HorizontalCardsSection.swift b/Examples/Examples-iOS/IGListKitExamples/Models/HorizontalCardsSection.swift new file mode 100644 index 000000000..2ac02d59b --- /dev/null +++ b/Examples/Examples-iOS/IGListKitExamples/Models/HorizontalCardsSection.swift @@ -0,0 +1,39 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import IGListKit +import Foundation + +final class HorizontalCardsSection: NSObject { + + let cardCount: Int + private(set) var items: [String] = [] + + init(cardCount: Int) { + self.cardCount = cardCount + super.init() + self.items = computeItems() + } + + private func computeItems() -> [String] { + return [Int](1...cardCount).map { + String(describing: $0) + } + } +} + +extension HorizontalCardsSection: ListDiffable { + + func diffIdentifier() -> NSObjectProtocol { + return self + } + + func isEqual(toDiffableObject object: ListDiffable?) -> Bool { + return self === object ? true : self.isEqual(object) + } + +} diff --git a/Examples/Examples-iOS/IGListKitExamples/SectionControllers/With Composable Layout/HorizontalComposableSectionController.swift b/Examples/Examples-iOS/IGListKitExamples/SectionControllers/With Composable Layout/HorizontalComposableSectionController.swift new file mode 100644 index 000000000..9eaba5b75 --- /dev/null +++ b/Examples/Examples-iOS/IGListKitExamples/SectionControllers/With Composable Layout/HorizontalComposableSectionController.swift @@ -0,0 +1,56 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import IGListKit +import UIKit + +final class HorizontalComposableSectionController: ListSectionController, CompositionLayoutCapable { + + private var object: HorizontalCardsSection? + + override func numberOfItems() -> Int { + return object?.cardCount ?? 0 + } + + override func sizeForItem(at index: Int) -> CGSize { + // Size handled by cell + return CGSizeZero + } + + override func cellForItem(at index: Int) -> UICollectionViewCell { + let cell: CompositionLayoutCell = collectionContext.dequeueReusableCell(for: self, at: index) + cell.text = object?.items[index] ?? "undefined" + cell.contentView.backgroundColor = UIColor.secondarySystemBackground + cell.contentView.layer.cornerRadius = 8 + return cell + } + + override func didUpdate(to object: Any) { + self.object = object as? HorizontalCardsSection + } + + // MARK: CompositionLayoutCapable + + func collectionViewSectionLayout(layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? { + // Item + let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), + heightDimension: .fractionalHeight(1.0)) + let item = NSCollectionLayoutItem(layoutSize: itemSize) + item.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 16) + + // Group + let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(160)) + let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item]) + + // Section + let section = NSCollectionLayoutSection(group: group) + section.contentInsets = NSDirectionalEdgeInsets(top: 16, leading: 16, bottom: 16, trailing: 16) + section.orthogonalScrollingBehavior = .continuousGroupLeadingBoundary + return section + } + +} diff --git a/Examples/Examples-iOS/IGListKitExamples/ViewControllers/CompositionLayoutViewController.swift b/Examples/Examples-iOS/IGListKitExamples/ViewControllers/CompositionLayoutViewController.swift index 05d83a9d6..a515ac756 100644 --- a/Examples/Examples-iOS/IGListKitExamples/ViewControllers/CompositionLayoutViewController.swift +++ b/Examples/Examples-iOS/IGListKitExamples/ViewControllers/CompositionLayoutViewController.swift @@ -27,8 +27,10 @@ final class CompositionLayoutViewController: UIViewController, ListAdapterDataSo "Maecenas faucibus mollis interdum. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit.", GridItem(color: UIColor(red: 237 / 255.0, green: 73 / 255.0, blue: 86 / 255.0, alpha: 1), itemCount: 6), User(pk: 2, name: "Ryan Olson", handle: "ryanolsonk"), + HorizontalCardsSection(cardCount: 10), "Praesent commodo cursus magna, vel scelerisque nisl consectetur et.", User(pk: 4, name: "Oliver Rickard", handle: "ocrickard"), + HorizontalCardsSection(cardCount: 2), GridItem(color: UIColor(red: 56 / 255.0, green: 151 / 255.0, blue: 240 / 255.0, alpha: 1), itemCount: 5), "Nullam quis risus eget urna mollis ornare vel eu leo. Praesent commodo cursus magna, vel scelerisque nisl consectetur et.", User(pk: 3, name: "Jesse Squires", handle: "jesse_squires"), @@ -80,6 +82,8 @@ final class CompositionLayoutViewController: UIViewController, ListAdapterDataSo return GridComposableSectionController() case is User: return UserComposableSectionController() + case is HorizontalCardsSection: + return HorizontalComposableSectionController() default: return ListSectionController() }