首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >NSCollectionView自定义布局支持滚动

NSCollectionView自定义布局支持滚动
EN

Stack Overflow用户
提问于 2016-06-24 22:50:49
回答 5查看 3.4K关注 0票数 6

我无法同时使用垂直和水平滚动来使用NSCollectionView的自定义布局。根据文档,在我的子类中,我返回collectionViewContentSize,如果太大,集合视图的封闭滚动视图中会自动启用滚动。但是,即使我对水平行中的所有元素进行了排序,也只启用了垂直滚动。

截图如下:

这是我的布局代码:

代码语言:javascript
复制
class Layout: NSCollectionViewLayout
{
var cellSize = CGSize(width: 100, height: 30)

var cellSpacing: CGFloat = 10
var sectionSpacing: CGFloat = 20

private var contentSize = CGSize.zero
private var layoutAttributes = [NSIndexPath: NSCollectionViewLayoutAttributes]()


override func prepareLayout() {
    guard let collectionView = collectionView else { return }

    let sections = collectionView.numberOfSections
    guard sections > 0 else { return }

    contentSize.height = cellSize.height

    for section in 0..<sections {
        let items = collectionView.numberOfItemsInSection(section)
        guard items > 0 else { break }

        for item in 0..<items {
            let origin = CGPoint(x: contentSize.width, y: 0)
            let indexPath = NSIndexPath(forItem: item, inSection: section)
            let attributes = NSCollectionViewLayoutAttributes(forItemWithIndexPath: indexPath)
            attributes.frame = CGRect(origin: origin, size: cellSize)
            layoutAttributes[indexPath] = attributes

            contentSize.width += cellSize.width + cellSpacing
        }
        contentSize.width += sectionSpacing
    }
}

override var collectionViewContentSize: NSSize {
    return contentSize
}

override func layoutAttributesForElementsInRect(rect: NSRect) -> [NSCollectionViewLayoutAttributes] {

    return layoutAttributes.values.filter { $0.frame.intersects(rect) }
}

override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> NSCollectionViewLayoutAttributes? {
    return layoutAttributes[indexPath]
}

override func shouldInvalidateLayoutForBoundsChange(newBounds: NSRect) -> Bool {
    return false
}
}
EN

回答 5

Stack Overflow用户

发布于 2017-02-12 03:02:53

这个bug还在继续。我已经把博源的下流黑客换成了斯威夫特。(无意冒犯,伯远,我们必须做这个可怕的变通办法,这不是你的错!不过,一旦有正式的修复,我仍然会把这段代码去掉。就目前而言,这将使我的开发工作继续下去。)

代码语言:javascript
复制
class HackedCollectionView: NSCollectionView {
    override func setFrameSize(_ newSize: NSSize) {
        let size = collectionViewLayout?.collectionViewContentSize ?? newSize
        super.setFrameSize(size)
        if let scrollView = enclosingScrollView {
            scrollView.hasHorizontalScroller = size.width > scrollView.frame.width
        }
    }
}

请注意,这肯定需要尽快完成,因为滚动时动画的每一帧都会调用它。这可不好。请,请,请有人解决这个问题或找到一个适当的解决方案。不能水平滚动是荒谬的。

票数 7
EN

Stack Overflow用户

发布于 2017-08-02 07:54:45

似乎只有NSCollectionViewFlowLayout能够指定宽度大于父滚动视图框架的框架。

解决方案是对NSCollectionViewFlowLayout而不是NSCollectionViewLayout进行子类化。像对待任何其他布局子类一样对待该子类,但在prepareLayout()中添加关键的scrollDirection。

这是一个水平滚动的布局的最小实现,只需将所有项目设置为彼此相邻即可。

代码语言:javascript
复制
-(void) prepareLayout
{
    [super prepareLayout];
    self.scrollDirection = NSCollectionViewScrollDirectionHorizontal;
}

-(NSSize) collectionViewContentSize
{
    NSSize itemSize = self.itemSize;
    NSInteger num = [self.collectionView numberOfItemsInSection:0];
    NSSize contentSize = NSMakeSize((num * itemSize.width) + ((num+1) * self.minimumLineSpacing), NSHeight(self.collectionView.frame));
    return contentSize;
}

-(BOOL) shouldInvalidateLayoutForBoundsChange:(NSRect)newBounds { return YES; }

-(NSArray<__kindof NSCollectionViewLayoutAttributes *> *) layoutAttributesForElementsInRect:(NSRect)rect
{
    int numItems = [self.collectionView numberOfItemsInSection:0];
    NSMutableArray* attributes = [NSMutableArray arrayWithCapacity:numItems];
    for (int i=0; i<numItems; i++)
    {
        [attributes addObject:[self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:i inSection:0]]];
    }
    return attributes;
}

-(NSCollectionViewLayoutAttributes*) layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
    NSSize itemSize = self.itemSize;
    NSRect fr = NSZeroRect;
    fr.size = itemSize;
    fr.origin.y = (NSHeight(self.collectionView.frame) - itemSize.height) / 2.0;
    fr.origin.x = (indexPath.item+1 * self.minimumLineSpacing) + (indexPath.item * itemSize.width);
    NSCollectionViewLayoutAttributes* attr = [NSCollectionViewLayoutAttributes layoutAttributesForItemWithIndexPath:indexPath];
    attr.frame = fr;
    return attr;
}
票数 2
EN

Stack Overflow用户

发布于 2016-08-20 05:56:41

这基本上是NSCollectionView中的一个bug。作为变通办法,您可以(从NSCollectionViewFlowLayout)实现scrollDirection方法并返回NSCollectionViewScrollDirectionHorizontal。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38016263

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档