问题描述
我使用 NSCollectionView
构建了一个 NSViewRepresentable
包装器,但它拒绝滚动。这个类看起来像这样:
final class SwiftNSCollectionView: NSObject,NSViewRepresentable,NSCollectionViewDataSource // etc
{
// ... init ...
typealias NSViewType = NSCollectionView
func makeNSView(context: Context) -> NSCollectionView {
let collectionView = NSCollectionView()
scrollView.documentView = collectionView
updateNSView(collectionView,context: context)
return collectionView
}
func updateNSView(_ scrollView: NSCollectionView,context: Context) {
collectionView.dataSource = self
// ... other collectionView setup
}
// ...
}
通常,NSCollectionView
有一个内置的 NSScrollView。
我试过了:
-
没有包装器——
NSCollectionView
根本不滚动。 -
将此
SwiftNSCollectionView
包装在 SwiftUIScrollView
中,但这会导致两个问题:-
NSCollectionView
的高度折叠为 0(我可以使用GeometryReader
解决这个问题) -
NSCollectionView
不想扩展到其所有对象的高度(这是有道理的,因为它将它们虚拟化)
-
-
使用带有正交滚动方向的
NSCollectionViewCompositionalLayoutConfiguration
(hacky):let section = NSCollectionLayoutSection(group: group) section.orthogonalScrollingBehavior = .continuous // If the "official" scroll direction is horizontal,// then the orthogonal direction becomes vertical,// and we can scroll our one section ? let configuration = NSCollectionViewCompositionalLayoutConfiguration() configuration.scrollDirection = .horizontal
但这似乎打乱了键盘输入:在一定数量的元素之后,元素之间的箭头键要么完全停止工作,要么移动到完全错误的元素上。看起来像是某种虚拟化错误。
解决方法
您可以通过手动创建 NSScrollView
来缓解这种情况。
- 将
NSViewType
更新为NSScrollView
。 - 根据需要更新函数签名。
- 使用您现有的
NSCollectionView
作为新滚动视图的.documentView
。
然后您可以直接在 SwiftUI 代码中使用您的 SwiftNSCollectionView
,它会正确滚动,而无需您进行任何自定义工作。
final class SwiftNSCollectionView: NSObject,NSViewRepresentable,NSCollectionViewDataSource // etc {
// ... init ...
// No longer NSCollectionView
typealias NSViewType = NSScrollView
func makeNSView(context: Context) -> NSScrollView {
// Create an NSScrollView,too!
let scrollView = NSScrollView()
let collectionView = NSCollectionView()
scrollView.documentView = collectionView
updateNSView(scrollView,context: context)
return scrollView
}
func updateNSView(_ scrollView: NSScrollView,context: Context) {
// Since we get an NSScrollView,get the child!
let collectionView = scrollView.documentView as! NSCollectionView
collectionView.dataSource = self
// ... other collectionView setup
}
// ...
}