Cocoa 使用NSCollectionView显示列表,数据不足布局异常处理

同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)
    }

以上内容就是这些,基本可以解决滚动条没法隐藏及布局异常问题

相关推荐
茶底世界之下17 小时前
Metal 冷启动并发下,Pipeline Cache 为什么必须合并在途编译
ios·swift
青柠之夏cc18 小时前
Kotlin Multiplatform:一次编写,全平台运行,2026 年跨平台开发的 “最优解”?
macos·objective-c·cocoa
黑科技iOS上架2 天前
双引擎解决oc/swift开发引用加固难题
开发语言·ios·swift·审核·ios混淆·执行程序差异化
黑科技iOS上架2 天前
iOS framework/dylib动态库定向加固实战
macos·ios·objective-c·cocoa·审核·ios混淆·执行程序差异化
神奇的小猴程序员3 天前
苹果Mac电脑玩我的世界没有版本?用PCL-R即可!
macos
灵韵aura3 天前
macOS 的指令缩写
macos
传奇开心果编程3 天前
【SwiftUI提高练中学】第13课 实时活动与灵动岛:ActivityKit 实战
学习·ui·ios·swiftui·swift
Digitally4 天前
如何在没有Wi-Fi的情况使用移动数据或电脑更新iPhone
电脑·cocoa·iphone