diff --git a/Examples/Samples/Samples.xcodeproj/project.pbxproj b/Examples/Samples/Samples.xcodeproj/project.pbxproj index 1261f889..38fcb77e 100644 --- a/Examples/Samples/Samples.xcodeproj/project.pbxproj +++ b/Examples/Samples/Samples.xcodeproj/project.pbxproj @@ -32,6 +32,8 @@ 54CDC5D8215BBE23007D205C /* SupplementaryViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54CDC5D7215BBE23007D205C /* SupplementaryViews.swift */; }; 54EAD35B263A75EB006A36EA /* PanelLayouts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54EAD35A263A75EB006A36EA /* PanelLayouts.swift */; }; 54EAD365263A765F006A36EA /* PagePanelController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54EAD364263A765F006A36EA /* PagePanelController.swift */; }; + 54F185822BF4AD0000916F57 /* DebugListCollectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54F185812BF4AD0000916F57 /* DebugListCollectionViewController.swift */; }; + 54F185842BF4B82E00916F57 /* UnavailableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54F185832BF4B82E00916F57 /* UnavailableViewController.swift */; }; 5D82A6AD28D1843C006A44BA /* libswiftCoreGraphics.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D82A6AC28D18438006A44BA /* libswiftCoreGraphics.tbd */; }; /* End PBXBuildFile section */ @@ -76,6 +78,8 @@ 54CDC5D7215BBE23007D205C /* SupplementaryViews.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SupplementaryViews.swift; sourceTree = ""; }; 54EAD35A263A75EB006A36EA /* PanelLayouts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PanelLayouts.swift; sourceTree = ""; }; 54EAD364263A765F006A36EA /* PagePanelController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PagePanelController.swift; sourceTree = ""; }; + 54F185812BF4AD0000916F57 /* DebugListCollectionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugListCollectionViewController.swift; sourceTree = ""; }; + 54F185832BF4B82E00916F57 /* UnavailableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnavailableViewController.swift; sourceTree = ""; }; 5D82A6AC28D18438006A44BA /* libswiftCoreGraphics.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libswiftCoreGraphics.tbd; path = usr/lib/swift/libswiftCoreGraphics.tbd; sourceTree = SDKROOT; }; /* End PBXFileReference section */ @@ -97,6 +101,7 @@ children = ( 5442E23F25FC533800A26F43 /* DebugTableViewController.swift */, 5442E24925FC53C100A26F43 /* DebugTextViewController.swift */, + 54F185812BF4AD0000916F57 /* DebugListCollectionViewController.swift */, 5442E23325FC528400A26F43 /* DetailViewController.swift */, 5442E24325FC538200A26F43 /* InspectorViewController.swift */, 5442E22325FC51AF00A26F43 /* ImageViewController.swift */, @@ -106,6 +111,7 @@ 5442E22B25FC521F00A26F43 /* SettingsViewController.swift */, 5442E22F25FC525200A26F43 /* TabBarViewController.swift */, 544BC56726CC918200D0A436 /* AdaptiveLayoutTestViewController.swift */, + 54F185832BF4B82E00916F57 /* UnavailableViewController.swift */, ); path = ContentViewControllers; sourceTree = ""; @@ -247,6 +253,7 @@ 5442E23A25FC52CD00A26F43 /* ModalViewController.swift in Sources */, 5442E22425FC51AF00A26F43 /* ImageViewController.swift in Sources */, 5442E24025FC533800A26F43 /* DebugTableViewController.swift in Sources */, + 54F185822BF4AD0000916F57 /* DebugListCollectionViewController.swift in Sources */, 5442E25225FC541700A26F43 /* NestedScrollViewController.swift in Sources */, 5442E22825FC51E200A26F43 /* MultiPanelController.swift in Sources */, 546341A125C6415100CA0596 /* UseCase.swift in Sources */, @@ -257,6 +264,7 @@ 54EAD365263A765F006A36EA /* PagePanelController.swift in Sources */, 5442E24425FC538200A26F43 /* InspectorViewController.swift in Sources */, 5442E22C25FC521F00A26F43 /* SettingsViewController.swift in Sources */, + 54F185842BF4B82E00916F57 /* UnavailableViewController.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Examples/Samples/Sources/ContentViewControllers/DebugListCollectionViewController.swift b/Examples/Samples/Sources/ContentViewControllers/DebugListCollectionViewController.swift new file mode 100644 index 00000000..042878e5 --- /dev/null +++ b/Examples/Samples/Sources/ContentViewControllers/DebugListCollectionViewController.swift @@ -0,0 +1,77 @@ +// Copyright 2018 the FloatingPanel authors. All rights reserved. MIT license. + +import UIKit + +@available(iOS 14, *) +class DebugListCollectionViewController: UIViewController { + + enum Section { + case main + } + + var dataSource: UICollectionViewDiffableDataSource! = nil + var collectionView: UICollectionView! = nil + + override func viewDidLoad() { + super.viewDidLoad() + navigationItem.title = "List" + configureHierarchy() + configureDataSource() + } +} + +@available(iOS 14, *) +extension DebugListCollectionViewController { + /// - Tag: List + private func createLayout() -> UICollectionViewLayout { + var config = UICollectionLayoutListConfiguration(appearance: .insetGrouped) + config.trailingSwipeActionsConfigurationProvider = { indexPath -> UISwipeActionsConfiguration? in + return UISwipeActionsConfiguration( + actions: [UIContextualAction( + style: .destructive, + title: "Delete", + handler: { _, _, completion in + // Do nothing now + } + )] + ) + } + return UICollectionViewCompositionalLayout.list(using: config) + } +} + +@available(iOS 14, *) +extension DebugListCollectionViewController { + private func configureHierarchy() { + collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: createLayout()) + collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight] + view.addSubview(collectionView) + collectionView.delegate = self + } + private func configureDataSource() { + + let cellRegistration = UICollectionView.CellRegistration { (cell, indexPath, item) in + var content = cell.defaultContentConfiguration() + content.text = "\(item)" + cell.contentConfiguration = content + } + + dataSource = UICollectionViewDiffableDataSource(collectionView: collectionView) { + (collectionView: UICollectionView, indexPath: IndexPath, identifier: Int) -> UICollectionViewCell? in + + return collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: identifier) + } + + var snapshot = NSDiffableDataSourceSnapshot() + snapshot.appendSections([.main]) + snapshot.appendItems(Array(0..<94)) + dataSource.apply(snapshot, animatingDifferences: false) + } +} + +@available(iOS 14, *) +extension DebugListCollectionViewController: UICollectionViewDelegate { + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + collectionView.deselectItem(at: indexPath, animated: true) + } +} diff --git a/Examples/Samples/Sources/ContentViewControllers/UnavailableViewController.swift b/Examples/Samples/Sources/ContentViewControllers/UnavailableViewController.swift new file mode 100644 index 00000000..7a180952 --- /dev/null +++ b/Examples/Samples/Sources/ContentViewControllers/UnavailableViewController.swift @@ -0,0 +1,24 @@ +// Copyright 2018 the FloatingPanel authors. All rights reserved. MIT license. + +import UIKit + +class UnavailableViewController: UIViewController { + weak var label: UILabel! + + override func viewDidLoad() { + super.viewDidLoad() + let label = UILabel() + label.text = "Unavailable content" + label.numberOfLines = 0 + label.textAlignment = .center + label.frame = view.bounds + label.autoresizingMask = [ + .flexibleTopMargin, + .flexibleLeftMargin, + .flexibleBottomMargin, + .flexibleRightMargin + ] + view.addSubview(label) + self.label = label + } +} diff --git a/Examples/Samples/Sources/UseCases/UseCase.swift b/Examples/Samples/Sources/UseCases/UseCase.swift index 3da2aa75..42d843f7 100644 --- a/Examples/Samples/Sources/UseCases/UseCase.swift +++ b/Examples/Samples/Sources/UseCases/UseCase.swift @@ -5,6 +5,7 @@ import UIKit enum UseCase: Int, CaseIterable { case trackingTableView case trackingTextView + case trackingCollectionViewList case showDetail case showModal case showPanelModal @@ -31,6 +32,7 @@ extension UseCase { var name: String { switch self { case .trackingTableView: return "Scroll tracking(TableView)" + case .trackingCollectionViewList: return "Scroll tracking(List CollectionView)" case .trackingTextView: return "Scroll tracking(TextView)" case .showDetail: return "Show Detail Panel" case .showModal: return "Show Modal" @@ -65,6 +67,15 @@ extension UseCase { private var content: Content { switch self { case .trackingTableView: return .viewController(DebugTableViewController()) + case .trackingCollectionViewList: + if #available(iOS 14, *) { + return .viewController(DebugListCollectionViewController()) + } else { + let vc = UnavailableViewController() + vc.loadViewIfNeeded() + vc.label.text = "UICollectionLayoutListConfiguration is unavailable.\nBuild this app on iOS 14 and later." + return .viewController(vc) + } case .trackingTextView: return .storyboard("ConsoleViewController") // Storyboard only case .showDetail: return .storyboard(String(describing: DetailViewController.self)) case .showModal: return .storyboard(String(describing: ModalViewController.self)) diff --git a/Examples/Samples/Sources/UseCases/UseCaseController.swift b/Examples/Samples/Sources/UseCases/UseCaseController.swift index 4f64e42b..5cddf6ba 100644 --- a/Examples/Samples/Sources/UseCases/UseCaseController.swift +++ b/Examples/Samples/Sources/UseCases/UseCaseController.swift @@ -52,6 +52,30 @@ extension UseCaseController { fpc.ext_trackScrollView(in: contentVC) addMain(panel: fpc) + case .trackingCollectionViewList: + let fpc = FloatingPanelController() + fpc.delegate = self + fpc.contentInsetAdjustmentBehavior = .always + fpc.surfaceView.appearance = { + let appearance = SurfaceAppearance() + appearance.cornerRadius = 6.0 + return appearance + }() + + let tapGesture = UITapGestureRecognizer(target: self, action: #selector(UseCaseController.handleSurface(tapGesture:))) + tapGesture.cancelsTouchesInView = false + tapGesture.numberOfTapsRequired = 2 + // Prevents a delay to response a tap in menus of DebugTableViewController. + tapGesture.delaysTouchesEnded = false + fpc.surfaceView.addGestureRecognizer(tapGesture) + + fpc.set(contentViewController: contentVC) + if #available(iOS 14, *), + let scrollView = (fpc.contentViewController as? DebugListCollectionViewController)?.collectionView { + fpc.track(scrollView: scrollView) + } + addMain(panel: fpc) + case .trackingTextView: let fpc = FloatingPanelController() fpc.delegate = self