Add Animations and List showcase (#13)

Summary: Pull Request resolved: https://github.com/facebookincubator/QuickLayout/pull/13

Reviewed By: saadhzahid

Differential Revision: D90382201

Pulled By: constantine-fry

fbshipit-source-id: 6726c6b6ee9c473b3a2a43880c9acf65e4f40ae9
This commit is contained in:
nuomi1 2026-01-19 10:00:19 -08:00 committed by meta-codesync[bot]
parent 54c78ef52b
commit bb0f8bbcbf
2 changed files with 88 additions and 15 deletions

View file

@ -10,13 +10,15 @@ import UIKit
final class BarsListViewController: UIViewController {
private var dataSource: UICollectionViewDiffableDataSource<Int, BarModel>?
private lazy var collectionView = {
private lazy var layout = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical
layout.minimumLineSpacing = 0
layout.minimumLineSpacing = 0
// patternlint-disable-next-line ig-avoid-uiscreen-bounds-swift
layout.itemSize = UIScreen.main.bounds.size
return layout
}()
private lazy var collectionView = {
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
collectionView.register(BarCardViewCell.self, forCellWithReuseIdentifier: BarCardViewCell.reuseIdentifier)
@ -37,6 +39,13 @@ final class BarsListViewController: UIViewController {
self.view = collectionView
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if layout.itemSize != view.bounds.size {
layout.itemSize = view.bounds.size
}
}
func configureDataSource() {
dataSource = UICollectionViewDiffableDataSource<Int, BarModel>(collectionView: collectionView) { (collectionView: UICollectionView, indexPath: IndexPath, item: BarModel) -> UICollectionViewCell? in
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: BarCardViewCell.reuseIdentifier, for: indexPath) as? BarCardViewCell else {

View file

@ -37,7 +37,16 @@ struct ShowcaseApp: View {
[
StateManagementView.self
]),
SCSection(
"Animations",
[
UpdatingWithAnimationView.self
]),
SCSection(
"List",
[
BarsListViewController.self
]),
SCSection(
"Alignment",
[
@ -101,34 +110,83 @@ struct ShowcaseApp: View {
private struct ShowcaseViewRepresentable: UIViewRepresentable {
let view: UIView.Type
let viewType: UIView.Type
init(_ viewType: UIView.Type) {
self.view = viewType
self.viewType = viewType
}
func makeUIView(context: Context) -> some UIView {
view.init() as UIView
viewType.init() as UIView
}
func updateUIView(_ uiView: UIViewType, context: Context) {
}
}
private struct ShowcaseViewControllerRepresentable: UIViewControllerRepresentable {
let viewControllerType: UIViewController.Type
init(_ viewControllerType: UIViewController.Type) {
self.viewControllerType = viewControllerType
}
func makeUIViewController(context: Context) -> some UIViewController {
viewControllerType.init() as UIViewController
}
func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
}
}
private enum ShowcaseType {
case view(UIView.Type)
case viewController(UIViewController.Type)
var underlyingType: Any.Type {
switch self {
case let .view(viewType):
return viewType
case let .viewController(viewControllerType):
return viewControllerType
}
}
}
@MainActor
private protocol ShowcaseTypeConvertable {
static var showcaseType: ShowcaseType { get }
}
extension UIView: ShowcaseTypeConvertable {
fileprivate static var showcaseType: ShowcaseType { .view(Self.self) }
}
extension UIViewController: ShowcaseTypeConvertable {
fileprivate static var showcaseType: ShowcaseType { .viewController(Self.self) }
}
private struct SCShowcase: Identifiable, Hashable {
let id = UUID()
let viewType: UIView.Type
let showcaseType: ShowcaseType
let label: String
init(viewType: UIView.Type) {
self.viewType = viewType
self.label = String(describing: viewType).splittingCamelCase()
init(showcaseType: ShowcaseType) {
self.showcaseType = showcaseType
self.label = String(describing: showcaseType.underlyingType).splittingCamelCase()
}
@MainActor
@ViewBuilder
func view() -> some View {
ShowcaseViewRepresentable(viewType)
switch showcaseType {
case let .view(viewType):
ShowcaseViewRepresentable(viewType)
case let .viewController(viewControllerType):
ShowcaseViewControllerRepresentable(viewControllerType)
}
}
static func == (lhs: SCShowcase, rhs: SCShowcase) -> Bool {
@ -142,7 +200,12 @@ private struct SCShowcase: Identifiable, Hashable {
private extension String {
func splittingCamelCase() -> String {
let stripped = self.hasSuffix("View") ? String(self.dropLast(4)) : self
let stripped =
self.hasSuffix("View")
? String(self.dropLast(4))
: (self.hasSuffix("ViewController")
? String(self.dropLast(14))
: self)
// Split by uppercase letters
let words = stripped.reduce("") { result, char in
@ -159,14 +222,15 @@ private extension String {
}
}
@MainActor
private struct SCSection: Identifiable, Hashable {
let id = UUID()
let showscases: [SCShowcase]
let title: String
init(_ title: String, _ showcases: [UIView.Type]) {
init(_ title: String, _ showcases: [ShowcaseTypeConvertable.Type]) {
self.title = title
self.showscases = showcases.map { SCShowcase(viewType: $0) }
self.showscases = showcases.map { SCShowcase(showcaseType: $0.showcaseType) }
}
}