同iOS app 实现横向或纵向列表布局在macOS 中会用到NSCollectionView,不同的是要实现滚动需要指定NSScrollView并将CollectionView对象赋值给ScrollView的documentView。在实际开发中遇到两个问题,一个是 NSScrollView 滚动条一直显示无法隐藏,另外就是 NSCollectionViewFlowLayout 在数据不足一行时,列会居中展示,十分不协调美观。效果如下图:

1、解决滚动条无法隐藏问题(继承后手动隐藏),示例如下:
Swift
import Cocoa
//MARK: - CustomScrollView
class CustomScrollView: NSScrollView {
//MARK: - override
override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
// Drawing code here.
self.hiddenScroller()
}
/// 隐藏滚动条
public func hiddenScroller(){
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.5) {
self.subviews.forEach { _v in
if _v is NSScroller {
_v.isHidden = true
}
}
}
}
}
//MARK: - CustomCollectionView
class CustomCollectionView : NSCollectionView {
//MARK: - override
override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
// Drawing code here.
self.hiddenScroller()
}
/// 隐藏滚动条
public func hiddenScroller(isAsync:Bool = true){
DispatchQueue.main.async {
self.enclosingScrollView?.subviews.forEach { _v in
if _v is NSScroller {
_v.isHidden = true
}
}
let _hideBlock:()->Void = {
self.subviews.forEach { _sv in
if _sv is NSScrollView {
_sv.subviews.forEach { _v in
if _v is NSScroller {
_v.isHidden = true
}
}
}
}
}
if isAsync {
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.02) {
_hideBlock()
}
}
else{
_hideBlock()
}
}
}
}
并在 viewDidUnhide 方法调用
Swift
override func viewDidUnhide() {
super.viewDidUnhide()
self.scrollView.hiddenScroller()
}
2、解决NSCollectionViewFlowLayout 数据不足一列布局居中问题,参考如下:
Swift
private func createCompositionalLayout() -> NSCollectionViewLayout {
let view_space:CGFloat = (CGRectGetWidth(self.frame) - CGFloat(4) * view_width - CGFloat(2) * view_margin_left_right)/CGFloat(4 - 1)
// Item 大小:每个 item 宽度为容器宽度的 1/4,减去间距
let itemSize = NSCollectionLayoutSize(
widthDimension: .fractionalWidth(1.0/4.0),
heightDimension: .absolute(215)
)
let item = NSCollectionLayoutItem(layoutSize: itemSize)
// Group:一行显示 4 个 item
let groupSize = NSCollectionLayoutSize(
widthDimension: .fractionalWidth(1.0),
heightDimension: .absolute(215)
)
let group = NSCollectionLayoutGroup.horizontal(
layoutSize: groupSize,
subitem: item,
count: 4
)
// 设置 item 之间的间距(列间距)
group.interItemSpacing = .fixed(view_space)
// Section
let section = NSCollectionLayoutSection(group: group)
section.interGroupSpacing = view_margin_left_right//行间距
// 设置左右间距
let sideSpacing: CGFloat = view_margin_left_right
section.contentInsets = NSDirectionalEdgeInsets(
top: view_margin_left_right,
leading: sideSpacing, // 左边距
bottom: 0,
trailing: 0// 右边距
)
return NSCollectionViewCompositionalLayout(section: section)
}
以上内容就是这些,基本可以解决滚动条没法隐藏及布局异常问题