Skip to content

Commit

Permalink
Support using collection view safe area insets as cell layout margins (
Browse files Browse the repository at this point in the history
  • Loading branch information
mohamede1945 authored Jan 20, 2024
1 parent a9403b0 commit ad95411
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 61 deletions.
2 changes: 1 addition & 1 deletion UI/NoorUI/Pager/PageViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ extension _PageViewController {
self.element = element
super.init(rootView: rootView)
view.backgroundColor = .clear
_disableSafeAreaInsets()
_disableSafeArea = true
}

@available(*, unavailable)
Expand Down
11 changes: 11 additions & 0 deletions UI/UIx/SwiftUI/CollectionView/CollectionView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public struct CollectionView<
configure: configure,
content: content,
isPagingEnabled: isPagingEnabled,
usesCollectionViewSafeAreaForCellLayoutMargins: usesCollectionViewSafeAreaForCellLayoutMargins,
scrollAnchorId: scrollAnchorId,
scrollAnchor: scrollAnchor
)
Expand Down Expand Up @@ -64,6 +65,12 @@ public struct CollectionView<
}
}

public func usesCollectionViewSafeAreaForCellLayoutMargins(_ flag: Bool) -> Self {
mutateSelf {
$0.usesCollectionViewSafeAreaForCellLayoutMargins = flag
}
}

// MARK: Private

private let layout: UICollectionViewLayout
Expand All @@ -72,6 +79,7 @@ public struct CollectionView<
private var configure: ((UICollectionView) -> Void)?

private var isPagingEnabled: Bool = false
private var usesCollectionViewSafeAreaForCellLayoutMargins: Bool = false

private var scrollAnchorId: Binding<Item.ID>?
private var scrollAnchor: ScrollAnchor = .center
Expand All @@ -92,6 +100,7 @@ private struct CollectionViewBody<
let content: (SectionId, Item) -> ItemContent

let isPagingEnabled: Bool
let usesCollectionViewSafeAreaForCellLayoutMargins: Bool

let scrollAnchorId: Binding<Item.ID>?
let scrollAnchor: ScrollAnchor
Expand Down Expand Up @@ -123,6 +132,8 @@ private struct CollectionViewBody<

viewController.dataSource?.sections = sections

viewController.usesCollectionViewSafeAreaForCellLayoutMargins = usesCollectionViewSafeAreaForCellLayoutMargins

viewController.scroller.isPagingEnabled = isPagingEnabled
viewController.scroller.onScrollAnchorIdUpdated = {
scrollAnchorId?.wrappedValue = $0
Expand Down
50 changes: 44 additions & 6 deletions UI/UIx/SwiftUI/CollectionView/CollectionViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,29 @@ final class CollectionViewController<
let collectionView: UICollectionView
lazy var scroller = CollectionViewScroller<SectionId, Item>(collectionView: collectionView)

var usesCollectionViewSafeAreaForCellLayoutMargins = true {
didSet {
if usesCollectionViewSafeAreaForCellLayoutMargins != oldValue {
updateLayoutMarginsForVisibleCells()
}
}
}

var dataSource: CollectionViewDataSource<SectionId, Item>? {
didSet {
scroller.dataSource = dataSource
}
}

override func viewSafeAreaInsetsDidChange() {
super.viewSafeAreaInsetsDidChange()
updateLayoutMarginsForVisibleCells()
}

override func loadView() {
view = collectionView
}

override func viewIsAppearing(_ animated: Bool) {
super.viewIsAppearing(animated)
scroller.scrollToInitialItemIfNeeded()
Expand All @@ -63,15 +80,26 @@ final class CollectionViewController<
// MARK: - Cell Lifecycle

func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
(cell as? CellType)?.cellWillDisplay(animated: false)
guard let typedCell = cell as? CellType else {
return
}
typedCell.updateLayoutMargins(
usesCollectionViewSafeAreaForCellLayoutMargins: usesCollectionViewSafeAreaForCellLayoutMargins,
collectionViewSafeAreaInsets: view.safeAreaInsets
)

typedCell.cellWillDisplay(animated: false)
}

func collectionView(
_ collectionView: UICollectionView,
didEndDisplaying cell: UICollectionViewCell,
forItemAt indexPath: IndexPath
) {
(cell as? CellType)?.cellDidEndDisplaying(animated: false)
guard let typedCell = cell as? CellType else {
return
}
typedCell.cellDidEndDisplaying(animated: false)
}

// MARK: - Paging
Expand Down Expand Up @@ -104,10 +132,6 @@ final class CollectionViewController<
scroller.endInteractiveScrolling()
}

