为简单起见,我想知道如何让UICollectionView和其父级Scroll View一起滚动。
我的应用中的此SingleMovieView是在SwiftUI中构建的,其滚动视图包含电影封面,电影详细信息(如体裁,时长...),在其下方的两个视图为createSecCollectionView()
,可创建一个UIViewRepresentable来显示电影信息学分,图像作为UIKit视图。
问题是,当我运行该应用程序时,我发现UIViewRepresentable View与该滚动视图不对齐,它只是独立滚动并滚动,与滚动视图不对齐,请在下面的gif中查看,然后您就会知道这个问题。 / p>
如果无法完成,我想知道如何在SwiftUI中应用该外观(垂直的Scroll View包含Image + Text +许多滚动列表)?就像可以使用其他视图一样。
import SwiftUI
import KingfisherSwiftUI
struct SingleMovieView: View {
var movieId: Int = -1
@ObservedObject var model = MovieListViewModel()
var body: some View {
ScrollView(showsIndicators: false) {
VStack() {
createPosterImage()
MovieDetailView(movie: self.model.movie)
}
if model.secSectionMoviesBundle.isEmpty {
Text("Loading...")
} else {
createSecCollectionView()
}
}.onAppear() {
self.model.getMovieDetail(id: self.movieId)
self.model.getSecSectionMoviesBundle(id: self.movieId)
}
}
fileprivate func createPosterImage() -> some View {
return KFImage(source: .network(model.movie.posterUrl))
.resizable().aspectRatio(contentMode: .fill)
}
fileprivate func createSecCollectionView() -> some View {
return SecMovieCollectionView(allItems: model.secSectionMoviesBundle)
}
}
//更新,这是SecMovieCollectionView的代码
import SwiftUI
struct SecMovieCollectionView: UIViewRepresentable {
var allItems: [SecHomeSection:[MixedMovieBundle]]
//var didSelectItem: ( (_ indexPath: IndexPath) -> () ) = {_ in}
var seeAllforSection: ( (_ section: SecHomeSection)->() ) = {_ in }
func makeUIView(context: Context) -> UICollectionView {
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: context.coordinator.createCompositionalLayout())
collectionView.backgroundColor = .clear
collectionView.register(CrewCell.self, forCellWithReuseIdentifier: CrewCell.reuseId)
collectionView.register(CastCell.self, forCellWithReuseIdentifier: CastCell.reuseId)
collectionView.register(ImageCell.self, forCellWithReuseIdentifier: ImageCell.reuseId)
collectionView.register(PopularCell.self, forCellWithReuseIdentifier: PopularCell.reuseId)
collectionView.register(HeaderView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: HeaderView.reuseId)
collectionView.dataSource = context.coordinator
collectionView.delegate = context.coordinator
collectionView.alwaysBounceVertical = true
collectionView.showsVerticalScrollIndicator = false
return collectionView
}
func updateUIView(_ uiView: UICollectionView, context: Context) {
}
func makeCoordinator() -> SecMovieCollectionView.Coordinator {
Coordinator(self)
}
class Coordinator: NSObject, UICollectionViewDataSource, UICollectionViewDelegate {
var parent: SecMovieCollectionView
init(_ parent: SecMovieCollectionView) {
self.parent = parent
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
print("all items count: \(parent.allItems.count)")
return parent.allItems.count
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return parent.allItems[SecHomeSection.allCases[section]]?.count ?? 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
switch indexPath.section {
case 0:
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CrewCell.reuseId, for: indexPath) as? CrewCell {
cell.crew = parent.allItems[.Director]?[indexPath.item] as? CrewViewModel
return cell
}
case 1:
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CastCell.reuseId, for: indexPath) as? CastCell {
cell.cast = parent.allItems[.Cast]?[indexPath.item] as? CastViewModel
return cell
}
case 2:
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ImageCell.reuseId, for: indexPath) as? ImageCell {
cell.image = parent.allItems[.Images]?[indexPath.item] as? ImageViewModel
return cell
}
default:
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PopularCell.reuseId, for: indexPath) as? PopularCell {
cell.movie = parent.allItems[.Recomm]?[indexPath.item] as? MovieViewModel
return cell
}
}
return UICollectionViewCell()
}
// func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
// parent.didSelectItem(indexPath)
// }
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
switch kind {
case UICollectionView.elementKindSectionHeader:
guard let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: HeaderView.reuseId, for: indexPath) as? HeaderView else {
return UICollectionReusableView()
}
header.name.text = SecHomeSection.allCases[indexPath.section].rawValue
header.onSeeAllClicked = { [weak self] in
print("%%% Click in SecCollectionView %$$$$")
self?.parent.seeAllforSection(SecHomeSection.allCases[indexPath.section])
}
return header
default:
return UICollectionReusableView()
}
}
func createSharedSection() -> NSCollectionLayoutSection {
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.5), heightDimension: .fractionalHeight(1))
let layoutItem = NSCollectionLayoutItem(layoutSize: itemSize)
layoutItem.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 10, bottom: 0, trailing: 10)
let layoutGroupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.93), heightDimension: .fractionalWidth(0.75))
let layoutGroup = NSCollectionLayoutGroup.horizontal(layoutSize: layoutGroupSize, subitems: [layoutItem])
let layoutSection = NSCollectionLayoutSection(group: layoutGroup)
layoutSection.orthogonalScrollingBehavior = .groupPagingCentered
layoutSection.boundarySupplementaryItems = [createSectionHeader()]
return layoutSection
}
func createSectionHeader() -> NSCollectionLayoutBoundarySupplementaryItem {
let layoutSectionHeaderSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .estimated(80))
let layoutSectionHeader = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: layoutSectionHeaderSize, elementKind: UICollectionView.elementKindSectionHeader, alignment: .top)
return layoutSectionHeader
}
func createCompositionalLayout() -> UICollectionViewLayout {
let layout = UICollectionViewCompositionalLayout {[weak self] index, environment in
switch index {
case 0:
return self?.createSharedSection()
case 1:
return self?.createSharedSection()
case 2:
return self?.createSharedSection()
default:
return self?.createSharedSection()
}
}
let config = UICollectionViewCompositionalLayoutConfiguration()
config.interSectionSpacing = 20
layout.configuration = config
return layout
}
}
}