apptekstudios / ASCollectionView

A SwiftUI collection view with support for custom layouts, preloading, and more.
MIT License
1.36k stars 160 forks source link

General documentation #195

Closed RWOverdijk closed 3 years ago

RWOverdijk commented 3 years ago

This project seems to be really useful and I've been trying to understand how it works. Is there more documentation available? It might be because I'm new to swift/swiftui but I find it difficult to understand how this works based on the examples.

More specifically, I'm trying to implement one of the "app store" demo sliders, specifically the one for "featured". I end up still having two directions to scroll in and I can't seem to get it to align to the bottom of the screen because it's taking up the full height (I think that's the vertical scroll, which I don't need but also can't get rid of).

This is what I ended up with:

import SwiftUI
import ASCollectionView_SwiftUI
import URLImage

struct NearbyVenuesListView : View {
    @State var title = Lorem.title

    @State var venues = DataSource.apps()

    var body: some View
    {
        ASCollectionView(section: ASSection(
            id: 0,
            data: venues,
            dataID: \.self,
            onCellEvent: self.onCellEvent) { item, _ in
            AppViewFeature(app: item)
        })
        .layout(self.layout)
        .contentInsets(.init(top: 10, left: 0, bottom: 10, right: 0))
        .shouldAttemptToMaintainScrollPositionOnOrientationChange(maintainPosition: false)
    }

    func onCellEvent(_ event: CellEvent<AppModel>)
    {
        switch event
        {
        case let .onAppear(item):
            ASRemoteImageManager.shared.load(item.featureImageURL)
        case let .onDisappear(item):
            ASRemoteImageManager.shared.cancelLoad(for: item.featureImageURL)
        case let .prefetchForData(data):
            for item in data
            {
                ASRemoteImageManager.shared.load(item.featureImageURL)
            }
        case let .cancelPrefetchForData(data):
            for item in data
            {
                ASRemoteImageManager.shared.cancelLoad(for: item.featureImageURL)
            }
        }
    }
}

extension NearbyVenuesListView
{
    var layout: ASCollectionLayout<Int>
    {
        ASCollectionLayout(scrollDirection: .vertical, interSectionSpacing: 20)
        { sectionID in
            ASCollectionLayoutSection
            { environment in
                let columnsToFit = floor(environment.container.effectiveContentSize.width / 320)
                let item = NSCollectionLayoutItem(layoutSize: NSCollectionLayoutSize(
                                                    widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalHeight(1.0)))

                let width = 0.8 / columnsToFit;

                let itemsGroup = NSCollectionLayoutGroup.vertical(
                    layoutSize: NSCollectionLayoutSize(
                        widthDimension: .fractionalWidth(width),
                        heightDimension: .fractionalHeight(0.3)),
                    subitem: item, count: 1)

                let section = NSCollectionLayoutSection(group: itemsGroup)
                section.interGroupSpacing = 20
                section.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 20, bottom: 0, trailing: 20)
                section.orthogonalScrollingBehavior = .groupPaging
                section.visibleItemsInvalidationHandler = { _, _, _ in } // If this isn't defined, there is a bug in UICVCompositional Layout that will fail to update sizes of cells

                return section
            }
        }
    }
}

struct NearbyVenuesListView_Previews: PreviewProvider {
    static var previews: some View {
        NearbyVenuesListView()
    }
}

And I want to move this to the bottom and have the rest be transparent:

image

TL;DR; I don't understand how this library works and I would really like some pointers.

I'm sorry if this already documented somewhere. I couldn't find it 😅

apptekstudios commented 3 years ago

You could use a SwiftUI .frame(height: xxx) modifier to limit the height of the collection view.

eg.

VStack {
   Spacer()
   ASCollectionView { ... }
      .frame(height: 100)
}
apptekstudios commented 3 years ago

This documentation is helpful for UICollectionView layouts: https://developer.apple.com/documentation/uikit/views_and_controls/collection_views/implementing_modern_collection_views

RWOverdijk commented 3 years ago

Thank you. I ended up using a frame, but I felt like it was wrong. Apparently it's not 😄