override func loadView() {
view = collectionView
}

// MARK: Private

private func setUpDataSource(content: @escaping (SectionId, Item) -> ItemContent) {
Expand All @@ -129,7 +153,21 @@ final class CollectionViewController<
let cell = collectionView.dequeueReusableCell(CellType.self, for: indexPath)
cell.configure(content: content(section.id, item), dataId: itemId)

cell.updateLayoutMargins(
usesCollectionViewSafeAreaForCellLayoutMargins: usesCollectionViewSafeAreaForCellLayoutMargins,
collectionViewSafeAreaInsets: view.safeAreaInsets
)

return cell
}
}

private func updateLayoutMarginsForVisibleCells() {
for cell in collectionView.visibleCells {
(cell as? CellType)?.updateLayoutMargins(
usesCollectionViewSafeAreaForCellLayoutMargins: usesCollectionViewSafeAreaForCellLayoutMargins,
collectionViewSafeAreaInsets: view.safeAreaInsets
)
}
}
}
32 changes: 32 additions & 0 deletions UI/UIx/SwiftUI/CollectionView/HostingCollectionViewCell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,18 @@ import SwiftUI
final class HostingCollectionViewCell<Content: View>: UICollectionViewCell {
// MARK: Internal

override var safeAreaInsets: UIEdgeInsets {
.zero
}

func updateLayoutMargins(usesCollectionViewSafeAreaForCellLayoutMargins: Bool, collectionViewSafeAreaInsets: UIEdgeInsets) {
if usesCollectionViewSafeAreaForCellLayoutMargins {
cellLayoutMargins = .useCollectionViewSafeArea(collectionViewSafeAreaInsets)
} else {
cellLayoutMargins = .zero
}
}

func configure(content: Content, dataId: AnyHashable) {
self.dataId = dataId
let content = EpoxySwiftUIHostingView<Content>.Content(rootView: content, dataID: dataId)
Expand All @@ -34,6 +46,12 @@ final class HostingCollectionViewCell<Content: View>: UICollectionViewCell {
private var dataId: AnyHashable?
private var hostingView: EpoxySwiftUIHostingView<Content>?

private var cellLayoutMargins: CollectionViewCellLayoutMargins = .zero {
didSet {
updateLayoutMarginsIfNeeded()
}
}

private func setViewIfNeeded(view: EpoxySwiftUIHostingView<Content>) {
guard hostingView == nil else {
return
Expand All @@ -52,4 +70,18 @@ final class HostingCollectionViewCell<Content: View>: UICollectionViewCell {
view.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
])
}

private func updateLayoutMarginsIfNeeded() {
switch cellLayoutMargins {
case .zero:
hostingView?.layoutMargins = .zero
case .useCollectionViewSafeArea(let insets):
hostingView?.layoutMargins = insets
}
}
}

private enum CollectionViewCellLayoutMargins {
case zero
case useCollectionViewSafeArea(_ safeArea: UIEdgeInsets)
}
54 changes: 0 additions & 54 deletions UI/UIx/SwiftUI/Miscellaneous/DisableSafeAreaInsets.swift

This file was deleted.

0 comments on commit ad95411

Please sign in to comment.