简体   繁体   中英

Full width NSCollectionViewFlowLayout with NSCollectionView

I have a NSCollectionViewFlowLayout which contains the following:

- (NSSize) itemSize
{
    return CGSizeMake(self.collectionView.bounds.size.width, kItemHeight);
} // End of itemSize

- (CGFloat) minimumLineSpacing
{
    return 0;
} // End of minimumLineSpacing

- (CGFloat) minimumInteritemSpacing
{
    return 0;
} // End of minimumInteritemSpacing

I've tried to ways to make the layout responsive (set the width whenever resized). I've tried adding the following:

[[NSNotificationCenter defaultCenter] addObserver: self
                                         selector: @selector(onWindowDidResize:)
                                             name: NSWindowDidResizeNotification
                                           object: nil];

- (void) onWindowDidResize: (NSNotification*) notification
{
    [connectionsListView.collectionViewLayout invalidateLayout];
} // End of windowDidResize:

And this works fine if I expand the collection view (resize larger). But if I attempt to collapse the view (resize smaller), I get the following exceptions:

The behavior of the UICollectionViewFlowLayout is not defined because:
The item width must be less than the width of the UICollectionView minus the section insets left and right values, minus the content insets left and right values.
The relevant UICollectionViewFlowLayout instance is <TestListLayout: 0x106f70f90>, and it is attached to <NSCollectionView: 0x106f76480>.

Any suggestions on how I can resolve this?

NOTE1: This is macOS and not iOS (even though the error message states UICollectionViewFlowLayout).

NOTE2: Even though I receive the warning/error the layout width works, but I would like to figure out the underlying issue.

This is because you are using the didResize event, which is too late. Your items are too wide at the moment the window starts to shrink. Try using:

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

...when overriding flow layout, to get everything recalculated.

The source code I posted in the question works fine as of macOS 10.14 with no issues. I added the following to my window which displays the collection view.

// Only Mojave and after is resizable. Before that, a full sized collection view caused issues as listed
// at https://stackoverflow.com/questions/48567326/full-width-nscollectionviewflowlayout-with-nscollectionview
if(@available(macOS 10.14, *))
{
    self.window.styleMask |= NSWindowStyleMaskResizable;
} // End of macOS 10.14+

I had the same problem but in my case I resized view. @Giles solution didn't work for me until I changed invalidation context

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

Hope it helps someone as it took me couple of evenings to find solution

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM