9

我有一个NSCollectionView包含CustomViews. 最初,它将子视图平铺成列和行,就像网格一样。然后我将ColumnsIB 中的属性设置为 1,所以现在它只是逐行显示它们。然而,即使 myCustomView是 400px 宽,它被设置为自动调整大小,它NSCollectionView是 400px 宽,并且它被设置为 1 列,子视图被绘制大约 80px 宽。

我知道我可以通过调用来解决这个问题:

CGFloat width = collectionView.bounds.size.width;
NSSize size = NSMakeSize(width, 85);
[collectionView setMinItemSize:size];
[collectionView setMaxItemSize:size];

但是将此代码放在awakeFromNibmy 的方法中WindowController仅在程序启动时设置正确的宽度。当我调整窗口大小(以及NSCollectionView我指定的自动调整大小)时,CustomViews 保持最初设置的宽度。

如果需要,我很乐意自己调整子视图的大小,但我对 Cocoa 还是很陌生,似乎找不到任何文章来解释如何做这样的事情。有人可以指出我正确的方向吗?

安东尼

4

8 回答 8

9

真正的答案是将 maxItemSize 设置为 0,0( NSZeroSize)。否则,计算。

[self.collectionView setMaxItemSize:NSZeroSize];

这可以设置在awakeFromNib.

于 2014-02-27T16:19:58.903 回答
3

我知道这是一个很晚的回应,但我遇到了同样的问题,希望我的解决方案能帮助别人。解决方案是访问封闭滚动视图的边界而不是集合视图本身。因此,要解决它,您需要将第一行替换为:

CGFloat width = collectionView.enclosingScrollView.bounds.size.width;
于 2013-05-08T16:20:37.477 回答
2

我无法让它与默认布局一起使用 - 但实现自定义布局相当容易:

/// Simple single column layout, assuming only one section
class SingleColumnLayout: NSCollectionViewLayout {

    /// Height of each view in the collection
    var height:CGFloat = 100

    /// Padding is wrapped round each item, with double an extra bottom padding above the top item, and an extra top padding beneath the bottom
    var padding = EdgeInsets.init(top: 5, left: 10, bottom: 5, right: 10)

    var itemCount:Int {
        guard let collectionView = collectionView else {
            return 0
        }

        return collectionView.numberOfItems(inSection:0)
    }

    override func shouldInvalidateLayout(forBoundsChange newBounds: NSRect) -> Bool {
        return true
    }

    override open func layoutAttributesForItem(at indexPath: IndexPath) -> NSCollectionViewLayoutAttributes? {
        let attributes = NSCollectionViewLayoutAttributes(forItemWith: indexPath)
        guard let collectionView = collectionView else {
            return attributes
        }

        let bounds = collectionView.bounds
        let itemHeightWithPadding = height + padding.top + padding.bottom
        let row = indexPath.item

        attributes.frame = NSRect(x: padding.left, y: itemHeightWithPadding * CGFloat(row) + padding.top + padding.bottom , width: bounds.width - padding.left - padding.right , height: height)
        attributes.zIndex = row

        return attributes
    }

    //If you have lots of items, then you should probably do a 'proper' implementation here
    override open func layoutAttributesForElements(in rect: NSRect) -> [NSCollectionViewLayoutAttributes] {
        var attributes = [NSCollectionViewLayoutAttributes]()

        if (itemCount>0){
            for index in 0...(itemCount-1) {
                if let attribute = layoutAttributesForItem(at: NSIndexPath(forItem: index, inSection: 0) as IndexPath) {
                    attributes.append(attribute)
                }
            }
        }

        return attributes
    }

    override open var collectionViewContentSize: NSSize {

        guard let collectionView = collectionView else {
            return NSSize.zero
        }

        let itemHeightWithPadding = height + padding.top + padding.bottom

        return NSSize.init(width: collectionView.bounds.width, height: CGFloat(itemCount) * itemHeightWithPadding + padding.top + padding.bottom )
    }
}

那么你所需要的就是

var layout=SingleColumnLayout()
collectionView.collectionViewLayout = layout
于 2017-01-23T18:31:38.127 回答
1

另一个迟到的 - 我刚刚切换到使用 anNSTableViewNSView通过该delegate方法提供 an 。

自动调整大小是免费的,一列很容易,而且渲染速度大大加快。

于 2014-10-20T15:30:09.683 回答
0

假设您希望 CollectionViewItem 的大小为 200x180px,那么您应该设置:

[myCollectionView setMinItemSize:NSMakeSize(200, 180)];
[myCollectionView setMaxItemSize:NSMakeSize(280, 250)];

您的 Max-Size 应该足够大,看起来不错,并提供足够的空间进行拉伸以适应 collectionView-Width。

如果您有固定数量的列,您可能可以使用 (0,0),但如果您想要动态的行数和列数,就像我想要的那样。您应该设置一个固定的最小尺寸和更大的最大尺寸。

于 2014-12-13T00:24:05.073 回答
0

虽然您可能会得到一个集合视图以按照您的意愿行事,但我认为您有一个设计问题

您应该使用 aNSTableView并将列设置为 1,并将它们的大小设置为“无”以外的任何值。NSTableView适用于表格数据,而且它可以回收单元格,从而为大量项目提供极大的性能提升。NSCollectionView更像是一种线性布局,将项目排列在网格中,垂直滚动。当列号可以动态更改以允许在屏幕上显示更多项目时,它很有用,通常取决于设备方向和屏幕大小。

于 2015-02-27T14:45:46.877 回答
0

我尝试了这里提出的所有解决方案,但没有一个有帮助。如果您使用流布局(默认使用),您可以使用以下代码对其进行扩展,并且每次更改都会调用委托的 sizeForItem 方法

class MyCollectionViewFlowLayout: NSCollectionViewFlowLayout {

    override func shouldInvalidateLayout(forBoundsChange newBounds: NSRect) -> Bool {
        return true
    }

    override func invalidationContext(forBoundsChange newBounds: NSRect) -> NSCollectionViewLayoutInvalidationContext {
       let context = super.invalidationContext(forBoundsChange: newBounds) as! NSCollectionViewFlowLayoutInvalidationContext
       context.invalidateFlowLayoutDelegateMetrics = true
       return context
    }
}

希望它对某人有所帮助,因为我花了几个晚上才找到解决方案

于 2020-10-09T20:39:10.913 回答
-5

Matt Gallagher 的精彩博客Cocoa with Love即将解决这个问题本周,他分享了一个单列视图的绑定细节,比如有问题的视图:

http://cocoawithlove.com/2010/03/designing-view-with-bindings.html

下一个条目,他承诺分享其余的实现,这应该会给你你正在寻找的东西。

(我应该注意到,他直接继承了 NSView 并重新实现了 NSCollectionView 的许多功能。但这似乎很常见;没有多少人喜欢继承 NSCollectionView。)

编辑:似乎他违背了诺言……我们从未收到过那个帖子。请参阅下面的 tofutim 的答案。

于 2010-03-11T17:28:08.497 回答