【问题标题】:NSCollectionView, left align with Compositional LayoutNSCollectionView,左对齐组合布局
【发布时间】:2020-11-25 22:34:44
【问题描述】:

我一直在尝试实现一个左对齐的标记列表,(NSTextField 在一个盒子 NSBox 内)。

这是我想要的:

我正在使用带有组合布局的 NSCollectionView 配置:

  • ITEM,估计宽度(初始值 = 80)和固定高度 (16)
  • GROUP,具有分数宽度(1.0,冰全宽度)和固定高度 (16) 项目将被放置在部分内(上面示例中的“流派”和“组合艺术家”)

这个想法是,当项目获得它们的实际字段内容时,自动布局约束将自动计算框宽度并将项目一个接一个地放置,换行到一个新的行以容纳更多项目。

应用数据快照时不会发生这种情况。

我得到的是这样的:

有趣的是,当我调整封闭窗口的大小时,就实现了所需的布局!!!

看起来像第一次使用估计大小渲染集合视图。

示例代码:

////

- (void)configureLayout
{
    float iWW = 80;
    float iHH = 16;
    
    ////////////////////
    // Item Definition
    
    NSCollectionLayoutSize *itemSize = [NSCollectionLayoutSize sizeWithWidthDimension:[NSCollectionLayoutDimension estimatedDimension:iWW]
                                                                      heightDimension:[NSCollectionLayoutDimension absoluteDimension:iHH]];
    NSCollectionLayoutItem *item = [NSCollectionLayoutItem itemWithLayoutSize:itemSize];

    
    ////////////////////
    // Group Definition
    
    NSCollectionLayoutSize *groupSize = [NSCollectionLayoutSize sizeWithWidthDimension:[NSCollectionLayoutDimension fractionalWidthDimension:1.0]
                                                                       heightDimension:[NSCollectionLayoutDimension estimatedDimension:iHH]];
    NSCollectionLayoutGroup *group = [NSCollectionLayoutGroup horizontalGroupWithLayoutSize:groupSize subitems:@[item]];

    group.interItemSpacing = [NSCollectionLayoutSpacing fixedSpacing:4.0];

    
    ////////////////////
    // Section Definition
    
    NSCollectionLayoutSection *section = [NSCollectionLayoutSection sectionWithGroup:group];
    NSCollectionLayoutSize *headerSize = [NSCollectionLayoutSize sizeWithWidthDimension:[NSCollectionLayoutDimension fractionalWidthDimension:1.0]
                                                                        heightDimension:[NSCollectionLayoutDimension absoluteDimension:22]];
    NSCollectionLayoutBoundarySupplementaryItem *sectionHeader = [NSCollectionLayoutBoundarySupplementaryItem
                                                                  boundarySupplementaryItemWithLayoutSize:headerSize
                                                                  elementKind:sectionHeaderElementKind
                                                                  alignment:NSRectAlignmentTop];
    section.boundarySupplementaryItems = @[sectionHeader];
    section.contentInsets = NSDirectionalEdgeInsetsMake(2, 0, 4, 10);
    section.interGroupSpacing = 4.0;


    ////////////////////
    // Prepare Layout
    
    collectionView.collectionViewLayout = [[NSCollectionViewCompositionalLayout alloc]initWithSection:section];
}

【问题讨论】:

    标签: macos nscollectionview


    【解决方案1】:
    1. 创建NSCollectionViewDiffableDataSource+Private.h(不需要.m文件)
    #import <Cocoa/Cocoa.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface NSCollectionViewDiffableDataSource (Private)
    - (void)applySnapshot:(NSDiffableDataSourceSnapshot *)snapshot animatingDifferences:(BOOL)animatingDifferences completion:(void(^ _Nullable)(void))completion;
    @end
    
    NS_ASSUME_NONNULL_END
    
    1. 在您的 applySnapshot:animatingDifferences: 代码中,替换为:
    #import "NSCollectionViewDiffableDataSource+Private.h"
    
    [self.dataSource applySnapshot:snapshot animatingDifferences:NO completion:^{
        [self.collectionView.collectionViewLayout invalidateLayout];
    }];
    

    如果您想避免使用 Private 方法,请使用NSViewFrameDidChangeNotification 观察NSCollectionView 的框架并调用- [NSCollectionViewLayout invalidateLayout]

    【讨论】: