Repository: CoderFM/FMCollectionLayout Branch: master Commit: 312f97d176cc Files: 261 Total size: 670.7 KB Directory structure: gitextract_jeq_n4qo/ ├── .gitignore ├── .travis.yml ├── Example/ │ ├── FMLayoutKit/ │ │ ├── Base.lproj/ │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ ├── FMAddViewController.h │ │ ├── FMAddViewController.m │ │ ├── FMAotuSizeReusableView.h │ │ ├── FMAotuSizeReusableView.m │ │ ├── FMAppDelegate.h │ │ ├── FMAppDelegate.m │ │ ├── FMCollViewController.h │ │ ├── FMCollViewController.m │ │ ├── FMCollectionCustomCell.h │ │ ├── FMCollectionCustomCell.m │ │ ├── FMCollectionCustomDecoration.h │ │ ├── FMCollectionCustomDecoration.m │ │ ├── FMCollectionNavTitleView.h │ │ ├── FMCollectionNavTitleView.m │ │ ├── FMCollectionViewCell.h │ │ ├── FMCollectionViewCell.m │ │ ├── FMCollectionViewCell.xib │ │ ├── FMCombineViewController.h │ │ ├── FMCombineViewController.m │ │ ├── FMExcuteTimeTool.h │ │ ├── FMExcuteTimeTool.m │ │ ├── FMFPSLabel.h │ │ ├── FMFPSLabel.m │ │ ├── FMHorizontalLayoutController.h │ │ ├── FMHorizontalLayoutController.m │ │ ├── FMLayoutKit-Info.plist │ │ ├── FMLayoutKit-Prefix.pch │ │ ├── FMLayoutLabel.h │ │ ├── FMLayoutLabel.m │ │ ├── FMViewController.h │ │ ├── FMViewController.m │ │ ├── Images.xcassets/ │ │ │ ├── AppIcon.appiconset/ │ │ │ │ └── Contents.json │ │ │ ├── Contents.json │ │ │ └── timg.imageset/ │ │ │ └── Contents.json │ │ ├── LS_HomeActivityCell.h │ │ ├── LS_HomeActivityCell.m │ │ ├── en.lproj/ │ │ │ └── InfoPlist.strings │ │ └── main.m │ ├── FMLayoutKit.xcodeproj/ │ │ ├── project.pbxproj │ │ ├── project.xcworkspace/ │ │ │ └── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── xcschemes/ │ │ └── FMLayoutKit-Example.xcscheme │ ├── FMLayoutKit.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ ├── FMLayoutKitFramework/ │ │ └── FMLayoutKit.framework/ │ │ ├── FMLayoutKit │ │ ├── Headers/ │ │ │ ├── FMCollectionLayoutAttributes.h │ │ │ ├── FMCollectionViewDelegateDataSourceProvider.h │ │ │ ├── FMKVOArrayObject.h │ │ │ ├── FMLayout.h │ │ │ ├── FMLayoutAbsoluteSection.h │ │ │ ├── FMLayoutBackground.h │ │ │ ├── FMLayoutBaseSection.h │ │ │ ├── FMLayoutCombineSection.h │ │ │ ├── FMLayoutCrossSection.h │ │ │ ├── FMLayoutCrossTransformSection.h │ │ │ ├── FMLayoutDebugLog.h │ │ │ ├── FMLayoutDynamicSection.h │ │ │ ├── FMLayoutElement.h │ │ │ ├── FMLayoutFillSection.h │ │ │ ├── FMLayoutFixedSection.h │ │ │ ├── FMLayoutFooter.h │ │ │ ├── FMLayoutHeader.h │ │ │ ├── FMLayoutKit-umbrella.h │ │ │ ├── FMLayoutKit.h │ │ │ ├── FMLayoutLabelSection.h │ │ │ ├── FMLayoutScaleSection.h │ │ │ ├── FMLayoutView.h │ │ │ ├── FMSupplementary.h │ │ │ ├── FMTeslaLayoutView.h │ │ │ └── FMTeslaSuspensionHeightChangeDelegate.h │ │ ├── Info.plist │ │ ├── Modules/ │ │ │ └── module.modulemap │ │ └── _CodeSignature/ │ │ └── CodeResources │ ├── FrameworkTmp/ │ │ ├── Release-iphoneos/ │ │ │ └── FMLayoutKit/ │ │ │ ├── FMLayoutKit.framework/ │ │ │ │ ├── FMLayoutKit │ │ │ │ ├── Headers/ │ │ │ │ │ ├── FMCollectionLayoutAttributes.h │ │ │ │ │ ├── FMCollectionViewDelegateDataSourceProvider.h │ │ │ │ │ ├── FMKVOArrayObject.h │ │ │ │ │ ├── FMLayout.h │ │ │ │ │ ├── FMLayoutAbsoluteSection.h │ │ │ │ │ ├── FMLayoutBackground.h │ │ │ │ │ ├── FMLayoutBaseSection.h │ │ │ │ │ ├── FMLayoutCombineSection.h │ │ │ │ │ ├── FMLayoutCrossSection.h │ │ │ │ │ ├── FMLayoutCrossTransformSection.h │ │ │ │ │ ├── FMLayoutDebugLog.h │ │ │ │ │ ├── FMLayoutDynamicSection.h │ │ │ │ │ ├── FMLayoutElement.h │ │ │ │ │ ├── FMLayoutFillSection.h │ │ │ │ │ ├── FMLayoutFixedSection.h │ │ │ │ │ ├── FMLayoutFooter.h │ │ │ │ │ ├── FMLayoutHeader.h │ │ │ │ │ ├── FMLayoutKit-umbrella.h │ │ │ │ │ ├── FMLayoutKit.h │ │ │ │ │ ├── FMLayoutLabelSection.h │ │ │ │ │ ├── FMLayoutScaleSection.h │ │ │ │ │ ├── FMLayoutView.h │ │ │ │ │ ├── FMSupplementary.h │ │ │ │ │ ├── FMTeslaLayoutView.h │ │ │ │ │ └── FMTeslaSuspensionHeightChangeDelegate.h │ │ │ │ ├── Info.plist │ │ │ │ └── Modules/ │ │ │ │ └── module.modulemap │ │ │ └── FMLayoutKit.framework.dSYM/ │ │ │ └── Contents/ │ │ │ ├── Info.plist │ │ │ └── Resources/ │ │ │ └── DWARF/ │ │ │ └── FMLayoutKit │ │ └── Release-iphonesimulator/ │ │ └── FMLayoutKit/ │ │ ├── FMLayoutKit.framework/ │ │ │ ├── FMLayoutKit │ │ │ ├── Headers/ │ │ │ │ ├── FMCollectionLayoutAttributes.h │ │ │ │ ├── FMCollectionViewDelegateDataSourceProvider.h │ │ │ │ ├── FMKVOArrayObject.h │ │ │ │ ├── FMLayout.h │ │ │ │ ├── FMLayoutAbsoluteSection.h │ │ │ │ ├── FMLayoutBackground.h │ │ │ │ ├── FMLayoutBaseSection.h │ │ │ │ ├── FMLayoutCombineSection.h │ │ │ │ ├── FMLayoutCrossSection.h │ │ │ │ ├── FMLayoutCrossTransformSection.h │ │ │ │ ├── FMLayoutDebugLog.h │ │ │ │ ├── FMLayoutDynamicSection.h │ │ │ │ ├── FMLayoutElement.h │ │ │ │ ├── FMLayoutFillSection.h │ │ │ │ ├── FMLayoutFixedSection.h │ │ │ │ ├── FMLayoutFooter.h │ │ │ │ ├── FMLayoutHeader.h │ │ │ │ ├── FMLayoutKit-umbrella.h │ │ │ │ ├── FMLayoutKit.h │ │ │ │ ├── FMLayoutLabelSection.h │ │ │ │ ├── FMLayoutScaleSection.h │ │ │ │ ├── FMLayoutView.h │ │ │ │ ├── FMSupplementary.h │ │ │ │ ├── FMTeslaLayoutView.h │ │ │ │ └── FMTeslaSuspensionHeightChangeDelegate.h │ │ │ ├── Info.plist │ │ │ ├── Modules/ │ │ │ │ └── module.modulemap │ │ │ └── _CodeSignature/ │ │ │ └── CodeResources │ │ └── FMLayoutKit.framework.dSYM/ │ │ └── Contents/ │ │ ├── Info.plist │ │ └── Resources/ │ │ └── DWARF/ │ │ └── FMLayoutKit │ ├── Podfile │ ├── Pods/ │ │ ├── Local Podspecs/ │ │ │ └── FMLayoutKit.podspec.json │ │ ├── Masonry/ │ │ │ ├── LICENSE │ │ │ ├── Masonry/ │ │ │ │ ├── MASCompositeConstraint.h │ │ │ │ ├── MASCompositeConstraint.m │ │ │ │ ├── MASConstraint+Private.h │ │ │ │ ├── MASConstraint.h │ │ │ │ ├── MASConstraint.m │ │ │ │ ├── MASConstraintMaker.h │ │ │ │ ├── MASConstraintMaker.m │ │ │ │ ├── MASLayoutConstraint.h │ │ │ │ ├── MASLayoutConstraint.m │ │ │ │ ├── MASUtilities.h │ │ │ │ ├── MASViewAttribute.h │ │ │ │ ├── MASViewAttribute.m │ │ │ │ ├── MASViewConstraint.h │ │ │ │ ├── MASViewConstraint.m │ │ │ │ ├── Masonry.h │ │ │ │ ├── NSArray+MASAdditions.h │ │ │ │ ├── NSArray+MASAdditions.m │ │ │ │ ├── NSArray+MASShorthandAdditions.h │ │ │ │ ├── NSLayoutConstraint+MASDebugAdditions.h │ │ │ │ ├── NSLayoutConstraint+MASDebugAdditions.m │ │ │ │ ├── View+MASAdditions.h │ │ │ │ ├── View+MASAdditions.m │ │ │ │ ├── View+MASShorthandAdditions.h │ │ │ │ ├── ViewController+MASAdditions.h │ │ │ │ └── ViewController+MASAdditions.m │ │ │ └── README.md │ │ ├── Pods.xcodeproj/ │ │ │ └── project.pbxproj │ │ └── Target Support Files/ │ │ ├── FMLayoutKit/ │ │ │ ├── FMLayoutKit-Info.plist │ │ │ ├── FMLayoutKit-dummy.m │ │ │ ├── FMLayoutKit-prefix.pch │ │ │ ├── FMLayoutKit-umbrella.h │ │ │ ├── FMLayoutKit.debug.xcconfig │ │ │ ├── FMLayoutKit.modulemap │ │ │ └── FMLayoutKit.release.xcconfig │ │ ├── Masonry/ │ │ │ ├── Masonry-Info.plist │ │ │ ├── Masonry-dummy.m │ │ │ ├── Masonry-prefix.pch │ │ │ ├── Masonry-umbrella.h │ │ │ ├── Masonry.debug.xcconfig │ │ │ ├── Masonry.modulemap │ │ │ └── Masonry.release.xcconfig │ │ ├── Pods-FMLayoutKit_Example/ │ │ │ ├── Pods-FMLayoutKit_Example-Info.plist │ │ │ ├── Pods-FMLayoutKit_Example-acknowledgements.markdown │ │ │ ├── Pods-FMLayoutKit_Example-acknowledgements.plist │ │ │ ├── Pods-FMLayoutKit_Example-dummy.m │ │ │ ├── Pods-FMLayoutKit_Example-frameworks.sh │ │ │ ├── Pods-FMLayoutKit_Example-umbrella.h │ │ │ ├── Pods-FMLayoutKit_Example.debug.xcconfig │ │ │ ├── Pods-FMLayoutKit_Example.modulemap │ │ │ └── Pods-FMLayoutKit_Example.release.xcconfig │ │ └── Pods-FMLayoutKit_Tests/ │ │ ├── Pods-FMLayoutKit_Tests-Info.plist │ │ ├── Pods-FMLayoutKit_Tests-acknowledgements.markdown │ │ ├── Pods-FMLayoutKit_Tests-acknowledgements.plist │ │ ├── Pods-FMLayoutKit_Tests-dummy.m │ │ ├── Pods-FMLayoutKit_Tests-umbrella.h │ │ ├── Pods-FMLayoutKit_Tests.debug.xcconfig │ │ ├── Pods-FMLayoutKit_Tests.modulemap │ │ └── Pods-FMLayoutKit_Tests.release.xcconfig │ ├── Tests/ │ │ ├── Tests-Info.plist │ │ ├── Tests-Prefix.pch │ │ ├── Tests.m │ │ └── en.lproj/ │ │ └── InfoPlist.strings │ └── makeFramework.sh ├── FMLayoutKit/ │ ├── Assets/ │ │ └── .gitkeep │ └── Classes/ │ ├── .gitkeep │ ├── Cross/ │ │ ├── FMLayoutCrossCell.h │ │ ├── FMLayoutCrossCell.m │ │ ├── FMLayoutCrossSection.h │ │ ├── FMLayoutCrossSection.m │ │ ├── FMLayoutCrossTransformSection.h │ │ └── FMLayoutCrossTransformSection.m │ ├── Element/ │ │ ├── FMLayoutBackground.h │ │ ├── FMLayoutBackground.m │ │ ├── FMLayoutElement.h │ │ ├── FMLayoutElement.m │ │ ├── FMLayoutFooter.h │ │ ├── FMLayoutFooter.m │ │ ├── FMLayoutHeader.h │ │ ├── FMLayoutHeader.m │ │ ├── FMSupplementary.h │ │ └── FMSupplementary.m │ ├── FMCollectionLayoutAttributes.h │ ├── FMCollectionLayoutAttributes.m │ ├── FMCollectionViewDelegateDataSourceProvider.h │ ├── FMCollectionViewDelegateDataSourceProvider.m │ ├── FMKVOArrayObject.h │ ├── FMKVOArrayObject.m │ ├── FMLayout.h │ ├── FMLayout.m │ ├── FMLayoutDebugLog.h │ ├── FMLayoutDebugLog.m │ ├── FMLayoutKit.h │ ├── FMLayoutView.h │ ├── FMLayoutView.m │ ├── FMTeslaLayoutView.h │ ├── FMTeslaLayoutView.m │ ├── FMTeslaSuspensionHeightChangeDelegate.h │ ├── Sections/ │ │ ├── FMLayoutAbsoluteSection.h │ │ ├── FMLayoutAbsoluteSection.m │ │ ├── FMLayoutBaseSection.h │ │ ├── FMLayoutBaseSection.m │ │ ├── FMLayoutCombineSection.h │ │ ├── FMLayoutCombineSection.m │ │ ├── FMLayoutDynamicSection.h │ │ ├── FMLayoutDynamicSection.m │ │ ├── FMLayoutFillSection.h │ │ ├── FMLayoutFillSection.m │ │ ├── FMLayoutFixedSection.h │ │ ├── FMLayoutFixedSection.m │ │ ├── FMLayoutLabelSection.h │ │ ├── FMLayoutLabelSection.m │ │ ├── FMLayoutScaleSection.h │ │ └── FMLayoutScaleSection.m │ ├── UIView+FMLayout.h │ ├── UIView+FMLayout.m │ ├── _FMLayoutSussEmptyView.h │ └── _FMLayoutSussEmptyView.m ├── FMLayoutKit.podspec ├── LICENSE ├── README.md └── submitNewVersion.sh ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ # OS X .DS_Store # Xcode build/ *.pbxuser !default.pbxuser *.mode1v3 !default.mode1v3 *.mode2v3 !default.mode2v3 *.perspectivev3 !default.perspectivev3 xcuserdata/ *.xccheckout profile *.moved-aside DerivedData *.hmap *.ipa # Bundler .bundle # Add this line if you want to avoid checking in source code from Carthage dependencies. # Carthage/Checkouts Carthage/Build # We recommend against adding the Pods directory to your .gitignore. However # you should judge for yourself, the pros and cons are mentioned at: # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control # # Note: if you ignore the Pods directory, make sure to uncomment # `pod install` in .travis.yml # # Pods/ ================================================ FILE: .travis.yml ================================================ # references: # * https://www.objc.io/issues/6-build-tools/travis-ci/ # * https://github.com/supermarin/xcpretty#usage osx_image: xcode7.3 language: objective-c # cache: cocoapods # podfile: Example/Podfile # before_install: # - gem install cocoapods # Since Travis is not always on latest version # - pod install --project-directory=Example script: - set -o pipefail && xcodebuild test -enableCodeCoverage YES -workspace Example/FMLayoutKit.xcworkspace -scheme FMLayoutKit-Example -sdk iphonesimulator9.3 ONLY_ACTIVE_ARCH=NO | xcpretty - pod lib lint ================================================ FILE: Example/FMLayoutKit/Base.lproj/LaunchScreen.storyboard ================================================ ================================================ FILE: Example/FMLayoutKit/Base.lproj/Main.storyboard ================================================ ================================================ FILE: Example/FMLayoutKit/FMAddViewController.h ================================================ // // FMAddViewController.h // FMCollectionLayout_Example // // Created by 周发明 on 2020/4/17. // Copyright © 2020 周发明. All rights reserved. // #import NS_ASSUME_NONNULL_BEGIN @interface FMAddViewController : UIViewController @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FMLayoutKit/FMAddViewController.m ================================================ // // FMAddViewController.m // FMCollectionLayout_Example // // Created by 周发明 on 2020/4/17. // Copyright © 2020 周发明. All rights reserved. // #import "FMAddViewController.h" #import #import #import "LS_HomeActivityCell.h" #import "FMCollectionCustomDecoration.h" #import "FMCollectionCustomCell.h" #import "FMCollectionNavTitleView.h" #import "FMHorizontalLayoutController.h" #import "FMAotuSizeReusableView.h" @interface FMAddViewController () @property(nonatomic, strong)NSMutableArray *shareSections; @property(nonatomic, weak)FMLayoutView *collectionView; @property(nonatomic, weak)FMLayoutBaseSection *firstSection; @property(nonatomic, weak)FMLayoutDynamicSection *secondSection; @property(nonatomic, assign)BOOL twoChangeed; @end @implementation FMAddViewController - (void)firstAdd{ [self.firstSection.itemDatas addObjectsFromArray:@[@"1", @"2", @"3", @"4"]]; // [self.collectionView reloadSections:[NSIndexSet indexSetWithIndex:1]]; // [self.collectionView.layout.sections exchangeObjectAtIndex:1 withObjectAtIndex:2]; // [self.collectionView moveSection:1 toSection:2]; [self.collectionView reloadChangedSectionsData]; } - (void)firstDelete{ // [self.firstSection.itemDatas removeLastObject]; // [self.collectionView reloadSections:[NSIndexSet indexSetWithIndex:1]]; // [self.collectionView reloadData]; } - (void)secondsReplace{ self.twoChangeed = !self.twoChangeed; [self.secondSection markChangeAt:3]; // [self.secondSection.itemDatas replaceObjectAtIndex:2 withObject:@"2"]; [self.collectionView reloadChangedSectionsData]; } - (void)secondsAdd{ [self.secondSection.itemDatas addObjectsFromArray:@[@"1", @"2", @"3", @"4"]]; [self.collectionView reloadChangedSectionsData]; } - (void)secondsDelete{ [self.secondSection.itemDatas removeLastObject]; [self.collectionView reloadChangedSectionsData]; } - (void)viewDidLoad { [super viewDidLoad]; self.navigationItem.title = @"追加数据测试"; UIBarButtonItem *item1 = [[UIBarButtonItem alloc] initWithTitle:@"一添加" style:UIBarButtonItemStyleDone target:self action:@selector(firstAdd)]; UIBarButtonItem *item2 = [[UIBarButtonItem alloc] initWithTitle:@"一删除" style:UIBarButtonItemStyleDone target:self action:@selector(firstDelete)]; UIBarButtonItem *item3 = [[UIBarButtonItem alloc] initWithTitle:@"二替换" style:UIBarButtonItemStyleDone target:self action:@selector(secondsReplace)]; UIBarButtonItem *item4 = [[UIBarButtonItem alloc] initWithTitle:@"二添加" style:UIBarButtonItemStyleDone target:self action:@selector(secondsAdd)]; UIBarButtonItem *item5 = [[UIBarButtonItem alloc] initWithTitle:@"二删除" style:UIBarButtonItemStyleDone target:self action:@selector(secondsDelete)]; self.navigationItem.rightBarButtonItems = @[item2, item1, item3, item4, item5]; self.shareSections = [NSMutableArray array]; __weak typeof(self) weakSelf = self; { FMLayoutFixedSection *section = [FMLayoutFixedSection sectionWithSectionInset:UIEdgeInsetsMake(0, 15, 0, 15) itemSpace:10 lineSpace:10 column:2]; // section.header = [FMLayoutHeader elementSize:50 viewClass:[FMCollectionCustomDecoration class]]; section.header = [FMLayoutHeader elementSize:0 viewClass:[FMAotuSizeReusableView class]]; section.header.autoHeight = YES; // section.header.type = FMLayoutHeaderTypeSuspensionAlways; // section.header.zIndex = FMLayoutZIndexFrontAlways; // section.header.isStickTop = YES; section.header.inset = UIEdgeInsetsMake(0, -15, 0, -15); [section setConfigureHeaderData:^(FMLayoutBaseSection * _Nonnull section, UICollectionReusableView * _Nonnull header) { [(FMAotuSizeReusableView *)header contentLabel].text = @"按实际大街上肯德基哈克斯就打回修改后\n1\n2\n3\n4\n阿拉山口基多拉科技的拉升科技大理石科技大流口水基多拉考试记录"; }]; // [section setConfigureHeaderData:^(FMLayoutBaseSection * _Nonnull section, UICollectionReusableView * _Nonnull header) { // FMCollectionCustomDecoration *custom = (FMCollectionCustomDecoration *)header; // custom.textLabel.text = @"第一个悬浮的顶部视图, 黏在顶部"; // }]; [self.shareSections addObject:section]; } { FMLayoutFillSection *section = [[FMLayoutFillSection alloc] init]; section.itemDatas = [@[@"1", @"2", @"3", @"1", @"2", @"3", @"1", @"2", @"3", @"1", @"2", @"3", @"1", @"2", @"3",] mutableCopy]; section.sectionInset = UIEdgeInsetsMake(10, 10, 10, 10); // section.lineSpace = 10; // section.itemSpace = 10; section.header = [FMLayoutHeader elementSize:50 viewClass:[FMCollectionCustomDecoration class]]; // section.header.suspensionTopMargin = 150; section.header.zIndex = FMLayoutZIndexFrontAlways; section.header.type = FMLayoutHeaderTypeSuspensionAlways; [section setConfigureHeaderData:^(FMLayoutBaseSection * _Nonnull section, UICollectionReusableView * _Nonnull header) { FMCollectionCustomDecoration *customHeader = (FMCollectionCustomDecoration *)header; customHeader.textLabel.text = @"填充布局,寻找合适的空档,支持多种cell, header样式一直悬停在顶部"; }]; section.cellElement = [FMLayoutElement elementWithViewClass:[FMCollectionCustomCell class]]; [section setSizeBlock:^CGSize(id _Nonnull section, NSInteger item) { switch (item) { case 2: return CGSizeMake(150, 140.32); case 5: return CGSizeMake((weakSelf.view.frame.size.width-20-150)/2, 70.19); case 8: case 11: return CGSizeMake(100, 240); case 10: return CGSizeMake(weakSelf.view.frame.size.width-20-200, 140); case 9: case 12: return CGSizeMake(weakSelf.view.frame.size.width-20-100, 100); case 0: case 1: case 3: case 4: return CGSizeMake((weakSelf.view.frame.size.width-20-150)/4, 70.13); default: return CGSizeMake((weakSelf.view.frame.size.width-20-150)/4, 70.19); } }]; // [section setConfigureCellLayoutAttributes:^(id _Nonnull section, UICollectionViewLayoutAttributes * _Nonnull attributes, NSInteger item) { // if (item == 10) { // attributes.transform = CGAffineTransformMakeRotation(M_PI_4); // } // }]; [section setConfigureCellData:^(FMLayoutBaseSection * _Nonnull section, UICollectionViewCell * _Nonnull cell, NSInteger item) { FMCollectionCustomCell *customCell = (FMCollectionCustomCell *)cell; customCell.label.text = [NSString stringWithFormat:@"%ld", item]; }]; [self.shareSections addObject:section]; self.firstSection = section; } { FMLayoutFixedSection *section = [FMLayoutFixedSection sectionWithSectionInset:UIEdgeInsetsMake(0, 15, 15, 15) itemSpace:10 lineSpace:10 column:2]; section.header = [FMLayoutHeader elementSize:100 viewClass:[FMCollectionCustomDecoration class]]; section.header.lastMargin = 10; section.header.type = FMLayoutHeaderTypeSuspensionAlways; section.header.zIndex = FMLayoutZIndexFrontAlways; section.header.isStickTop = NO; section.header.suspensionTopMargin = 50; section.header.inset = UIEdgeInsetsMake(0, -15, 0, -15); [section setConfigureHeaderData:^(FMLayoutBaseSection * _Nonnull section, UICollectionReusableView * _Nonnull header) { FMCollectionCustomDecoration *custom = (FMCollectionCustomDecoration *)header; custom.textLabel.text = @"第二个悬浮的顶部视图, 不黏在顶部"; }]; section.footer = [FMLayoutFooter elementSize:50 viewClass:[FMCollectionCustomDecoration class]]; section.footer.topMargin = 10; section.itemSize = CGSizeMake(100, 100); section.itemDatas = [@[@"1", @"2", @"3"] mutableCopy]; section.cellElement = [FMLayoutElement elementWithViewClass:[FMCollectionCustomCell class]]; [section setClickCellBlock:^(FMLayoutBaseSection * _Nonnull section, NSInteger item) { FMHorizontalLayoutController *vc = [[FMHorizontalLayoutController alloc] init]; [weakSelf.navigationController pushViewController:vc animated:YES]; }]; [self.shareSections addObject:section]; // self.firstSection = section; } { FMLayoutLabelSection *section = [FMLayoutLabelSection sectionWithSectionInset:UIEdgeInsetsMake(0, 10, 0, 10) itemSpace:10 lineSpace:10 column:3]; section.header = [FMLayoutHeader elementSize:30 viewClass:[FMCollectionCustomDecoration class]]; section.header.zIndex = FMLayoutZIndexFrontOfItem; section.header.type = FMLayoutHeaderTypeFixed; section.header.lastMargin = 10; // section.isSingleLineCanScroll = YES; section.maxLine = 2; section.cellFixedHeight = 40; [section setWidthBlock:^CGFloat(id _Nonnull section, NSInteger item) { return item * 20 + 100; }]; section.itemDatas = [@[@"1", @"2", @"3", @"1", @"2", @"3", @"1", @"2", @"3", @"1", @"2", @"3", ] mutableCopy]; section.cellElement = [FMLayoutElement elementWithViewClass:[FMCollectionCustomCell class]]; // FMLayoutCrossSection *hSection = [FMLayoutCrossSection sectionAutoWithSection:section]; [self.shareSections addObject:section]; // self.firstSection = section; } { FMLayoutDynamicSection *section = [FMLayoutDynamicSection sectionWithSectionInset:UIEdgeInsetsMake(5, 15, 5, 15) itemSpace:10 lineSpace:10 column:2]; section.cellFixedSize = 166; section.autoHeightFixedWidth = YES; section.itemDatas = [@[@1, @1, @1, @1, @1, @1] mutableCopy]; section.cellElement = [FMLayoutElement elementWithViewClass:[LS_HomeActivityCell class]]; __weak typeof(self) weakSelf = self; [section setConfigureCellData:^(FMLayoutBaseSection * _Nonnull section, UICollectionViewCell * _Nonnull cell, NSInteger item) { if (item == 0) { ((LS_HomeActivityCell *)cell).introLabel.text = @" 一些描述\n爱神的箭埃里克森基多拉\n离开时尽量少肯德基分离式的"; return; } if (item == 1) { ((LS_HomeActivityCell *)cell).introLabel.text = @" 一些描述\n爱神的箭埃里克森基多拉\n离开时尽量少肯德基分离式的\n爱神的箭埃里克森基多拉\n离开时尽量少肯德基分离式的"; return; } if (item == 2) { ((LS_HomeActivityCell *)cell).introLabel.text = @" 一些描述"; return; } if (item == 3) { if (weakSelf.twoChangeed) { ((LS_HomeActivityCell *)cell).introLabel.text = @" 一些描述\n爱神的箭埃里克森基多拉\n离开时尽量少\n离开时尽量少肯德基分离式的一些描述\n爱神的箭埃里克森基多拉\n离开时尽量少\n离开时尽量少肯德基分离式的一些描述\n爱神的箭埃里克森基多拉\n离开时尽量少\n离开时尽量少肯德基分离式的一些描述\n爱神的箭埃里克森基多拉\n离开时尽量少\n离开时尽量少肯德基分离式的"; return; } else { ((LS_HomeActivityCell *)cell).introLabel.text = @" 一些描述\n爱神的箭埃里克森基多拉\n"; return; } } ((LS_HomeActivityCell *)cell).introLabel.text = @" 一些描述\n爱神的箭埃里克森基多拉\n离开时尽量少"; }]; self.secondSection = section; [self.shareSections addObject:section]; } { FMLayoutAbsoluteSection *section = [FMLayoutAbsoluteSection sectionWithSectionInset:UIEdgeInsetsMake(0, 0, 0, 0) itemSpace:0 lineSpace:0 column:0]; section.itemDatas = [@[@"1", @"2", @"3"] mutableCopy]; section.cellElement = [FMLayoutElement elementWithViewClass:[FMCollectionCustomCell class]]; [section setFrameBlock:^CGRect(id _Nonnull section, NSInteger item) { switch (item) { case 0: return CGRectMake(0, 0, 100, 100); case 1: return CGRectMake(200, 100, 150, 100); case 2: return CGRectMake(100, 400, 400, 90); default: return CGRectZero; break; } }]; [self.shareSections addObject:section]; } FMLayoutView *view = [[FMLayoutView alloc] init]; self.automaticallyAdjustsScrollViewInsets = NO; view.delegate = self; [view.layout setSections:self.shareSections]; view.backgroundColor = [UIColor whiteColor]; [self.view addSubview:view]; [view mas_makeConstraints:^(MASConstraintMaker *make) { make.left.right.bottom.mas_equalTo(0); make.top.mas_equalTo(100); }]; self.collectionView = view; } @end ================================================ FILE: Example/FMLayoutKit/FMAotuSizeReusableView.h ================================================ // // FMAotuSizeReusableView.h // FMLayoutKit_Example // // Created by 郑桂华 on 2020/7/3. // Copyright © 2020 zhoufaming251@163.com. All rights reserved. // #import NS_ASSUME_NONNULL_BEGIN @interface FMAotuSizeReusableView : UICollectionReusableView @property(nonatomic, weak)UILabel *contentLabel; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FMLayoutKit/FMAotuSizeReusableView.m ================================================ // // FMAotuSizeReusableView.m // FMLayoutKit_Example // // Created by 郑桂华 on 2020/7/3. // Copyright © 2020 zhoufaming251@163.com. All rights reserved. // #import "FMAotuSizeReusableView.h" #import @implementation FMAotuSizeReusableView - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.backgroundColor = UIColor.cyanColor; UILabel *label = [[UILabel alloc] init]; label.text = @"自动布局高度大小"; [self addSubview:label]; [label mas_makeConstraints:^(MASConstraintMaker *make) { make.centerX.mas_equalTo(0); make.top.mas_equalTo(20); }]; UILabel *content = [[UILabel alloc] init]; content.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 40; content.text = @"内容\n内容埃里克森基多拉可接受的拉可视角度阿拉山口基多拉刷卡机的啦可视角度拉克丝基多拉可视角度拉克丝基多拉可视角度拉手孔"; content.numberOfLines = 0; [self addSubview:content]; [content mas_makeConstraints:^(MASConstraintMaker *make) { make.left.mas_equalTo(20); make.right.mas_equalTo(-20); make.top.mas_equalTo(label.mas_bottom).offset(20); make.bottom.mas_equalTo(-20); }]; self.contentLabel = content; } return self; } @end ================================================ FILE: Example/FMLayoutKit/FMAppDelegate.h ================================================ // // FMAppDelegate.h // FMCollectionLayout // // Created by 周发明 on 04/01/2020. // Copyright (c) 2020 周发明. All rights reserved. // @import UIKit; @interface FMAppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; @end ================================================ FILE: Example/FMLayoutKit/FMAppDelegate.m ================================================ // // FMAppDelegate.m // FMCollectionLayout // // Created by 周发明 on 04/01/2020. // Copyright (c) 2020 周发明. All rights reserved. // #import "FMAppDelegate.h" /// pod trunk push FMLayoutKit.podspec --allow-warnings @implementation FMAppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. return YES; } - (void)applicationWillResignActive:(UIApplication *)application { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. } - (void)applicationDidEnterBackground:(UIApplication *)application { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } - (void)applicationWillEnterForeground:(UIApplication *)application { // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. } - (void)applicationDidBecomeActive:(UIApplication *)application { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. } - (void)applicationWillTerminate:(UIApplication *)application { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } @end ================================================ FILE: Example/FMLayoutKit/FMCollViewController.h ================================================ // // FMCollViewController.h // FMCollectionLayout_Example // // Created by 周发明 on 2020/4/11. // Copyright © 2020 周发明. All rights reserved. // #import NS_ASSUME_NONNULL_BEGIN @interface FMCollViewController : UIViewController @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FMLayoutKit/FMCollViewController.m ================================================ // // FMCollViewController.m // FMCollectionLayout_Example // // Created by 周发明 on 2020/4/11. // Copyright © 2020 周发明. All rights reserved. // #import "FMCollViewController.h" #import #import #import "FMAddViewController.h" #import "FMCollectionCustomDecoration.h" #import "FMCollectionCustomCell.h" #import "FMCollectionNavTitleView.h" #import "LS_HomeActivityCell.h" #import "FMCollectionViewCell.h" #import "FMFPSLabel.h" @interface FMCollViewController () @property(nonatomic, strong)NSMutableArray *shareSections; @property(nonatomic, weak)FMLayoutView *collectionView; @end @implementation FMCollViewController - (void)dealloc{ NSLog(@"FMCollViewController dealloc"); } - (void)reloadSection{ FMLayoutBaseSection *section = [self.shareSections[2] copy]; [self.collectionView.sections insertObject:section atIndex:1]; [self.collectionView reloadData]; } - (void)addItem{ [[self.shareSections firstObject].itemDatas addObject:@"1"]; [self.collectionView reloadData]; } - (void)insetItem{ [[self.shareSections firstObject].itemDatas insertObject:@"1" atIndex:0]; [self.collectionView reloadData]; } - (void)deleteSection{ [self.collectionView.sections removeObjectAtIndex:1]; // [self.collectionView reloadData]; } - (void)deleteItem{ [[self.shareSections firstObject].itemDatas removeObjectAtIndex:1]; [self.collectionView reloadData]; } - (void)reloadItem{ [[self.shareSections firstObject] markChangeAt:3]; // [self.collectionView reloadData]; } - (void)addSection{ { FMLayoutFixedSection *section = [FMLayoutFixedSection sectionWithSectionInset:UIEdgeInsetsMake(0, 15, 15, 15) itemSpace:10 lineSpace:10 column:3]; section.header = [FMLayoutHeader elementSize:100 viewClass:[FMCollectionCustomDecoration class]]; section.header.lastMargin = 10; section.header.type = FMLayoutHeaderTypeSuspension; section.header.inset = UIEdgeInsetsMake(0, -15, 0, -15); section.footer = [FMLayoutFooter elementSize:50 viewClass:[FMCollectionCustomDecoration class]]; section.footer.topMargin = 10; section.itemSize = CGSizeMake(100, 100); section.itemDatas = [@[@"1", @"2", @"3", @"1", @"2", @"3"] mutableCopy]; section.cellElement = [FMLayoutElement elementWithViewClass:[FMCollectionCustomCell class]]; // [self.shareSections addObject:section]; [self.collectionView.sections addObject:section]; } [self.collectionView reloadData]; } //- (void)addItem{ // [[self.shareSections firstObject].itemDatas removeObjectAtIndex:1]; // [self.collectionView reloadData]; //} - (void)viewDidLoad { [super viewDidLoad]; self.navigationItem.title = @"纵向布局"; __weak typeof(self) weakSelf = self; self.view.backgroundColor = [UIColor redColor]; UIBarButtonItem *item1 = [[UIBarButtonItem alloc] initWithTitle:@"插组" style:UIBarButtonItemStyleDone target:self action:@selector(reloadSection)]; UIBarButtonItem *item2 = [[UIBarButtonItem alloc] initWithTitle:@"插单" style:UIBarButtonItemStyleDone target:self action:@selector(insetItem)]; UIBarButtonItem *item11 = [[UIBarButtonItem alloc] initWithTitle:@"删组" style:UIBarButtonItemStyleDone target:self action:@selector(deleteSection)]; UIBarButtonItem *item22 = [[UIBarButtonItem alloc] initWithTitle:@"删单" style:UIBarButtonItemStyleDone target:self action:@selector(deleteItem)]; UIBarButtonItem *item111 = [[UIBarButtonItem alloc] initWithTitle:@"加组" style:UIBarButtonItemStyleDone target:self action:@selector(addSection)]; UIBarButtonItem *item222 = [[UIBarButtonItem alloc] initWithTitle:@"加单" style:UIBarButtonItemStyleDone target:self action:@selector(addItem)]; UIBarButtonItem *item2222 = [[UIBarButtonItem alloc] initWithTitle:@"刷单" style:UIBarButtonItemStyleDone target:self action:@selector(reloadItem)]; self.navigationItem.rightBarButtonItems = @[item2, item1, item22, item11, item111, item222, item2222]; self.shareSections = [NSMutableArray array]; { FMLayoutFixedSection *section = [FMLayoutFixedSection sectionWithSectionInset:UIEdgeInsetsMake(20, 15, 15, 15) itemSpace:10 lineSpace:10 column:2]; section.header = [FMLayoutHeader elementSize:100 viewClass:[FMCollectionCustomDecoration class]]; section.header.lastMargin = 10; section.header.type = FMLayoutHeaderTypeSuspensionBigger; // section.header.minSize = 50; section.header.isStickTop = YES; section.header.inset = UIEdgeInsetsMake(0, -15, 0, -15); [section setConfigureHeaderData:^(FMLayoutBaseSection * _Nonnull section, UICollectionReusableView * _Nonnull header) { FMCollectionCustomDecoration *customHeader = (FMCollectionCustomDecoration *)header; customHeader.textLabel.text = @"固定大小, 从左往右从上往下排的分组, 头部放大缩放效果"; }]; section.footer = [FMLayoutFooter elementSize:50 viewClass:[FMCollectionCustomDecoration class]]; section.footer.topMargin = 10; section.itemSize = CGSizeMake(200, 100); section.itemDatas = [@[@"1", @"2", @"3"] mutableCopy]; section.cellElement = [FMLayoutElement elementWithViewClass:[FMCollectionViewCell class] isNib:YES]; [section setConfigureCellData:^(FMLayoutBaseSection * _Nonnull section, UICollectionViewCell * _Nonnull cell, NSInteger item) { }]; [section setClickCellBlock:^(FMLayoutBaseSection * _Nonnull section, NSInteger item) { FMAddViewController *add = [[FMAddViewController alloc] init]; [weakSelf.navigationController pushViewController:add animated:YES]; }]; [self.shareSections addObject:section]; } { FMLayoutDynamicSection *section = [FMLayoutDynamicSection sectionWithSectionInset:UIEdgeInsetsMake(5, 15, 5, 15) itemSpace:10 lineSpace:10 column:2]; section.header = [FMLayoutHeader elementSize:50 viewClass:[FMCollectionCustomDecoration class]]; section.header.zIndex = FMLayoutZIndexFrontOfItem; section.header.type = FMLayoutHeaderTypeFixed; [section setConfigureHeaderData:^(FMLayoutBaseSection * _Nonnull section, UICollectionReusableView * _Nonnull header) { FMCollectionCustomDecoration *customHeader = (FMCollectionCustomDecoration *)header; customHeader.textLabel.text = @"自动适应高度布局, 续固定宽度"; }]; section.cellFixedSize = 166; section.autoHeightFixedWidth = YES; //, @1, @1, @1, @1 section.itemDatas = [@[@1, @1] mutableCopy]; section.cellElement = [FMLayoutElement elementWithViewClass:[LS_HomeActivityCell class]]; [section setConfigureCellData:^(FMLayoutBaseSection * _Nonnull section, UICollectionViewCell * _Nonnull cell, NSInteger item) { if (item == 0) { ((LS_HomeActivityCell *)cell).introLabel.text = @" 一些描述\n爱神的箭埃里克森基多拉\n离开时尽量少肯德基分离式的"; return; } if (item == 1) { ((LS_HomeActivityCell *)cell).introLabel.text = @" 一些描述\n爱神的箭埃里克森基多拉\n离开时尽量少肯德基分离式的\n爱神的箭埃里克森基多拉\n离开时尽量少肯德基分离式的"; return; } if (item == 2) { ((LS_HomeActivityCell *)cell).introLabel.text = @" 一些描述"; return; } if (item == 3) { ((LS_HomeActivityCell *)cell).introLabel.text = @" 一些描述\n爱神的箭埃里克森基多拉\n离开时尽量少\n离开时尽量少肯德基分离式的一些描述\n爱神的箭埃里克森基多拉\n离开时尽量少\n离开时尽量少肯德基分离式的一些描述\n爱神的箭埃里克森基多拉\n离开时尽量少\n离开时尽量少肯德基分离式的一些描述\n爱神的箭埃里克森基多拉\n离开时尽量少\n离开时尽量少肯德基分离式的"; return; } ((LS_HomeActivityCell *)cell).introLabel.text = @" 一些描述\n一些描述"; }]; // [self.shareSections addObject:section]; } { FMLayoutFixedSection *section = [FMLayoutFixedSection sectionWithSectionInset:UIEdgeInsetsMake(0, 0, 0, 0) itemSpace:10 lineSpace:10 column:3]; section.header = [FMLayoutHeader elementSize:150 viewClass:[FMCollectionCustomDecoration class]]; section.header.zIndex = FMLayoutZIndexFrontAlways; section.header.type = FMLayoutHeaderTypeSuspensionAlways; section.header.lastMargin = 10; [section setConfigureHeaderData:^(FMLayoutBaseSection * _Nonnull section, UICollectionReusableView * _Nonnull header) { FMCollectionCustomDecoration *customHeader = (FMCollectionCustomDecoration *)header; customHeader.textLabel.text = @"固定大小, 从左往右从上往下排的分组, 可横向滚动, 可设置多行, 头部悬停, 跟着分组滚动(类似table的section的plain模式)"; }]; // section.isHorizontalCanScroll = YES; section.itemSize = CGSizeMake(150, 100); section.itemDatas = [@[@"1", @"2", @"3", @"1", @"2", @"3", @"1", @"2", @"3", @"1", @"2", @"3", ] mutableCopy]; section.cellElement = [FMLayoutElement elementWithViewClass:[FMCollectionCustomCell class]]; [section setConfigureCellLayoutAttributes:^(id _Nonnull section, UICollectionViewLayoutAttributes * _Nonnull attributes, NSInteger item) { if (item == 10) { attributes.transform = CGAffineTransformMakeRotation(M_PI_4); attributes.zIndex = FMLayoutZIndexFrontOfItem; } }]; // [self.shareSections addObject:section]; [self.shareSections addObject:[FMLayoutCrossSection sectionAutoWithSection:section]]; } { FMLayoutFillSection *section = [[FMLayoutFillSection alloc] init]; section.itemDatas = [@[@"1", @"2", @"3", @"1", @"2", @"3", @"1", @"2", @"3", @"1", @"2", @"3", @"1", @"2", @"3",] mutableCopy]; section.sectionInset = UIEdgeInsetsMake(10, 10, 10, 10); section.header = [FMLayoutHeader elementSize:50 viewClass:[FMCollectionCustomDecoration class]]; // section.header.suspensionTopMargin = 150; section.header.zIndex = FMLayoutZIndexFrontAlways; section.header.type = FMLayoutHeaderTypeSuspensionAlways; [section setConfigureHeaderData:^(FMLayoutBaseSection * _Nonnull section, UICollectionReusableView * _Nonnull header) { FMCollectionCustomDecoration *customHeader = (FMCollectionCustomDecoration *)header; customHeader.textLabel.text = @"填充布局,寻找合适的空档,支持多种cell, header样式一直悬停在顶部"; }]; section.cellElement = [FMLayoutElement elementWithViewClass:[FMCollectionCustomCell class]]; [section setSizeBlock:^CGSize(id _Nonnull section, NSInteger item) { switch (item) { case 2: return CGSizeMake(150, 140.32); case 5: return CGSizeMake((weakSelf.view.frame.size.width-20-150)/2, 70.19); case 8: case 11: return CGSizeMake(100, 240); case 10: return CGSizeMake(weakSelf.view.frame.size.width-20-200, 140); case 9: case 12: return CGSizeMake(weakSelf.view.frame.size.width-20-100, 100); case 0: case 1: case 3: case 4: return CGSizeMake((weakSelf.view.frame.size.width-20-150)/4, 70.13); default: return CGSizeMake((weakSelf.view.frame.size.width-20-150)/4, 70.19); } }]; // [section setConfigureCellLayoutAttributes:^(id _Nonnull section, UICollectionViewLayoutAttributes * _Nonnull attributes, NSInteger item) { // if (item == 10) { // attributes.transform = CGAffineTransformMakeRotation(M_PI_4); // } // }]; [section setConfigureCellData:^(FMLayoutBaseSection * _Nonnull section, UICollectionViewCell * _Nonnull cell, NSInteger item) { FMCollectionCustomCell *customCell = (FMCollectionCustomCell *)cell; customCell.label.text = [NSString stringWithFormat:@"%ld", item]; }]; [self.shareSections addObject:section]; } { FMLayoutDynamicSection *section = [FMLayoutDynamicSection sectionWithSectionInset:UIEdgeInsetsMake(10, 0, 0, 0) itemSpace:0 lineSpace:10 column:1]; section.header = [FMLayoutHeader elementSize:50 viewClass:[FMCollectionCustomDecoration class]]; section.header.zIndex = FMLayoutZIndexFrontOfItem; section.header.type = FMLayoutHeaderTypeFixed; [section setConfigureHeaderData:^(FMLayoutBaseSection * _Nonnull section, UICollectionReusableView * _Nonnull header) { FMCollectionCustomDecoration *customHeader = (FMCollectionCustomDecoration *)header; customHeader.textLabel.text = @"列表的样式, 支持多种cell, 当前手动返回计算返回高度"; }]; section.footer = [FMLayoutFooter elementSize:50 viewClass:[FMCollectionCustomDecoration class]]; section.footer.topMargin = 10; section.itemDatas = [@[@"1", @"2", @"3"] mutableCopy]; section.cellElement = [FMLayoutElement elementWithViewClass:[FMCollectionCustomCell class]]; section.cellFixedSize = [UIScreen mainScreen].bounds.size.width; [section setOtherBlock:^CGFloat(id _Nonnull section, NSInteger item) { return 100 + item * 100; }]; [self.shareSections addObject:section]; } { FMLayoutDynamicSection *section = [FMLayoutDynamicSection sectionWithSectionInset:UIEdgeInsetsMake(10, 0, 0, 0) itemSpace:10 lineSpace:10 column:2]; section.header = [FMLayoutHeader elementSize:50 viewClass:[FMCollectionCustomDecoration class]]; section.header.zIndex = FMLayoutZIndexFrontOfItem; section.header.type = FMLayoutHeaderTypeFixed; [section setConfigureHeaderData:^(FMLayoutBaseSection * _Nonnull section, UICollectionReusableView * _Nonnull header) { FMCollectionCustomDecoration *customHeader = (FMCollectionCustomDecoration *)header; customHeader.textLabel.text = @"瀑布流, 列表也就是单列, 列数可设置"; }]; section.footer = [FMLayoutFooter elementSize:50 viewClass:[FMCollectionCustomDecoration class]]; section.footer.topMargin = 10; section.itemDatas = [@[@"1", @"2", @"3", @"2", @"3", @"2", @"3"] mutableCopy]; section.cellElement = [FMLayoutElement elementWithViewClass:[FMCollectionCustomCell class]]; section.cellFixedSize = ([UIScreen mainScreen].bounds.size.width - 10) * 0.5; [section setOtherBlock:^CGFloat(id _Nonnull section, NSInteger item) { return 100 + item * 30; }]; [self.shareSections addObject:section]; } { FMLayoutLabelSection *section = [FMLayoutLabelSection sectionWithSectionInset:UIEdgeInsetsMake(10, 10, 10, 10) itemSpace:10 lineSpace:10 column:3]; section.header = [FMLayoutHeader elementSize:50 viewClass:[FMCollectionCustomDecoration class]]; section.header.zIndex = FMLayoutZIndexFrontOfItem; section.header.type = FMLayoutHeaderTypeFixed; section.header.lastMargin = 10; [section setConfigureHeaderData:^(FMLayoutBaseSection * _Nonnull section, UICollectionReusableView * _Nonnull header) { FMCollectionCustomDecoration *customHeader = (FMCollectionCustomDecoration *)header; customHeader.textLabel.text = @"标签式布局, 单行横向滚动模式"; }]; // section.isSingleLineCanScroll = YES; section.maxLine = 6; section.cellFixedHeight = 40; [section setWidthBlock:^CGFloat(id _Nonnull section, NSInteger item) { return item * 20 + 100; }]; section.itemDatas = [@[@"1", @"2", @"3", @"1", @"2", @"3", @"1", @"2", @"3", @"1", @"2", @"3", ] mutableCopy]; section.cellElement = [FMLayoutElement elementWithViewClass:[FMCollectionCustomCell class]]; [self.shareSections addObject:section]; } { FMLayoutLabelSection *section = [FMLayoutLabelSection sectionWithSectionInset:UIEdgeInsetsMake(0, 10, 0, 10) itemSpace:10 lineSpace:10 column:3]; section.header = [FMLayoutHeader elementSize:50 viewClass:[FMCollectionCustomDecoration class]]; section.header.zIndex = FMLayoutZIndexFrontOfItem; section.header.type = FMLayoutHeaderTypeFixed; section.header.lastMargin = 10; [section setConfigureHeaderData:^(FMLayoutBaseSection * _Nonnull section, UICollectionReusableView * _Nonnull header) { FMCollectionCustomDecoration *customHeader = (FMCollectionCustomDecoration *)header; customHeader.textLabel.text = @"标签式布局, 多行模式"; }]; section.maxLine = 6; section.cellFixedHeight = 40; [section setWidthBlock:^CGFloat(id _Nonnull section, NSInteger item) { return item * 20 + 100; }]; section.itemDatas = [@[@"1", @"2", @"3", @"1", @"2", @"3", @"1", @"2", @"3", @"1", @"2", @"3", ] mutableCopy]; section.cellElement = [FMLayoutElement elementWithViewClass:[FMCollectionCustomCell class]]; [self.shareSections addObject:section]; } FMLayoutView *view = [[FMLayoutView alloc] init]; self.automaticallyAdjustsScrollViewInsets = NO; view.delegate = self; // view.reloadOlnyChanged = NO; [view.layout setSections:self.shareSections]; view.backgroundColor = [UIColor whiteColor]; [self.view addSubview:view]; [view mas_makeConstraints:^(MASConstraintMaker *make) { make.left.right.bottom.mas_equalTo(0); make.top.mas_equalTo(100); }]; self.collectionView = view; // [self.collectionView layoutIfNeeded]; } - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{ NSLog(@"collectionView:didSelectItemAtIndexPath"); } - (void)scrollViewDidScroll:(UIScrollView *)scrollView{ NSLog(@"scrollViewDidScroll"); } @end ================================================ FILE: Example/FMLayoutKit/FMCollectionCustomCell.h ================================================ // // FMCollectionCustomCell.h // FMCollectionLayout_Example // // Created by 周发明 on 2020/4/8. // Copyright © 2020 周发明. All rights reserved. // #import NS_ASSUME_NONNULL_BEGIN @interface FMCollectionCustomCell : UICollectionViewCell @property(nonatomic, weak)UILabel *label; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FMLayoutKit/FMCollectionCustomCell.m ================================================ // // FMCollectionCustomCell.m // FMCollectionLayout_Example // // Created by 周发明 on 2020/4/8. // Copyright © 2020 周发明. All rights reserved. // #import "FMCollectionCustomCell.h" #import @implementation FMCollectionCustomCell - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { NSInteger aRedValue =arc4random() %255; NSInteger aGreenValue =arc4random() %255; NSInteger aBlueValue =arc4random() %255; UIColor*randColor = [UIColor colorWithRed:aRedValue /255.0f green:aGreenValue /255.0f blue:aBlueValue /255.0f alpha:1.0f]; self.contentView.backgroundColor = randColor; UILabel *label = [[UILabel alloc] init]; label.numberOfLines = 0; label.textAlignment = NSTextAlignmentCenter; label.text = NSStringFromClass(self.class); [self.contentView addSubview:label]; [label mas_makeConstraints:^(MASConstraintMaker *make) { make.left.right.top.bottom.mas_equalTo(0); }]; self.label = label; } return self; } - (void)layoutSubviews{ [super layoutSubviews]; } - (void)applyLayoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes{ NSLog(@"cell:%p attr:%p", self, layoutAttributes); [super applyLayoutAttributes:layoutAttributes]; } @end ================================================ FILE: Example/FMLayoutKit/FMCollectionCustomDecoration.h ================================================ // // FMCollectionCustomDecoration.h // FMCollectionLayout_Example // // Created by 周发明 on 2020/4/8. // Copyright © 2020 周发明. All rights reserved. // #import NS_ASSUME_NONNULL_BEGIN @interface FMCollectionCustomDecoration : UICollectionReusableView @property(nonatomic, weak)UILabel *textLabel; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FMLayoutKit/FMCollectionCustomDecoration.m ================================================ // // FMCollectionCustomDecoration.m // FMCollectionLayout_Example // // Created by 周发明 on 2020/4/8. // Copyright © 2020 周发明. All rights reserved. // #import "FMCollectionCustomDecoration.h" #import @implementation FMCollectionCustomDecoration - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // NSInteger aRedValue =arc4random() %255; // NSInteger aGreenValue =arc4random() %255; // NSInteger aBlueValue =arc4random() %255; // UIColor*randColor = [UIColor colorWithRed:aRedValue /255.0f green:aGreenValue /255.0f blue:aBlueValue /255.0f alpha:1.0f]; // self.backgroundColor = randColor; UIImageView *imageV = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"timg"]]; imageV.contentMode = UIViewContentModeScaleAspectFill; imageV.clipsToBounds = YES; [self addSubview:imageV]; [imageV mas_makeConstraints:^(MASConstraintMaker *make) { make.left.right.top.bottom.mas_equalTo(0); }]; UILabel *text = [[UILabel alloc] init]; text.numberOfLines = 0; text.textColor = [UIColor whiteColor]; [self addSubview:text]; [text mas_makeConstraints:^(MASConstraintMaker *make) { make.left.centerY.right.mas_equalTo(0); }]; self.textLabel = text; } return self; } - (void)layoutSubviews{ [super layoutSubviews]; } @end ================================================ FILE: Example/FMLayoutKit/FMCollectionNavTitleView.h ================================================ // // FMCollectionNavTitleView.h // FMCollectionLayout_Example // // Created by 周发明 on 2020/4/9. // Copyright © 2020 周发明. All rights reserved. // #import #import NS_ASSUME_NONNULL_BEGIN @interface FMCollectionNavTitleView : UICollectionReusableView @property(nonatomic, copy)NSArray *titles; @property(nonatomic, copy)void(^clickBlock)(NSInteger tag); - (void)selectWithIndex:(NSInteger)index; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FMLayoutKit/FMCollectionNavTitleView.m ================================================ // // FMCollectionNavTitleView.m // FMCollectionLayout_Example // // Created by 周发明 on 2020/4/9. // Copyright © 2020 周发明. All rights reserved. // #import "FMCollectionNavTitleView.h" #import @interface FMCollectionNavTitleView () @property(nonatomic, weak)UIView *contentView; @property(nonatomic, weak)UIButton *selectBtn; @property(nonatomic, strong)NSMutableArray *btns; @end @implementation FMCollectionNavTitleView - (void)selectWithIndex:(NSInteger)index{ self.selectBtn = [self viewWithTag:index + 100]; } - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { UIView *contentView = [[UIView alloc] init]; [self addSubview:contentView]; [contentView mas_makeConstraints:^(MASConstraintMaker *make) { make.left.right.bottom.mas_equalTo(0); make.height.mas_equalTo(100); }]; self.contentView = contentView; self.contentView.backgroundColor = [UIColor greenColor]; self.btns = [NSMutableArray array]; [self reCreateBtns]; } return self; } - (void)setSelectBtn:(UIButton *)selectBtn{ _selectBtn.selected = NO; _selectBtn = selectBtn; _selectBtn.selected = YES; } - (void)reCreateBtns{ self.titles = @[@"标签1", @"标签2", @"标签3", @"标签4"]; UIButton *left = nil; CGFloat multiplied = 1 / (self.titles.count * 1.0); for (int i = 0; i < self.titles.count; i++) { NSString *title = self.titles[i]; UIButton *btn = [[UIButton alloc] init]; btn.tag = 100+i; btn.titleLabel.font = [UIFont systemFontOfSize:16]; [btn setTitle:title forState:UIControlStateNormal]; [btn setTitleColor:[UIColor blackColor] forState:UIControlStateSelected]; [btn setTitleColor:[UIColor orangeColor] forState:UIControlStateNormal]; [btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside]; [self.contentView addSubview:btn]; [btn mas_makeConstraints:^(MASConstraintMaker *make) { if (left) { make.left.mas_equalTo(left.mas_right); } else { make.left.mas_equalTo(0); } make.top.bottom.mas_equalTo(0); make.width.mas_equalTo(self.mas_width).multipliedBy(multiplied); }]; [self.btns addObject:btn]; left = btn; if (i == 0) { self.selectBtn = btn; } } [self btnClick:self.selectBtn]; } - (void)btnClick:(UIButton *)sender{ !self.clickBlock?:self.clickBlock(sender.tag-100); self.selectBtn = sender; } - (void)teslaSuspensionHeaderShouldShowHeight:(CGFloat)showHeight{ [self.contentView mas_updateConstraints:^(MASConstraintMaker *make) { make.height.mas_equalTo(showHeight); }]; for (UIButton *btn in self.btns) { btn.titleLabel.font = [UIFont systemFontOfSize:16 + (100 - showHeight) / 40.0 * 10]; } } @end ================================================ FILE: Example/FMLayoutKit/FMCollectionViewCell.h ================================================ // // FMCollectionViewCell.h // FMLayoutKit_Example // // Created by 周发明 on 2020/6/15. // Copyright © 2020 zhoufaming251@163.com. All rights reserved. // #import NS_ASSUME_NONNULL_BEGIN @interface FMCollectionViewCell : UICollectionViewCell @property (weak, nonatomic) IBOutlet UILabel *label; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FMLayoutKit/FMCollectionViewCell.m ================================================ // // FMCollectionViewCell.m // FMLayoutKit_Example // // Created by 周发明 on 2020/6/15. // Copyright © 2020 zhoufaming251@163.com. All rights reserved. // #import "FMCollectionViewCell.h" @implementation FMCollectionViewCell - (void)awakeFromNib { [super awakeFromNib]; self.contentView.backgroundColor = [UIColor cyanColor]; } @end ================================================ FILE: Example/FMLayoutKit/FMCollectionViewCell.xib ================================================ ================================================ FILE: Example/FMLayoutKit/FMCombineViewController.h ================================================ // // FMCombineViewController.h // FMLayoutKit_Example // // Created by 郑桂华 on 2020/7/12. // Copyright © 2020 zhoufaming251@163.com. All rights reserved. // #import NS_ASSUME_NONNULL_BEGIN @interface FMCombineViewController : UIViewController @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FMLayoutKit/FMCombineViewController.m ================================================ // // FMCombineViewController.m // FMLayoutKit_Example // // Created by 郑桂华 on 2020/7/12. // Copyright © 2020 zhoufaming251@163.com. All rights reserved. // #import "FMCombineViewController.h" #import #import #import "FMCollectionCustomDecoration.h" #import "FMCollectionCustomCell.h" #import "FMAddViewController.h" #import "FMCollectionViewCell.h" #import "LS_HomeActivityCell.h" @interface FMDeletePanGestureRecognizer : UIPanGestureRecognizer @property(nonatomic, assign)BOOL isLeft; @end @implementation FMDeletePanGestureRecognizer @end @interface FMCollectionDeleteCell : UICollectionViewCell @property(nonatomic, assign)CGFloat handleViewWidth; @end @implementation FMCollectionDeleteCell - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.handleViewWidth = 100; NSInteger aRedValue =arc4random() %255; NSInteger aGreenValue =arc4random() %255; NSInteger aBlueValue =arc4random() %255; UIColor*randColor = [UIColor colorWithRed:aRedValue /255.0f green:aGreenValue /255.0f blue:aBlueValue /255.0f alpha:1.0f]; self.contentView.backgroundColor = randColor; UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGesture:)]; pan.delegate = self; [self addGestureRecognizer:pan]; } return self; } - (void)panGesture:(UIPanGestureRecognizer *)pan{ CGPoint translate = [pan translationInView:self]; NSLog(@"translate: %@", [NSValue valueWithCGPoint:translate]); switch (pan.state) { case UIGestureRecognizerStateBegan: break; case UIGestureRecognizerStateChanged: { if (-translate.x < self.handleViewWidth) { self.transform = CGAffineTransformMakeTranslation(translate.x, 0); } } break; case UIGestureRecognizerStateEnded: { if (-translate.x < self.handleViewWidth * 0.5) { [UIView animateWithDuration:0.2 animations:^{ self.transform = CGAffineTransformIdentity; }]; } else { [UIView animateWithDuration:0.2 animations:^{ self.transform = CGAffineTransformMakeTranslation(-self.handleViewWidth, 0);; }]; } } default: break; } } - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{ CGPoint vel = [(UIPanGestureRecognizer *)gestureRecognizer velocityInView:self]; if (fabs(vel.y) < 20 && vel.x < 0) { return YES; } return NO; } @end @interface FMCombineViewController () @property(nonatomic, weak)FMLayoutView *collectionView; @end @implementation FMCombineViewController - (void)viewDidLoad { [super viewDidLoad]; FMLayoutView *view = [[FMLayoutView alloc] init]; // view.layout.minContentSize = 1000; view.backgroundColor = [UIColor whiteColor]; [self.view addSubview:view]; [view mas_makeConstraints:^(MASConstraintMaker *make) { make.left.right.bottom.mas_equalTo(0); make.top.mas_equalTo(100); }]; self.collectionView = view; // [self addSections]; [self addCrossFixedSections]; // [self addScaleSection]; // self.collectionView.enableLongPressDrag = YES; // [self.collectionView setConfigureSourceView:^UIView * _Nonnull(UICollectionViewCell * _Nonnull sourceCell) { // UIView *source = [[UIView alloc] initWithFrame:sourceCell.frame]; // source.backgroundColor = [UIColor purpleColor]; // return source; // }]; // self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"刷新" style:UIBarButtonItemStylePlain target:self.collectionView action:@selector(reloadData)]; } - (void)addSections{ NSMutableArray *sections = [NSMutableArray array]; self.automaticallyAdjustsScrollViewInsets = NO; __weak typeof(self) weakSelf = self; { FMLayoutFixedSection *section = [FMLayoutFixedSection sectionWithSectionInset:UIEdgeInsetsMake(20, 15, 15, 15) itemSpace:10 lineSpace:10 column:2]; section.header = [FMLayoutHeader elementSize:100 viewClass:[FMCollectionCustomDecoration class] isNib:NO reuseIdentifier:@"按实际大嫂家打卡机塑料袋卡死来得快"]; section.header.lastMargin = 10; section.header.type = FMLayoutHeaderTypeSuspensionBigger; section.header.minSize = 50; section.header.isStickTop = YES; section.header.inset = UIEdgeInsetsMake(0, -15, 0, -15); [section setConfigureHeaderData:^(FMLayoutBaseSection * _Nonnull section, UICollectionReusableView * _Nonnull header) { FMCollectionCustomDecoration *customHeader = (FMCollectionCustomDecoration *)header; customHeader.textLabel.text = @"固定大小, 从左往右从上往下排的分组, 头部放大缩放效果"; }]; section.footer = [FMLayoutFooter elementSize:50 viewClass:[FMCollectionCustomDecoration class]]; section.footer.topMargin = 10; section.itemSize = CGSizeMake(200, 100); section.itemDatas = [@[@"1", @"2", @"3", @"4", @"5", @"6", @"7", @"8", @"9"] mutableCopy]; section.cellElement = [FMLayoutElement elementWithViewClass:[FMCollectionViewCell class] isNib:YES]; [section setConfigureCellData:^(FMLayoutBaseSection * _Nonnull section, UICollectionViewCell * _Nonnull cell, NSInteger item) { [(FMCollectionViewCell *)cell label].text = section.itemDatas[item]; }]; [section setClickCellBlock:^(FMLayoutBaseSection * _Nonnull section, NSInteger item) { FMAddViewController *add = [[FMAddViewController alloc] init]; [weakSelf.navigationController pushViewController:add animated:YES]; }]; section.canLongPressExchange = YES; [sections addObject:section]; } { NSMutableArray *subSections = [NSMutableArray array]; { FMLayoutFixedSection *section = [FMLayoutFixedSection sectionWithSectionInset:UIEdgeInsetsMake(0, 0, 0, 0) itemSpace:10 lineSpace:10 column:2]; section.itemSize = CGSizeMake(150, 100); section.itemDatas = [@[@"0-1", @"0-2", @"0-3", @"0-4", @"0-5", @"0-6", @"0-7", @"0-8", @"0-9", @"0-10", @"0-11"] mutableCopy]; section.cellElement = [FMLayoutElement elementWithViewClass:[FMCollectionCustomCell class]]; [section setConfigureCellData:^(FMLayoutBaseSection * _Nonnull section, UICollectionViewCell * _Nonnull cell, NSInteger item) { [(FMCollectionCustomCell *)cell label].text = section.itemDatas[item]; }]; [section setClickCellBlock:^(FMLayoutBaseSection * _Nonnull section, NSInteger item) { }]; [subSections addObject:section]; } { FMLayoutAbsoluteSection *section = [FMLayoutAbsoluteSection sectionWithSectionInset:UIEdgeInsetsMake(0, 0, 0, 0) itemSpace:0 lineSpace:0 column:0]; section.itemDatas = [@[@"1-1", @"1-2", @"1-3"] mutableCopy]; section.cellElement = [FMLayoutElement elementWithViewClass:[FMCollectionCustomCell class]]; [section setDeqCellReturnElement:^FMLayoutElement * _Nonnull(FMLayoutDynamicSection * _Nonnull section, NSInteger index) { return [section.cellElements lastObject]; }]; [section setFrameBlock:^CGRect(id _Nonnull section, NSInteger item) { switch (item) { case 0: return CGRectMake(0, 0, 100, 100); case 1: return CGRectMake(200, 100, 150, 100); case 2: return CGRectMake(100, 400, 400, 90); default: return CGRectZero; break; } }]; [section setConfigureCellData:^(FMLayoutBaseSection * _Nonnull section, UICollectionViewCell * _Nonnull cell, NSInteger item) { [(FMCollectionCustomCell *)cell label].text = section.itemDatas[item]; }]; [section setClickCellBlock:^(FMLayoutBaseSection * _Nonnull section, NSInteger item) { }]; [subSections addObject:section]; } FMLayoutCombineSection *section = [FMLayoutCombineSection combineSections:subSections]; [section setCanLongPressExchangeItem:^BOOL(id _Nonnull section, NSInteger item) { if (item < 2) { return NO; } return YES; }]; section.canLongPressExchange = YES; section.header = [FMLayoutHeader elementSize:50 viewClass:[FMCollectionCustomDecoration class]]; section.header.type = FMLayoutHeaderTypeSuspensionAlways; section.header.zIndex = FMLayoutZIndexFrontAlways; // section.header.isStickTop = YES; // section.header.inset = UIEdgeInsetsMake(0, -15, 0, -15); [section setConfigureHeaderData:^(FMLayoutBaseSection * _Nonnull section, UICollectionReusableView * _Nonnull header) { FMCollectionCustomDecoration *custom = (FMCollectionCustomDecoration *)header; custom.textLabel.text = @"第一个悬浮的顶部视图, 黏在顶部"; }]; section.footer = [FMLayoutFooter elementSize:100 viewClass:[FMCollectionCustomDecoration class]]; // section.footer.inset = UIEdgeInsetsMake(10, 0, 10, 0); section.footer.topMargin = 10; section.background = [FMLayoutBackground bgWithViewClass:[UICollectionReusableView class]]; section.background.inset = UIEdgeInsetsMake(10, 10, 10, 10); [section setConfigureBg:^(FMLayoutBaseSection * _Nonnull section, UICollectionReusableView * _Nonnull bg) { bg.backgroundColor = [UIColor yellowColor]; }]; { FMLayoutDynamicSection *dsection = [FMLayoutDynamicSection sectionWithSectionInset:UIEdgeInsetsMake(10, 0, 0, 0) itemSpace:0 lineSpace:10 column:1]; dsection.itemDatas = [@[@"1", @"2", @"3"] mutableCopy]; dsection.cellElement = [FMLayoutElement elementWithViewClass:[FMCollectionDeleteCell class]]; dsection.cellFixedSize = [UIScreen mainScreen].bounds.size.width; [dsection setOtherBlock:^CGFloat(id _Nonnull section, NSInteger item) { return 100 + item * 100; }]; [section appendSection:dsection]; } { FMLayoutDynamicSection *dsection = [FMLayoutDynamicSection sectionWithSectionInset:UIEdgeInsetsMake(10, 0, 0, 0) itemSpace:0 lineSpace:10 column:1]; dsection.itemDatas = [@[@"1", @"2", @"3"] mutableCopy]; dsection.cellElement = [FMLayoutElement elementWithViewClass:[FMCollectionDeleteCell class]]; dsection.cellFixedSize = [UIScreen mainScreen].bounds.size.width; [dsection setOtherBlock:^CGFloat(id _Nonnull section, NSInteger item) { return 100 + item * 100; }]; [section insetSection:dsection atIndex:1]; } [sections addObject:section]; } { FMLayoutDynamicSection *section = [FMLayoutDynamicSection sectionWithSectionInset:UIEdgeInsetsMake(10, 0, 0, 0) itemSpace:0 lineSpace:10 column:1]; section.canLongPressExchange = YES; section.moveType = FMLayoutLongMoveTable; section.header = [FMLayoutHeader elementSize:50 viewClass:[FMCollectionCustomDecoration class]]; section.header.zIndex = FMLayoutZIndexFrontOfItem; section.header.type = FMLayoutHeaderTypeFixed; [section setConfigureHeaderData:^(FMLayoutBaseSection * _Nonnull section, UICollectionReusableView * _Nonnull header) { FMCollectionCustomDecoration *customHeader = (FMCollectionCustomDecoration *)header; customHeader.textLabel.text = @"列表的样式, 支持多种cell, 当前手动返回计算返回高度"; }]; section.footer = [FMLayoutFooter elementSize:50 viewClass:[FMCollectionCustomDecoration class]]; section.footer.topMargin = 10; section.itemDatas = [@[@"1", @"2", @"3"] mutableCopy]; section.cellElement = [FMLayoutElement elementWithViewClass:[FMCollectionDeleteCell class]]; section.cellFixedSize = [UIScreen mainScreen].bounds.size.width; [section setOtherBlock:^CGFloat(id _Nonnull section, NSInteger item) { return 100 + item * 100; }]; [sections addObject:section]; } self.collectionView.sections = sections; [self.collectionView reloadData]; } - (void)addCrossFixedSections{ NSMutableArray *sections = [NSMutableArray array]; { FMLayoutFixedSection *section = [FMLayoutFixedSection sectionWithSectionInset:UIEdgeInsetsMake(50, 50, 50, 50) itemSpace:20 lineSpace:0 column:1]; section.itemSize = CGSizeMake([UIScreen mainScreen].bounds.size.width - 100, 300); section.cellElement = [FMLayoutElement elementWithViewClass:[FMCollectionCustomCell class]]; // section.itemDatas = [@[@"1", @"2", @"2", @"3", @"2", @"3", @"2", @"3", @"2", @"3", @"2", @"3"] mutableCopy]; FMLayoutCrossTransformSection *cSection = [FMLayoutCrossTransformSection sectionAutoWithSection:section]; cSection.transformType = FMLayoutCrossTransformScale; // [cSection setTransformBlock:^(UICollectionViewCell * _Nonnull cell, CGFloat progress) { // cell.la // }]; [sections addObject:cSection]; } self.collectionView.sections = sections; [self.collectionView reloadData]; } - (void)addScaleSection{ NSMutableArray *sections = [NSMutableArray array]; { FMLayoutScaleSection *section = [FMLayoutScaleSection sectionWithSectionInset:UIEdgeInsetsMake(10, 10, 10, 10) itemSpace:10 lineSpace:10 column:1]; section.scales = @"1:0.5"; section.cellElement = [FMLayoutElement elementWithViewClass:[FMCollectionCustomCell class]]; [section setOtherBlock:^CGFloat(id _Nonnull section, NSInteger item) { switch (item) { case 0: case 3: case 6: case 9: return ([UIScreen mainScreen].bounds.size.width - 30) / 3.0 * 2; break; default: return (([UIScreen mainScreen].bounds.size.width - 30) / 3.0 * 2 - 10) * 0.5; break; } // return 50 + ((item % 2 == 0) ? item * 50 : item * 10); }]; // section.itemDatas = [@[@"1", @"2", @"2", @"3", @"2", @"3", @"2", @"3", @"2", @"3", @"2", @"3"] mutableCopy]; [section setConfigureCellData:^(FMLayoutBaseSection * _Nonnull section, UICollectionViewCell * _Nonnull cell, NSInteger item) { [(FMCollectionCustomCell *)cell label].text = [NSString stringWithFormat:@"%ld", item]; }]; [sections addObject:section]; } { FMLayoutScaleSection *section = [FMLayoutScaleSection sectionWithSectionInset:UIEdgeInsetsMake(10, 10, 10, 10) itemSpace:10 lineSpace:10 column:1]; section.sizeNums = @[@100, @200]; section.cellElement = [FMLayoutElement elementWithViewClass:[FMCollectionCustomCell class]]; // section.cellElement = [FMLayoutElement elementWithViewClass:[LS_HomeActivityCell class]]; // section.autoHeightFixedWidth = YES; [section setOtherBlock:^CGFloat(id _Nonnull section, NSInteger item) { switch (item) { case 0: case 3: case 6: case 9: return ([UIScreen mainScreen].bounds.size.width - 30) / 3.0 * 2; break; default: return (([UIScreen mainScreen].bounds.size.width - 30) / 3.0 * 2 - 10) * 0.5; break; } // return 50 + ((item % 2 == 0) ? item * 50 : item * 10); }]; section.itemDatas = [@[@"1", @"2", @"2", @"3", @"2", @"3", @"2", @"3", @"2", @"3", @"2", @"3"] mutableCopy]; [section setConfigureCellData:^(FMLayoutBaseSection * _Nonnull section, UICollectionViewCell * _Nonnull cell, NSInteger item) { [(FMCollectionCustomCell *)cell label].text = [NSString stringWithFormat:@"%ld", item]; // if (item == 0) { // ((LS_HomeActivityCell *)cell).introLabel.text = @" 一些描述\n爱神的箭埃里克森基多拉\n离开时尽量少肯德基分离式的"; // return; // } // if (item == 1) { // ((LS_HomeActivityCell *)cell).introLabel.text = @" 一些描述\n爱神的箭埃里克森基多拉\n离开时尽量少肯德基分离式的\n爱神的箭埃里克森基多拉\n离开时尽量少肯德基分离式的"; // return; // } // if (item == 2) { // ((LS_HomeActivityCell *)cell).introLabel.text = @" 一些描述"; // return; // } // if (item == 3) { // ((LS_HomeActivityCell *)cell).introLabel.text = @" 一些描述\n爱神的箭埃里克森基多拉\n离开时尽量少\n离开时尽量少肯德基分离式的一些描述\n爱神的箭埃里克森基多拉\n离开时尽量少\n离开时尽量少肯德基分离式的一些描述\n爱神的箭埃里克森基多拉\n离开时尽量少\n离开时尽量少肯德基分离式的一些描述\n爱神的箭埃里克森基多拉\n离开时尽量少\n离开时尽量少肯德基分离式的"; // return; // // } // ((LS_HomeActivityCell *)cell).introLabel.text = @" 一些描述\n爱神的箭埃里克森基多拉\n离开时尽量少"; }]; [sections addObject:section]; } self.collectionView.sections = sections; [self.collectionView reloadData]; } @end ================================================ FILE: Example/FMLayoutKit/FMExcuteTimeTool.h ================================================ // // FMExcuteTimeTool.h // FMCollectionLayout_Example // // Created by 周发明 on 2020/6/6. // Copyright © 2020 周发明. All rights reserved. // #import NS_ASSUME_NONNULL_BEGIN @interface FMExcuteTimeTool : NSObject + (void)excuteTime:(void(^)(void))excute; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FMLayoutKit/FMExcuteTimeTool.m ================================================ // // FMExcuteTimeTool.m // FMCollectionLayout_Example // // Created by 周发明 on 2020/6/6. // Copyright © 2020 周发明. All rights reserved. // #import "FMExcuteTimeTool.h" @implementation FMExcuteTimeTool + (void)excuteTime:(void(^)(void))excute{ CFAbsoluteTime start = CFAbsoluteTimeGetCurrent(); !excute?:excute(); CFAbsoluteTime end = CFAbsoluteTimeGetCurrent() - start; NSLog(@"该block执行耗时 %f ms", end *1000.0); } @end ================================================ FILE: Example/FMLayoutKit/FMFPSLabel.h ================================================ // // FMFPSLabel.h // FMLayoutKit_Example // // Created by 郑桂华 on 2020/7/1. // Copyright © 2020 zhoufaming251@163.com. All rights reserved. // #import NS_ASSUME_NONNULL_BEGIN @interface FMFPSLabel : UILabel @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FMLayoutKit/FMFPSLabel.m ================================================ // // FMFPSLabel.m // FMLayoutKit_Example // // Created by 郑桂华 on 2020/7/1. // Copyright © 2020 zhoufaming251@163.com. All rights reserved. // #import "FMFPSLabel.h" @interface FMFPSLabel () @property(nonatomic, strong)CADisplayLink *link; @property(nonatomic, assign)CFTimeInterval timestamp; @property(nonatomic, assign)NSInteger count; @end @implementation FMFPSLabel - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateLink:)]; [link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; self.link = link; } return self; } - (void)updateLink:(CADisplayLink *)link{ if (self.timestamp == 0) { self.timestamp = link.timestamp; return; } self.count ++; // 两帧间隔时间 NSTimeInterval delta = link.timestamp - self.timestamp; // 过滤刷新次数 if (delta < 1) return; // 计算FPS self.timestamp = link.timestamp; float fps = self.count / delta; self.count = 0; self.text = [NSString stringWithFormat:@"%d FPS", (int)round(fps)]; } @end ================================================ FILE: Example/FMLayoutKit/FMHorizontalLayoutController.h ================================================ // // FMHorizontalLayoutController.h // FMLayoutKit_Example // // Created by 周发明 on 2020/6/15. // Copyright © 2020 zhoufaming251@163.com. All rights reserved. // #import NS_ASSUME_NONNULL_BEGIN @interface FMHorizontalLayoutController : UIViewController @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FMLayoutKit/FMHorizontalLayoutController.m ================================================ // // FMHorizontalLayoutController.m // FMLayoutKit_Example // // Created by 周发明 on 2020/6/15. // Copyright © 2020 zhoufaming251@163.com. All rights reserved. // #import "FMHorizontalLayoutController.h" #import #import #import "LS_HomeActivityCell.h" #import "FMCollectionCustomDecoration.h" #import "FMCollectionCustomCell.h" #import "FMCollectionNavTitleView.h" #import "FMViewController.h" #import "FMFPSLabel.h" @interface FMHorizontalLayoutController () @property(nonatomic, strong)NSMutableArray *shareSections; @property(nonatomic, weak)FMLayoutView *collectionView; @property(nonatomic, strong)NSMutableDictionary *fillSizeData; @end @implementation FMHorizontalLayoutController - (void)viewDidLoad { [super viewDidLoad]; // self.navigationItem.title = @"横向布局"; self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"切换" style:UIBarButtonItemStyleDone target:self action:@selector(changeLayoutDirection)]; self.shareSections = [NSMutableArray array]; self.fillSizeData = [NSMutableDictionary dictionary]; // FMLayoutCloseLog() __weak typeof(self) weakSelf = self; { FMLayoutFixedSection *section = [FMLayoutFixedSection sectionWithSectionInset:UIEdgeInsetsMake(0, 0, 0, 0) itemSpace:10 lineSpace:10 column:2]; section.header = [FMLayoutHeader elementSize:50 viewClass:[FMCollectionCustomDecoration class]]; section.header.type = FMLayoutHeaderTypeSuspensionAlways; section.header.zIndex = FMLayoutZIndexFrontAlways; section.header.isStickTop = YES; // section.header.inset = UIEdgeInsetsMake(0, -15, 0, -15); [section setConfigureHeaderData:^(FMLayoutBaseSection * _Nonnull section, UICollectionReusableView * _Nonnull header) { FMCollectionCustomDecoration *custom = (FMCollectionCustomDecoration *)header; custom.textLabel.text = @"第一个悬浮的顶部视图, 黏在顶部"; }]; section.footer = [FMLayoutFooter elementSize:100 viewClass:[FMCollectionCustomDecoration class]]; // section.footer.inset = UIEdgeInsetsMake(10, 0, 10, 0); section.footer.topMargin = 10; section.background = [FMLayoutBackground bgWithViewClass:[UICollectionReusableView class]]; section.background.inset = UIEdgeInsetsMake(10, 10, 10, 10); [section setConfigureBg:^(FMLayoutBaseSection * _Nonnull section, UICollectionReusableView * _Nonnull bg) { bg.backgroundColor = [UIColor yellowColor]; }]; FMLayoutCrossSection *hSection = [FMLayoutCrossSection sectionAutoWithSection:section]; hSection.autoMaxSize = NO; hSection.size = 300; // [self.shareSections addObject:hSection]; } { FMLayoutFixedSection *section = [FMLayoutFixedSection sectionWithSectionInset:UIEdgeInsetsZero itemSpace:10 lineSpace:10 column:3]; section.header = [FMLayoutHeader elementSize:100 viewClass:[FMCollectionCustomDecoration class]]; section.header.lastMargin = 10; section.header.type = FMLayoutHeaderTypeSuspensionAlways; section.header.zIndex = FMLayoutZIndexFrontAlways; section.header.isStickTop = NO; // section.header.suspensionTopMargin = 50; // section.header.inset = UIEdgeInsetsMake(0, -15, 0, -15); section.footer = [FMLayoutFooter elementSize:50 viewClass:[FMCollectionCustomDecoration class]]; section.footer.topMargin = 10; // section.isHorizontalCanScroll = YES; section.itemSize = CGSizeMake(150, 100); section.itemDatas = [@[@"1", @"2", @"3", @"2", @"3", @"2", @"3", @"2", @"3", @"2", @"3"] mutableCopy]; section.cellElement = [FMLayoutElement elementWithViewClass:[FMCollectionCustomCell class]]; [section setClickCellBlock:^(FMLayoutBaseSection * _Nonnull section, NSInteger item) { FMViewController *vc = [[FMViewController alloc] init]; [weakSelf.navigationController pushViewController:vc animated:YES]; }]; FMLayoutCrossSection *hSection = [FMLayoutCrossSection sectionAutoWithSection:section]; hSection.header = [FMLayoutHeader elementSize:100 viewClass:[FMCollectionCustomDecoration class]]; [hSection setConfigureHeaderData:^(FMLayoutBaseSection * _Nonnull section, UICollectionReusableView * _Nonnull header) { FMCollectionCustomDecoration *custom = (FMCollectionCustomDecoration *)header; custom.textLabel.text = @"FMLayoutFixedSection"; }]; // [self.shareSections addObject:hSection]; } // { FMLayoutLabelSection *section = [FMLayoutLabelSection sectionWithSectionInset:UIEdgeInsetsMake(0, 10, 0, 10) itemSpace:10 lineSpace:10 column:3]; section.header = [FMLayoutHeader elementSize:30 viewClass:[FMCollectionCustomDecoration class]]; section.header.zIndex = FMLayoutZIndexFrontOfItem; section.header.type = FMLayoutHeaderTypeFixed; section.header.lastMargin = 10; // section.isSingleLineCanScroll = YES; section.maxLine = 1; section.cellFixedHeight = 40; [section setWidthBlock:^CGFloat(id _Nonnull section, NSInteger item) { return item * 20 + 100; }]; section.itemDatas = [@[@"1", @"2", @"3", @"1", @"2", @"3", @"1", @"2", @"3", @"1", @"2", @"3", ] mutableCopy]; section.cellElement = [FMLayoutElement elementWithViewClass:[FMCollectionCustomCell class]]; FMLayoutCrossSection *hSection = [FMLayoutCrossSection sectionAutoWithSection:section]; hSection.header = [FMLayoutHeader elementSize:100 viewClass:[FMCollectionCustomDecoration class]]; [hSection setConfigureHeaderData:^(FMLayoutBaseSection * _Nonnull section, UICollectionReusableView * _Nonnull header) { FMCollectionCustomDecoration *custom = (FMCollectionCustomDecoration *)header; custom.textLabel.text = @"FMLayoutLabelSection"; }]; // [self.shareSections addObject:hSection]; // [self.shareSections addObject:section]; } // { // FMLayoutSingleDynamicAddSection *section = [FMLayoutSingleDynamicAddSection sectionWithSectionInset:UIEdgeInsetsMake(0, 0, 0, 0) itemSpace:10 lineSpace:10 column:3]; // // section.header = [FMLayoutHeader elementSize:150 viewClass:[FMCollectionCustomDecoration class]]; // section.header.zIndex = FMLayoutZIndexFrontOfItem; // section.header.type = FMLayoutHeaderTypeFixed; // section.header.lastMargin = 10; // // section.itemDatas = [@[@"1", @"2", @"3", @"1", @"2", @"3", @"1", @"2", @"3", @"1", @"2", @"3", ] mutableCopy]; // section.cellElement = [FMLayoutElement elementWithViewClass:[FMCollectionCustomCell class]]; // section.cellFixedSize = 100; // [section setHeightBlock:^CGFloat(id _Nonnull section, NSInteger item) { // return 100 + (item % 3) * 20; // }]; // [self.shareSections addObject:section]; // self.secondSection = section; // } // { // FMLayoutSingleDynamicAddSection *section = [FMLayoutSingleDynamicAddSection sectionWithSectionInset:UIEdgeInsetsMake(5, 15, 5, 15) itemSpace:10 lineSpace:10 column:2]; // // section.cellFixedSize = 166; // section.autoHeightFixedWidth = YES; // section.itemDatas = [@[@1, @1, @1, @1, @1, @1] mutableCopy]; // section.cellElement = [FMLayoutElement elementWithViewClass:[LS_HomeActivityCell class]]; // __weak typeof(self) weakSelf = self; // [section setConfigureCellData:^(FMLayoutBaseSection * _Nonnull section, UICollectionViewCell * _Nonnull cell, NSInteger item) { // if (item == 0) { // ((LS_HomeActivityCell *)cell).introLabel.text = @" 一些描述\n爱神的箭埃里克森基多拉\n离开时尽量少肯德基分离式的"; // return; // } // if (item == 1) { // ((LS_HomeActivityCell *)cell).introLabel.text = @" 一些描述\n爱神的箭埃里克森基多拉\n离开时尽量少肯德基分离式的\n爱神的箭埃里克森基多拉\n离开时尽量少肯德基分离式的"; // return; // } // if (item == 2) { // ((LS_HomeActivityCell *)cell).introLabel.text = @" 一些描述"; // return; // } // if (item == 3) { // ((LS_HomeActivityCell *)cell).introLabel.text = @" 一些描述\n爱神的箭埃里克森基多拉\n离开时尽量少\n离开时尽量少肯德基分离式的一些描述\n爱神的箭埃里克森基多拉\n离开时尽量少\n离开时尽量少肯德基分离式的一些描述\n爱神的箭埃里克森基多拉\n离开时尽量少\n离开时尽量少肯德基分离式的一些描述\n爱神的箭埃里克森基多拉\n离开时尽量少\n离开时尽量少肯德基分离式的"; // return; // } // ((LS_HomeActivityCell *)cell).introLabel.text = @" 一些描述\n爱神的箭埃里克森基多拉\n离开时尽量少"; // }]; // [self.shareSections addObject:section]; // } { FMLayoutAbsoluteSection *section = [FMLayoutAbsoluteSection sectionWithSectionInset:UIEdgeInsetsMake(0, 0, 0, 0) itemSpace:0 lineSpace:0 column:0]; section.itemDatas = [@[@"1", @"2", @"3"] mutableCopy]; section.cellElement = [FMLayoutElement elementWithViewClass:[FMCollectionCustomCell class]]; [section setFrameBlock:^CGRect(id _Nonnull section, NSInteger item) { switch (item) { case 0: return CGRectMake(0, 0, 100, 100); case 1: return CGRectMake(200, 100, 150, 100); case 2: return CGRectMake(100, 400, 400, 90); default: return CGRectZero; break; } }]; FMLayoutCrossSection *hSection = [FMLayoutCrossSection sectionAutoWithSection:section]; hSection.header = [FMLayoutHeader elementSize:100 viewClass:[FMCollectionCustomDecoration class]]; [hSection setConfigureHeaderData:^(FMLayoutBaseSection * _Nonnull section, UICollectionReusableView * _Nonnull header) { FMCollectionCustomDecoration *custom = (FMCollectionCustomDecoration *)header; custom.textLabel.text = @"FMLayoutAbsoluteSection"; }]; // [self.shareSections addObject:hSection]; // [self.shareSections addObject:section]; } // { // FMLayoutAbsoluteSection *section = [FMLayoutAbsoluteSection sectionWithSectionInset:UIEdgeInsetsMake(0, 0, 0, 0) itemSpace:0 lineSpace:0 column:0]; // // section.itemDatas = [@[@"1", @"2", @"3"] mutableCopy]; // section.cellElements = @[[FMLayoutElement elementWithViewClass:[FMCollectionCustomCell class]]]; // [section setDeqCellReturnReuseId:^NSString * _Nonnull(FMLayoutDynamicSection * _Nonnull section, NSInteger index) { // return [section.cellElements firstObject].reuseIdentifier; // }]; // [section setFrameBlock:^CGRect(id _Nonnull section, NSInteger item) { // switch (item) { // case 0: // return CGRectMake(0, 0, 100, 100); // case 1: // return CGRectMake(200, 100, 150, 100); // case 2: // return CGRectMake(100, 400, 400, 90); // default: // return CGRectZero; // break; // } // }]; // [self.shareSections addObject:section]; // } { FMLayoutFillSection *section = [[FMLayoutFillSection alloc] init]; section.sectionInset = UIEdgeInsetsMake(10, 10, 10, 10); section.lineSpace = 10; section.itemSpace = 10; section.header = [FMLayoutHeader elementSize:50 viewClass:[FMCollectionCustomDecoration class]]; section.header.suspensionTopMargin = 0; // section.header.zIndex = FMLayoutZIndexFrontAlways; // section.header.type = FMLayoutHeaderTypeSuspensionAlways; [section setConfigureHeaderData:^(FMLayoutBaseSection * _Nonnull section, UICollectionReusableView * _Nonnull header) { FMCollectionCustomDecoration *customHeader = (FMCollectionCustomDecoration *)header; customHeader.textLabel.text = @"填充布局,寻找合适的空档,支持多种cell, header样式一直悬停在顶部"; }]; section.cellElement = [FMLayoutElement elementWithViewClass:[FMCollectionCustomCell class]]; section.itemDatas = [@[@"1", @"2", @"3", @"1", @"2", @"3", @"1", @"2", @"3", @"1", @"2", @"3", @"1", @"2", @"3", @"3", @"1", @"2", @"3", @"3", @"1", @"2", @"3",] mutableCopy]; CGFloat leftWith = [UIScreen mainScreen].bounds.size.width - section.sectionInset.left - section.sectionInset.right; CGFloat width1 = leftWith; CGFloat width2 = (leftWith - section.itemSpace) * 0.5; CGFloat width4 = (width2 - section.itemSpace) * 0.5; CGFloat height2width4 = width4 * 2 + section.lineSpace; [section setSizeBlock:^CGSize(id _Nonnull section, NSInteger item) { if (item < 2) { return CGSizeMake(width2, width2); } if (item < 4) { return CGSizeMake(width4, width4); } if (item < 6) { return CGSizeMake(width4, height2width4); } if (item < 7) { return CGSizeMake(width2, width4); } if (item < 8) { return CGSizeMake(width1, width4); } return CGSizeMake(width2, width2); // switch (item) { // case 2: // return CGSizeMake(150, 140); // case 5: // return CGSizeMake((weakSelf.view.frame.size.width-20-150)/2, 70); // case 8: // case 11: // return CGSizeMake(100, 240); // case 10: // return CGSizeMake(weakSelf.view.frame.size.width-20-200, 140); // case 9: // case 12: // return CGSizeMake(weakSelf.view.frame.size.width-20-100, 100); // case 0: // case 1: // case 3: // case 4: // return CGSizeMake((weakSelf.view.frame.size.width-20-150)/4, 70); // default: //// { //// NSValue *value = weakSelf.fillSizeData[@(item)]; //// if (value == nil) { //// value = [NSValue valueWithCGSize:CGSizeMake(FMLayoutRandomValue(100, 300), FMLayoutRandomValue(50, 200))]; //// weakSelf.fillSizeData[@(item)] = value; //// } //// return [value CGSizeValue]; //// } // return CGSizeMake((weakSelf.view.frame.size.width-20-150)/4, 70); // } }]; // [section setConfigureCellLayoutAttributes:^(id _Nonnull section, UICollectionViewLayoutAttributes * _Nonnull attributes, NSInteger item) { // if (item == 10) { // attributes.transform = CGAffineTransformMakeRotation(M_PI_4); // } // }]; [section setConfigureCellData:^(FMLayoutBaseSection * _Nonnull section, UICollectionViewCell * _Nonnull cell, NSInteger item) { FMCollectionCustomCell *customCell = (FMCollectionCustomCell *)cell; customCell.label.text = [NSString stringWithFormat:@"%ld", item]; }]; // FMLayoutCrossSection *hSection = [FMLayoutCrossSection sectionAutoWithSection:section]; // hSection.autoMaxSize = NO; // hSection.height = 500; // hSection.header = [FMLayoutHeader elementSize:100 viewClass:[FMCollectionCustomDecoration class]]; // [hSection setConfigureHeaderData:^(FMLayoutBaseSection * _Nonnull section, UICollectionReusableView * _Nonnull header) { // FMCollectionCustomDecoration *custom = (FMCollectionCustomDecoration *)header; // custom.textLabel.text = @"FMLayoutFillSection"; // }]; // [self.shareSections addObject:hSection]; [self.shareSections addObject:section]; } { FMLayoutCrossSection *sections = [FMLayoutCrossSection sectionWithSectionInset:UIEdgeInsetsMake(10, 10, 10, 10) itemSpace:0 lineSpace:0 column:1]; sections.header = [FMLayoutHeader elementSize:100 viewClass:[FMCollectionCustomDecoration class]]; sections.header.lastMargin = 10; // sections.size = 400; sections.autoMaxSize = YES; { // { // FMLayoutFillSection *section = [[FMLayoutFillSection alloc] init]; // section.itemDatas = [@[@"1", @"2", @"3", @"1", @"2", @"3", @"1", @"2", @"3", @"1", @"2", @"3", @"1", @"2", @"3",] mutableCopy]; // // section.sectionInset = UIEdgeInsetsMake(10, 10, 10, 10); // // section.header = [FMLayoutHeader elementSize:50 viewClass:[FMCollectionCustomDecoration class]]; // section.header.suspensionTopMargin = 0; // section.header.zIndex = FMLayoutZIndexFrontAlways; // section.header.type = FMLayoutHeaderTypeSuspensionAlways; // [section setConfigureHeaderData:^(FMLayoutBaseSection * _Nonnull section, UICollectionReusableView * _Nonnull header) { // FMCollectionCustomDecoration *customHeader = (FMCollectionCustomDecoration *)header; // customHeader.textLabel.text = @"填充布局,寻找合适的空档,支持多种cell, header样式一直悬停在顶部"; // }]; // // section.cellElements = @[[FMLayoutElement elementWithViewClass:[FMCollectionCustomCell class]]]; // [section setDeqCellReturnReuseId:^NSString * _Nonnull(FMLayoutDynamicSection * _Nonnull section, NSInteger index) { // return [section.cellElements firstObject].reuseIdentifier; // }]; // [section setSizeBlock:^CGSize(id _Nonnull section, NSInteger item) { // switch (item) { // case 2: // return CGSizeMake(150, 140.32); // case 5: // return CGSizeMake((weakSelf.view.frame.size.width-20-150)/2, 70.19); // case 8: // case 11: // return CGSizeMake(100, 240); // case 10: // return CGSizeMake(weakSelf.view.frame.size.width-20-200, 140); // case 9: // case 12: // return CGSizeMake(weakSelf.view.frame.size.width-20-100, 100); // case 0: // case 1: // case 3: // case 4: // return CGSizeMake((weakSelf.view.frame.size.width-20-150)/4, 70.13); // default: // return CGSizeMake((weakSelf.view.frame.size.width-20-150)/4, 70.19); // } // }]; // // [section setConfigureCellLayoutAttributes:^(id _Nonnull section, UICollectionViewLayoutAttributes * _Nonnull attributes, NSInteger item) { // // if (item == 10) { // // attributes.transform = CGAffineTransformMakeRotation(M_PI_4); // // } // // }]; // [section setConfigureCellData:^(FMLayoutBaseSection * _Nonnull section, UICollectionViewCell * _Nonnull cell, NSInteger item) { // FMCollectionCustomCell *customCell = (FMCollectionCustomCell *)cell; // customCell.label.text = [NSString stringWithFormat:@"%ld", item]; // }]; // [sections.sections addObject:section]; // } { FMLayoutFixedSection *section = [FMLayoutFixedSection sectionWithSectionInset:UIEdgeInsetsZero itemSpace:10 lineSpace:10 column:3]; section.header = [FMLayoutHeader elementSize:100 viewClass:[FMCollectionCustomDecoration class]]; section.header.lastMargin = 10; section.header.type = FMLayoutHeaderTypeSuspensionBigger; section.header.zIndex = FMLayoutZIndexFrontAlways; section.header.minSize = 50; section.header.maxSize = 200; section.header.isStickTop = YES; // section.header.suspensionTopMargin = 50; // section.header.inset = UIEdgeInsetsMake(0, -15, 0, -15); [section setConfigureHeaderData:^(FMLayoutBaseSection * _Nonnull section, UICollectionReusableView * _Nonnull header) { FMCollectionCustomDecoration *custom = (FMCollectionCustomDecoration *)header; custom.textLabel.text = @"第二个悬浮的顶部视图, 不黏在顶部"; }]; // section.footer = [FMLayoutFooter elementSize:50 viewClass:[FMCollectionCustomDecoration class]]; // section.footer.topMargin = 10; // section.isHorizontalCanScroll = YES; section.itemSize = CGSizeMake(150, 100); section.itemDatas = [@[@"1", @"2", @"3", @"2", @"3", @"2", @"3", @"2", @"3", @"2", @"3", @"2", @"3", @"2", @"3", @"2", @"3", @"2", @"3", @"2", @"3"] mutableCopy]; section.cellElement = [FMLayoutElement elementWithViewClass:[FMCollectionCustomCell class]]; [section setConfigureCellData:^(FMLayoutBaseSection * _Nonnull section, UICollectionViewCell * _Nonnull cell, NSInteger item) { FMCollectionCustomCell *custom = (FMCollectionCustomCell *)cell; custom.label.text = [NSString stringWithFormat:@"%ld", (long)item]; }]; [section setClickCellBlock:^(FMLayoutBaseSection * _Nonnull section, NSInteger item) { }]; // [sections.sections addObject:section]; // [self.shareSections addObject:section]; } // // { // FMLayoutLabelSection *section = [FMLayoutLabelSection sectionWithSectionInset:UIEdgeInsetsMake(0, 10, 0, 10) itemSpace:10 lineSpace:10 column:3]; // // section.header = [FMLayoutHeader elementSize:30 viewClass:[FMCollectionCustomDecoration class]]; // section.header.zIndex = FMLayoutZIndexFrontOfItem; // section.header.type = FMLayoutHeaderTypeFixed; // section.header.lastMargin = 10; // //// section.maxLine = 1; // section.cellFixedHeight = 40; // [section setWidthBlock:^CGFloat(id _Nonnull section, NSInteger item) { // return item * 20 + 100; // }]; // section.itemDatas = [@[@"1", @"2", @"3", @"1", @"2", @"3", @"1", @"2", @"3", @"1", @"2", @"3", ] mutableCopy]; // section.cellElement = [FMLayoutElement elementWithViewClass:[FMCollectionCustomCell class]]; // [sections.sections addObject:section]; // } // { // FMLayoutAbsoluteSection *section = [FMLayoutAbsoluteSection sectionWithSectionInset:UIEdgeInsetsMake(0, 0, 0, 0) itemSpace:0 lineSpace:0 column:0]; // // section.itemDatas = [@[@"1", @"2", @"3"] mutableCopy]; // section.cellElements = @[[FMLayoutElement elementWithViewClass:[FMCollectionCustomCell class]]]; // [section setDeqCellReturnReuseId:^NSString * _Nonnull(FMLayoutDynamicSection * _Nonnull section, NSInteger index) { // return [section.cellElements firstObject].reuseIdentifier; // }]; // [section setFrameBlock:^CGRect(id _Nonnull section, NSInteger item) { // switch (item) { // case 0: // return CGRectMake(0, 0, 100, 100); // case 1: // return CGRectMake(200, 100, 150, 100); // case 2: // return CGRectMake(100, 400, 400, 90); // default: // return CGRectZero; // break; // } // }]; // [sections.sections addObject:section]; // } // { // FMLayoutLabelSection *section = [FMLayoutLabelSection sectionWithSectionInset:UIEdgeInsetsMake(0, 10, 0, 10) itemSpace:10 lineSpace:10 column:3]; // // section.header = [FMLayoutHeader elementSize:30 viewClass:[FMCollectionCustomDecoration class]]; // section.header.zIndex = FMLayoutZIndexFrontOfItem; // section.header.type = FMLayoutHeaderTypeFixed; // section.header.lastMargin = 10; // // // section.isSingleLineCanScroll = YES; // section.maxLine = 1; // section.cellFixedHeight = 40; // [section setWidthBlock:^CGFloat(id _Nonnull section, NSInteger item) { // return item * 20 + 100; // }]; // section.itemDatas = [@[@"1", @"2", @"3", @"1", @"2", @"3", @"1", @"2", @"3", @"1", @"2", @"3", ] mutableCopy]; // section.cellElement = [FMLayoutElement elementWithViewClass:[FMCollectionCustomCell class]]; // [sections.sections addObject:section]; // } } // [self.shareSections addObject:sections]; } FMLayoutView *view = [[FMLayoutView alloc] initHorizontal]; self.automaticallyAdjustsScrollViewInsets = NO; view.delegate = self; // view.alwaysBounceVertical = YES; [view.layout setSections:self.shareSections]; // view.layout.minContentSize = 1000; view.backgroundColor = [UIColor whiteColor]; [self.view addSubview:view]; [view mas_makeConstraints:^(MASConstraintMaker *make) { make.left.right.bottom.mas_equalTo(0); make.top.mas_equalTo(100); }]; self.collectionView = view; } - (void)changeLayoutDirection{ self.collectionView.layout.direction = self.collectionView.layout.direction == FMLayoutDirectionVertical ? FMLayoutDirectionHorizontal : FMLayoutDirectionVertical; [self.collectionView reloadChangedSectionsData]; if (self.collectionView.layout.direction == FMLayoutDirectionVertical) { self.collectionView.alwaysBounceVertical = YES; self.collectionView.alwaysBounceHorizontal = NO; } else { self.collectionView.alwaysBounceVertical = NO; self.collectionView.alwaysBounceHorizontal = YES; } } - (void)scrollViewDidScroll:(UIScrollView *)scrollView{ /* index path: ( {length = 2, path = 0 - 0}); frame = (10 10; 61 70); , index path: ( {length = 2, path = 0 - 1}); frame = (71 10; 61 70); , index path: ( {length = 2, path = 0 - 2}); frame = (132 10; 150 140); , index path: ( {length = 2, path = 0 - 3}); frame = (282 10; 61 70); , index path: ( {length = 2, path = 0 - 4}); frame = (343 10; 61 70); , index path: ( {length = 2, path = 0 - 5}); frame = (10 80; 122 70); , index path: ( {length = 2, path = 0 - 6}); frame = (282 80; 61 70); , index path: ( {length = 2, path = 0 - 7}); frame = (343 80; 61 70); , index path: ( {length = 2, path = 0 - 8}); frame = (10 150; 100 240); , index path: ( {length = 2, path = 0 - 9}); frame = (110 150; 294 100); , index path: ( {length = 2, path = 0 - 10}); frame = (110 250; 194 140); , index path: ( {length = 2, path = 0 - 11}); frame = (304 250; 100 240); , index path: ( {length = 2, path = 0 - 12}); frame = (10 390; 294 100); , index path: ( {length = 2, path = 0 - 13}); frame = (10 490; 61 70); , index path: ( {length = 2, path = 0 - 14}); frame = (71 490; 61 70); , index path: ( {length = 2, path = 0 - 15}); frame = (132 490; 61 70); , index path: ( {length = 2, path = 0 - 16}); frame = (193 490; 61 70); , index path: ( {length = 2, path = 0 - 17}); frame = (254 490; 61 70); , index path: ( {length = 2, path = 0 - 18}); frame = (315 490; 61 70); */ } @end ================================================ FILE: Example/FMLayoutKit/FMLayoutKit-Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleDisplayName $(PRODUCT_NAME) CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1.0 LSRequiresIPhoneOS UILaunchStoryboardName LaunchScreen UIMainStoryboardFile Main UIRequiredDeviceCapabilities armv7 UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight ================================================ FILE: Example/FMLayoutKit/FMLayoutKit-Prefix.pch ================================================ // // Prefix header // // The contents of this file are implicitly included at the beginning of every source file. // #import #ifndef __IPHONE_5_0 #warning "This project uses features only available in iOS SDK 5.0 and later." #endif #ifdef __OBJC__ @import UIKit; @import Foundation; #endif ================================================ FILE: Example/FMLayoutKit/FMLayoutLabel.h ================================================ // // FMLayoutLabel.h // FMCollectionLayout_Example // // Created by 周发明 on 2020/4/23. // Copyright © 2020 周发明. All rights reserved. // #import NS_ASSUME_NONNULL_BEGIN @interface FMLayoutLabel : UILabel @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FMLayoutKit/FMLayoutLabel.m ================================================ // // FMLayoutLabel.m // FMCollectionLayout_Example // // Created by 周发明 on 2020/4/23. // Copyright © 2020 周发明. All rights reserved. // #import "FMLayoutLabel.h" @interface FMLayoutLabel () @property(nonatomic, assign)BOOL isLayoutSubviews; @property(nonatomic, assign)BOOL isAttributeText; @end @implementation FMLayoutLabel - (void)setText:(NSString *)text{ [super setText:text]; self.isAttributeText = NO; if (self.isLayoutSubviews) { [self updateFillSize]; } } - (void)setAttributedText:(NSAttributedString *)attributedText{ [super setAttributedText:attributedText]; self.isAttributeText = YES; if (self.isLayoutSubviews) { [self updateFillSize]; } } - (void)setFont:(UIFont *)font{ [super setFont:font]; if (self.isLayoutSubviews) { [self updateFillSize]; } } - (void)layoutSubviews{ [super layoutSubviews]; self.isLayoutSubviews = YES; [self updateFillSize]; } - (void)updateFillSize{ CGSize size = CGSizeZero; if (self.isAttributeText && self.attributedText != nil) { CGFloat height = [self.attributedText boundingRectWithSize:CGSizeMake(self.bounds.size.width, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading context:nil].size.height; size = [self sizeThatFits:CGSizeMake(self.bounds.size.width, height)]; } if (!self.isAttributeText && self.text != nil) { CGFloat height = [self.text boundingRectWithSize:CGSizeMake(self.bounds.size.width, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:self.font} context:nil].size.height; size = [self sizeThatFits:CGSizeMake(self.bounds.size.width, height)]; } NSLog(@"updateFillSize %@", [NSValue valueWithCGSize:size]); } @end ================================================ FILE: Example/FMLayoutKit/FMViewController.h ================================================ // // FMViewController.h // FMCollectionLayout // // Created by 周发明 on 04/01/2020. // Copyright (c) 2020 周发明. All rights reserved. // @import UIKit; @interface FMViewController : UIViewController @end ================================================ FILE: Example/FMLayoutKit/FMViewController.m ================================================ // // FMViewController.m // FMLayoutKit // // Created by zhoufaming251@163.com on 06/09/2020. // Copyright (c) 2020 zhoufaming251@163.com. All rights reserved. // #import "FMViewController.h" #import #import #import "FMCollectionCustomDecoration.h" #import "FMCollectionCustomCell.h" #import "FMCollectionNavTitleView.h" #import "FMCollViewController.h" #import "LS_HomeActivityCell.h" #import "FMFPSLabel.h" @interface FMViewController () @property(nonatomic, strong)NSMutableArray *shareSections; @property(nonatomic, strong)NSMutableArray *sections; @property(nonatomic, weak)FMTeslaLayoutView *multiScreen; @property(nonatomic, weak)FMCollectionNavTitleView *navTitleView; @property(nonatomic, weak)UILabel *fpsLabel; @property(nonatomic, assign)BOOL hasAdd; @end @implementation FMViewController - (FMTeslaLayoutView *)multiScreen{ if (_multiScreen == nil) { FMTeslaLayoutView *multi = [[FMTeslaLayoutView alloc] init]; multi.selectIndex = 2; multi.delegate = self; multi.dataSource = self; // multi.clipsToBounds = YES; // multi.allShareStickTop = YES; [self.view addSubview:multi]; _multiScreen = multi; } return _multiScreen; } - (void)setNavTitleView:(FMCollectionNavTitleView *)navTitleView{ if (_navTitleView == nil) { [navTitleView selectWithIndex:self.multiScreen.selectIndex]; } _navTitleView = navTitleView; __weak typeof(self) weakSelf = self; [navTitleView setClickBlock:^(NSInteger tag) { [weakSelf.multiScreen scrollToIndex:tag animated:YES]; }]; } - (void)viewDidAppear:(BOOL)animated{ [super viewDidAppear:animated]; if (!self.fpsLabel) { FMFPSLabel *label = [[FMFPSLabel alloc] initWithFrame:CGRectMake(40, 50, 100, 20)]; [self.view.window addSubview:label]; self.fpsLabel = label; } } - (void)add{ self.hasAdd = YES; [self.multiScreen reLoadSubViews]; } - (void)viewDidLoad { [super viewDidLoad]; // self.navigationItem.title = @"特斯拉布局"; self.automaticallyAdjustsScrollViewInsets = NO; UIBarButtonItem *item1 = [[UIBarButtonItem alloc] initWithTitle:@"添加刷新" style:UIBarButtonItemStyleDone target:self action:@selector(add)]; self.navigationItem.rightBarButtonItem = item1; self.shareSections = [NSMutableArray array]; self.sections = [NSMutableArray array]; __weak typeof(self) weakSelf = self; // [FMLayoutDebugLog closeLog]; // FMLayoutOpenLog(); { FMLayoutDynamicSection *section = [FMLayoutDynamicSection sectionWithSectionInset:UIEdgeInsetsMake(5, 15, 5, 15) itemSpace:10 lineSpace:10 column:2]; section.cellFixedSize = 166; section.autoHeightFixedWidth = YES; // section.itemDatas = [@[@1, @1, @1, @1, @1, @1] mutableCopy]; section.cellElement = [FMLayoutElement elementWithViewClass:[LS_HomeActivityCell class]]; [section setConfigureCellData:^(FMLayoutBaseSection * _Nonnull section, UICollectionViewCell * _Nonnull cell, NSInteger item) { if (item == 0) { ((LS_HomeActivityCell *)cell).introLabel.text = @" 一些描述\n爱神的箭埃里克森基多拉\n离开时尽量少肯德基分离式的"; return; } if (item == 1) { ((LS_HomeActivityCell *)cell).introLabel.text = @" 一些描述\n爱神的箭埃里克森基多拉\n离开时尽量少肯德基分离式的\n爱神的箭埃里克森基多拉\n离开时尽量少肯德基分离式的"; return; } if (item == 2) { ((LS_HomeActivityCell *)cell).introLabel.text = @" 一些描述"; return; } if (item == 3) { ((LS_HomeActivityCell *)cell).introLabel.text = @" 一些描述\n爱神的箭埃里克森基多拉\n离开时尽量少\n离开时尽量少肯德基分离式的一些描述\n爱神的箭埃里克森基多拉\n离开时尽量少\n离开时尽量少肯德基分离式的一些描述\n爱神的箭埃里克森基多拉\n离开时尽量少\n离开时尽量少肯德基分离式的一些描述\n爱神的箭埃里克森基多拉\n离开时尽量少\n离开时尽量少肯德基分离式的"; } else { ((LS_HomeActivityCell *)cell).introLabel.text = @"asdjlakjdlaksjdlakjdlask"; } }]; [self.shareSections addObject:section]; } { FMLayoutFixedSection *section = [FMLayoutFixedSection sectionWithSectionInset:UIEdgeInsetsMake(0, 15, 15, 15) itemSpace:10 lineSpace:10 column:2]; section.hidden = YES; section.header = [FMLayoutHeader elementSize:100 viewClass:[FMCollectionCustomDecoration class]]; section.header.lastMargin = 10; // section.header.type = FMSupplementaryTypeSuspensionAlways; // section.header.isStickTop = YES; section.header.inset = UIEdgeInsetsMake(0, -15, 0, -15); // section.footer = [FMSupplementaryFooter elementSize:50 viewClass:[FMCollectionCustomDecoration class]]; // section.footer.topMargin = 10; section.itemSize = CGSizeMake(100, 100); section.itemDatas = [@[@"1", @"2", @"3"] mutableCopy]; section.cellElement = [FMLayoutElement elementWithViewClass:[FMCollectionCustomCell class]]; [section setConfigureCellData:^(FMLayoutBaseSection * _Nonnull section, UICollectionViewCell * _Nonnull cell, NSInteger item) { FMCollectionCustomCell *customCell = (FMCollectionCustomCell *)cell; customCell.contentView.backgroundColor = [UIColor yellowColor]; }]; [section setClickCellBlock:^(FMLayoutBaseSection * _Nonnull section, NSInteger item) { FMCollViewController *vc = [[FMCollViewController alloc] init]; [weakSelf.navigationController pushViewController:vc animated:YES]; }]; [self.shareSections addObject:section]; } // { // FMLayoutFixedSection *section = [FMLayoutFixedSection sectionWithSectionInset:UIEdgeInsetsMake(0, 0, 0, 0) itemSpace:10 lineSpace:10 column:3]; // // section.header = [FMSupplementaryHeader elementSize:150 viewClass:[FMCollectionCustomDecoration class]]; // section.header.zIndex = FMLayoutZIndexFrontOfItem; // section.header.type = FMSupplementaryTypeFixed; // section.header.lastMargin = 10; // // section.isHorizontalCanScroll = YES; // section.itemSize = CGSizeMake(150, 100); // section.itemDatas = [@[@"1", @"2", @"3", @"1", @"2", @"3", @"1", @"2", @"3", @"1", @"2", @"3", ] mutableCopy]; // section.cellElement = [FMCollectionViewElement elementWithViewClass:[FMCollectionCustomCell class]]; // [section setConfigureCellData:^(FMLayoutBaseSection * _Nonnull section, UICollectionViewCell * _Nonnull cell, NSInteger item) { // // }]; // [self.shareSections addObject:section]; // } // { FMLayoutDynamicSection *section = [FMLayoutDynamicSection sectionWithSectionInset:UIEdgeInsetsMake(0, 0, 0, 0) itemSpace:0 lineSpace:10 column:1]; section.header = [FMLayoutHeader elementSize:100 viewClass:[FMCollectionNavTitleView class]]; section.header.type = FMLayoutHeaderTypeSuspensionAlways; section.header.zIndex = FMLayoutZIndexFrontAlways; // section.header.isStickTop = YES; [section setConfigureHeaderData:^(FMLayoutBaseSection * _Nonnull section, UICollectionReusableView * _Nonnull header) { weakSelf.navTitleView = (FMCollectionNavTitleView *)header; }]; [self.shareSections addObject:section]; } // self.multiScreen.shareSections = self.shareSections; { FMLayoutDynamicSection *section = [FMLayoutDynamicSection sectionWithSectionInset:UIEdgeInsetsMake(0, 0, 0, 0) itemSpace:0 lineSpace:10 column:1]; section.header = [FMLayoutHeader elementSize:100 viewClass:[FMCollectionCustomDecoration class]]; section.header.lastMargin = 10; // section.header.suspensionTopHeight = 70; // section.header.type = FMSupplementaryTypeSuspensionAlways; // section.header.zIndex = FMLayoutZIndexFrontAlways; // section.header.isStickTop = YES; section.header.inset = UIEdgeInsetsMake(0, -15, 0, -15); section.footer = [FMLayoutFooter elementSize:50 viewClass:[FMCollectionCustomDecoration class]]; section.footer.topMargin = 10; section.itemDatas = [@[@"1", @"2", @"3"] mutableCopy]; section.cellElement = [FMLayoutElement elementWithViewClass:[FMCollectionCustomCell class]]; section.cellFixedSize = [UIScreen mainScreen].bounds.size.width; [section setOtherBlock:^CGFloat(id _Nonnull section, NSInteger item) { return 100 + item * 100; }]; [self.sections addObject:section]; } { FMLayoutDynamicSection *section = [FMLayoutDynamicSection sectionWithSectionInset:UIEdgeInsetsMake(10, 0, 0, 0) itemSpace:10 lineSpace:10 column:2]; section.header = [FMLayoutHeader elementSize:100 viewClass:[FMCollectionCustomDecoration class]]; section.header.lastMargin = 10; section.footer = [FMLayoutFooter elementSize:50 viewClass:[FMCollectionCustomDecoration class]]; section.footer.topMargin = 10; section.itemDatas = [@[@"1", @"2", @"3", @"2", @"3", @"2", @"3"] mutableCopy]; section.cellElement = [FMLayoutElement elementWithViewClass:[FMCollectionCustomCell class]]; section.cellFixedSize = ([UIScreen mainScreen].bounds.size.width - 10) * 0.5; [section setOtherBlock:^CGFloat(id _Nonnull section, NSInteger item) { return 100 + item * 30; }]; __weak typeof(self) weakSelf = self; [section setClickCellBlock:^(FMLayoutBaseSection * _Nonnull section, NSInteger item) { FMCollViewController *vc = [[FMCollViewController alloc] init]; [weakSelf.navigationController pushViewController:vc animated:YES]; }]; FMLayoutCrossSection *horSection = [FMLayoutCrossSection sectionAutoWithSection:section]; [horSection setConfigureCollectionView:^(UICollectionView * _Nonnull collectionView, FMLayoutCrossSection *inSection) { collectionView.pagingEnabled = YES; }]; [self.sections addObject:horSection]; } { FMLayoutDynamicSection *section = [FMLayoutDynamicSection sectionWithSectionInset:UIEdgeInsetsMake(10, 0, 0, 0) itemSpace:10 lineSpace:10 column:2]; section.header = [FMLayoutHeader elementSize:100 viewClass:[FMCollectionCustomDecoration class]]; section.header.lastMargin = 10; section.footer = [FMLayoutFooter elementSize:50 viewClass:[FMCollectionCustomDecoration class]]; section.footer.topMargin = 10; section.itemDatas = [@[@"1\n1", @"2\n2\n2", @"3", @"2\n2\n2\n2\n2\n2\n2\n2\n2", @"3\n2\n2\n2\n2", @"2\n2\n2\n2\n2\n2\n2\n2\n2\n2\n2\n2\n2\n2\n2\n2\n2\n2\n2\n2\n2\n2\n2", @"3\n2\n2"] mutableCopy]; section.cellElement = [FMLayoutElement elementWithViewClass:[FMCollectionCustomCell class]]; section.cellFixedSize = ([UIScreen mainScreen].bounds.size.width - 10) * 0.5; section.autoHeightFixedWidth = YES; __weak typeof(self) weakSelf = self; [section setConfigurationCell:^(FMLayoutDynamicSection * _Nonnull section, UICollectionViewCell * _Nonnull cell, NSInteger index) { FMCollectionCustomCell *custom = (FMCollectionCustomCell *)cell; custom.label.text = section.itemDatas[index]; // [weakSelf tesla:nil configurationCell:cell indexPath:[NSIndexPath indexPathForItem:index inSection:section.indexPath.section] isShare:NO multiIndex:0 layoutView:nil]; }]; // [self.sections addObject:section]; } // { FMLayoutLabelSection *section = [FMLayoutLabelSection sectionWithSectionInset:UIEdgeInsetsMake(0, 0, 0, 0) itemSpace:10 lineSpace:10 column:3]; section.header = [FMLayoutHeader elementSize:30 viewClass:[FMCollectionCustomDecoration class]]; section.header.zIndex = FMLayoutZIndexFrontOfItem; section.header.type = FMLayoutHeaderTypeFixed; section.header.lastMargin = 10; // section.isSingleLineCanScroll = YES; section.maxLine = 6; section.cellFixedHeight = 40; [section setWidthBlock:^CGFloat(id _Nonnull section, NSInteger item) { return item * 20 + 100; }]; section.itemDatas = [@[@"1", @"2", @"3", @"1", @"2", @"3", @"1", @"2", @"3", @"1", @"2", @"3", ] mutableCopy]; section.cellElement = [FMLayoutElement elementWithViewClass:[FMCollectionCustomCell class]]; [self.sections addObject:section]; } // self.view.backgroundColor = [UIColor cyanColor]; [self.multiScreen reLoadSubViews]; [self.multiScreen reloadData]; } - (void)viewWillLayoutSubviews{ [super viewWillLayoutSubviews]; self.multiScreen.frame = CGRectMake(0, 100, self.view.bounds.size.width, self.view.bounds.size.height - 100); } - (CGFloat)shareSuspensionMinHeightWithTesla:(FMTeslaLayoutView *)tesla{ return 70; } - (void)tesla:(FMTeslaLayoutView *)tesla willCreateScrollViewWithIndex:(NSInteger)index{ NSLog(@"willCreateLayoutViewWithIndex %ld", (long)index); } - (void)tesla:(FMTeslaLayoutView *)tesla didCreatedScrollViewWithIndex:(NSInteger)index scrollView:(UIScrollView *)scrollView{ if ([scrollView isKindOfClass:[FMLayoutView class]]) { ((FMLayoutView *)scrollView).sections = [self.sections mutableCopy]; } NSLog(@"didCreatedLayoutViewWithIndex %ld", (long)index); } - (UIScrollView *)tesla:(FMTeslaLayoutView *)tesla customCreateWithIndex:(NSInteger)index shareHeight:(CGFloat)shareHeight{ if (index == 3) { UITableView *tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain]; UIView *header = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, shareHeight + 100)]; header.backgroundColor = [UIColor purpleColor]; tableView.tableHeaderView = header; UIView *footer = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 1000)]; footer.backgroundColor = [UIColor orangeColor]; tableView.tableFooterView = footer; return tableView; } return nil; } - (void)tesla:(FMTeslaLayoutView *)tesla didScrollEnd:(NSInteger)index currentScrollView:(nonnull FMLayoutView *)layoutView{ [self.navTitleView selectWithIndex:index]; } - (NSInteger)numberOfScreenInTesla:(nonnull FMTeslaLayoutView *)tesla { return self.hasAdd ? 4 : 0; } - (NSArray *)shareSectionsInTesla:(FMTeslaLayoutView *)tesla{ return self.shareSections; } @end ================================================ FILE: Example/FMLayoutKit/Images.xcassets/AppIcon.appiconset/Contents.json ================================================ { "images" : [ { "idiom" : "iphone", "size" : "20x20", "scale" : "2x" }, { "idiom" : "iphone", "size" : "20x20", "scale" : "3x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "2x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "3x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "2x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "3x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "2x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "3x" }, { "idiom" : "ipad", "size" : "20x20", "scale" : "1x" }, { "idiom" : "ipad", "size" : "20x20", "scale" : "2x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "1x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "2x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "1x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "2x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "1x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "2x" }, { "idiom" : "ipad", "size" : "83.5x83.5", "scale" : "2x" }, { "idiom" : "ios-marketing", "size" : "1024x1024", "scale" : "1x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: Example/FMLayoutKit/Images.xcassets/Contents.json ================================================ { "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: Example/FMLayoutKit/Images.xcassets/timg.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "timg.jpeg", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: Example/FMLayoutKit/LS_HomeActivityCell.h ================================================ // // LS_HomeActivityCell.h // LiangShanApp // // Created by 周发明 on 2020/4/9. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import NS_ASSUME_NONNULL_BEGIN @interface LS_HomeActivityCell : UICollectionViewCell @property(nonatomic, weak)UIImageView *leftImageView; @property(nonatomic, weak)UILabel *introLabel; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FMLayoutKit/LS_HomeActivityCell.m ================================================ // // LS_HomeActivityCell.m // LiangShanApp // // Created by 周发明 on 2020/4/9. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import "LS_HomeActivityCell.h" #import #import "FMLayoutLabel.h" @implementation LS_HomeActivityCell - (void)dealloc{ } - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.contentView.backgroundColor = [UIColor cyanColor]; UILabel *title = [[UILabel alloc] init]; title.text = @"大标题"; title.font = [UIFont systemFontOfSize:18]; [self.contentView addSubview:title]; [title mas_makeConstraints:^(MASConstraintMaker *make) { make.left.right.mas_equalTo(0); make.top.mas_equalTo(15); }]; UILabel *detail = [[UILabel alloc] init]; detail.text = @"小标题"; detail.font = [UIFont systemFontOfSize:14]; [self.contentView addSubview:detail]; [detail mas_makeConstraints:^(MASConstraintMaker *make) { make.left.right.mas_equalTo(0); make.top.mas_equalTo(title.mas_bottom).offset(5); }]; UIImageView *left = [[UIImageView alloc] init]; left.backgroundColor = [UIColor redColor]; [self.contentView addSubview:left]; [left mas_makeConstraints:^(MASConstraintMaker *make) { make.left.mas_equalTo(0); make.top.mas_equalTo(detail.mas_bottom).offset(9); make.width.height.mas_equalTo(81); }]; self.leftImageView = left; UIImageView *right = [[UIImageView alloc] init]; right.backgroundColor = [UIColor blueColor]; [self.contentView addSubview:right]; [right mas_makeConstraints:^(MASConstraintMaker *make) { make.left.mas_equalTo(left.mas_right).offset(5); make.top.mas_equalTo(left); make.width.height.mas_equalTo(81); }]; UILabel *intro = [[UILabel alloc] init]; intro.preferredMaxLayoutWidth = 166; intro.numberOfLines = 0; // intro.text = @"一些描述\n爱神的箭埃里克森基多拉\n离开时尽量少肯德基分离式的\n"; intro.text = @"一些描述"; [self.contentView addSubview:intro]; [intro mas_makeConstraints:^(MASConstraintMaker *make) { make.left.mas_equalTo(0); make.right.mas_equalTo(0); make.top.mas_equalTo(left.mas_bottom); make.bottom.mas_equalTo(-10); }]; self.introLabel = intro; } return self; } @end ================================================ FILE: Example/FMLayoutKit/en.lproj/InfoPlist.strings ================================================ /* Localized versions of Info.plist keys */ ================================================ FILE: Example/FMLayoutKit/main.m ================================================ // // main.m // FMLayoutKit // // Created by zhoufaming251@163.com on 06/09/2020. // Copyright (c) 2020 zhoufaming251@163.com. All rights reserved. // @import UIKit; #import "FMAppDelegate.h" int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([FMAppDelegate class])); } } ================================================ FILE: Example/FMLayoutKit.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 3BFF6A316B994187A788CFD9 /* Pods_FMLayoutKit_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05923D8C8C630E1B426CA144 /* Pods_FMLayoutKit_Tests.framework */; }; 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; }; 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58F195388D20070C39A /* CoreGraphics.framework */; }; 6003F592195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; }; 6003F598195388D20070C39A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6003F596195388D20070C39A /* InfoPlist.strings */; }; 6003F59A195388D20070C39A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F599195388D20070C39A /* main.m */; }; 6003F59E195388D20070C39A /* FMAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F59D195388D20070C39A /* FMAppDelegate.m */; }; 6003F5A7195388D20070C39A /* FMViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F5A6195388D20070C39A /* FMViewController.m */; }; 6003F5A9195388D20070C39A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6003F5A8195388D20070C39A /* Images.xcassets */; }; 6003F5B0195388D20070C39A /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F5AF195388D20070C39A /* XCTest.framework */; }; 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; }; 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; }; 6003F5BA195388D20070C39A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6003F5B8195388D20070C39A /* InfoPlist.strings */; }; 6003F5BC195388D20070C39A /* Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F5BB195388D20070C39A /* Tests.m */; }; 71719F9F1E33DC2100824A3D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 71719F9D1E33DC2100824A3D /* LaunchScreen.storyboard */; }; 873B8AEB1B1F5CCA007FD442 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 873B8AEA1B1F5CCA007FD442 /* Main.storyboard */; }; ADA669444312E818D0F6D99C /* Pods_FMLayoutKit_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3E1FF4A9BE374E5DE19B3342 /* Pods_FMLayoutKit_Example.framework */; }; C34E984F2497A9ED00E8EC44 /* FMCollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = C34E984D2497A9ED00E8EC44 /* FMCollectionViewCell.m */; }; C34E98502497A9ED00E8EC44 /* FMCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = C34E984E2497A9ED00E8EC44 /* FMCollectionViewCell.xib */; }; C34E98532497ABE600E8EC44 /* FMHorizontalLayoutController.m in Sources */ = {isa = PBXBuildFile; fileRef = C34E98522497ABE600E8EC44 /* FMHorizontalLayoutController.m */; }; C385261024AC6AAE00386DBB /* FMFPSLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = C385260F24AC6AAE00386DBB /* FMFPSLabel.m */; }; C3973877248F705000A7A2C2 /* FMCollectionCustomDecoration.m in Sources */ = {isa = PBXBuildFile; fileRef = C3973867248F704E00A7A2C2 /* FMCollectionCustomDecoration.m */; }; C3973878248F705000A7A2C2 /* FMCollViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C397386F248F704F00A7A2C2 /* FMCollViewController.m */; }; C3973879248F705000A7A2C2 /* FMAddViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C3973870248F704F00A7A2C2 /* FMAddViewController.m */; }; C397387A248F705000A7A2C2 /* FMCollectionNavTitleView.m in Sources */ = {isa = PBXBuildFile; fileRef = C3973871248F704F00A7A2C2 /* FMCollectionNavTitleView.m */; }; C397387B248F705000A7A2C2 /* FMExcuteTimeTool.m in Sources */ = {isa = PBXBuildFile; fileRef = C3973872248F704F00A7A2C2 /* FMExcuteTimeTool.m */; }; C397387C248F705000A7A2C2 /* FMCollectionCustomCell.m in Sources */ = {isa = PBXBuildFile; fileRef = C3973873248F704F00A7A2C2 /* FMCollectionCustomCell.m */; }; C397387D248F705000A7A2C2 /* FMLayoutLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = C3973874248F705000A7A2C2 /* FMLayoutLabel.m */; }; C397387E248F705000A7A2C2 /* LS_HomeActivityCell.m in Sources */ = {isa = PBXBuildFile; fileRef = C3973875248F705000A7A2C2 /* LS_HomeActivityCell.m */; }; C399E9A324AEC11D00353B76 /* FMAotuSizeReusableView.m in Sources */ = {isa = PBXBuildFile; fileRef = C399E9A224AEC11D00353B76 /* FMAotuSizeReusableView.m */; }; C3C47B9F24BAC2810020C071 /* FMCombineViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C3C47B9E24BAC2810020C071 /* FMCombineViewController.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ 6003F5B3195388D20070C39A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 6003F582195388D10070C39A /* Project object */; proxyType = 1; remoteGlobalIDString = 6003F589195388D20070C39A; remoteInfo = FMLayoutKit; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ 04E8703A16484F3E1A933C88 /* FMLayoutKit.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = FMLayoutKit.podspec; path = ../FMLayoutKit.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 05923D8C8C630E1B426CA144 /* Pods_FMLayoutKit_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_FMLayoutKit_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 0C1C4C8575B73D703C9D0B5D /* Pods-FMLayoutKit_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FMLayoutKit_Example.debug.xcconfig"; path = "Target Support Files/Pods-FMLayoutKit_Example/Pods-FMLayoutKit_Example.debug.xcconfig"; sourceTree = ""; }; 17F812EE8B554502C8DA01FA /* Pods-FMLayoutKit_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FMLayoutKit_Example.release.xcconfig"; path = "Target Support Files/Pods-FMLayoutKit_Example/Pods-FMLayoutKit_Example.release.xcconfig"; sourceTree = ""; }; 26DEFFE1DA7457947895DDDC /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; 2A07CACD9869F5819B6A0803 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; 3E1FF4A9BE374E5DE19B3342 /* Pods_FMLayoutKit_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_FMLayoutKit_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 4ECA8A4093CF864F4FA6C5CA /* Pods-FMLayoutKit_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FMLayoutKit_Tests.debug.xcconfig"; path = "Target Support Files/Pods-FMLayoutKit_Tests/Pods-FMLayoutKit_Tests.debug.xcconfig"; sourceTree = ""; }; 6003F58A195388D20070C39A /* FMLayoutKit.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FMLayoutKit.app; sourceTree = BUILT_PRODUCTS_DIR; }; 6003F58D195388D20070C39A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 6003F58F195388D20070C39A /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 6003F591195388D20070C39A /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 6003F595195388D20070C39A /* FMLayoutKit-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "FMLayoutKit-Info.plist"; sourceTree = ""; }; 6003F597195388D20070C39A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 6003F599195388D20070C39A /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 6003F59B195388D20070C39A /* FMLayoutKit-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "FMLayoutKit-Prefix.pch"; sourceTree = ""; }; 6003F59C195388D20070C39A /* FMAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FMAppDelegate.h; sourceTree = ""; }; 6003F59D195388D20070C39A /* FMAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FMAppDelegate.m; sourceTree = ""; }; 6003F5A5195388D20070C39A /* FMViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FMViewController.h; sourceTree = ""; }; 6003F5A6195388D20070C39A /* FMViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FMViewController.m; sourceTree = ""; }; 6003F5A8195388D20070C39A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 6003F5AE195388D20070C39A /* FMLayoutKit_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FMLayoutKit_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 6003F5AF195388D20070C39A /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 6003F5B7195388D20070C39A /* Tests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Tests-Info.plist"; sourceTree = ""; }; 6003F5B9195388D20070C39A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 6003F5BB195388D20070C39A /* Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Tests.m; sourceTree = ""; }; 606FC2411953D9B200FFA9A0 /* Tests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Tests-Prefix.pch"; sourceTree = ""; }; 71719F9E1E33DC2100824A3D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 873B8AEA1B1F5CCA007FD442 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = Main.storyboard; path = Base.lproj/Main.storyboard; sourceTree = ""; }; A8EFB03ECBAF6C997935840C /* Pods-FMLayoutKit_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FMLayoutKit_Tests.release.xcconfig"; path = "Target Support Files/Pods-FMLayoutKit_Tests/Pods-FMLayoutKit_Tests.release.xcconfig"; sourceTree = ""; }; C34E984C2497A9ED00E8EC44 /* FMCollectionViewCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FMCollectionViewCell.h; sourceTree = ""; }; C34E984D2497A9ED00E8EC44 /* FMCollectionViewCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FMCollectionViewCell.m; sourceTree = ""; }; C34E984E2497A9ED00E8EC44 /* FMCollectionViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FMCollectionViewCell.xib; sourceTree = ""; }; C34E98512497ABE600E8EC44 /* FMHorizontalLayoutController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FMHorizontalLayoutController.h; sourceTree = ""; }; C34E98522497ABE600E8EC44 /* FMHorizontalLayoutController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FMHorizontalLayoutController.m; sourceTree = ""; }; C385260E24AC6AAE00386DBB /* FMFPSLabel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FMFPSLabel.h; sourceTree = ""; }; C385260F24AC6AAE00386DBB /* FMFPSLabel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FMFPSLabel.m; sourceTree = ""; }; C3973867248F704E00A7A2C2 /* FMCollectionCustomDecoration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FMCollectionCustomDecoration.m; sourceTree = ""; }; C3973868248F704F00A7A2C2 /* FMCollectionNavTitleView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FMCollectionNavTitleView.h; sourceTree = ""; }; C3973869248F704F00A7A2C2 /* FMCollectionCustomCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FMCollectionCustomCell.h; sourceTree = ""; }; C397386A248F704F00A7A2C2 /* FMAddViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FMAddViewController.h; sourceTree = ""; }; C397386B248F704F00A7A2C2 /* FMExcuteTimeTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FMExcuteTimeTool.h; sourceTree = ""; }; C397386C248F704F00A7A2C2 /* FMLayoutLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FMLayoutLabel.h; sourceTree = ""; }; C397386D248F704F00A7A2C2 /* LS_HomeActivityCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LS_HomeActivityCell.h; sourceTree = ""; }; C397386E248F704F00A7A2C2 /* FMCollViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FMCollViewController.h; sourceTree = ""; }; C397386F248F704F00A7A2C2 /* FMCollViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FMCollViewController.m; sourceTree = ""; }; C3973870248F704F00A7A2C2 /* FMAddViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FMAddViewController.m; sourceTree = ""; }; C3973871248F704F00A7A2C2 /* FMCollectionNavTitleView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FMCollectionNavTitleView.m; sourceTree = ""; }; C3973872248F704F00A7A2C2 /* FMExcuteTimeTool.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FMExcuteTimeTool.m; sourceTree = ""; }; C3973873248F704F00A7A2C2 /* FMCollectionCustomCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FMCollectionCustomCell.m; sourceTree = ""; }; C3973874248F705000A7A2C2 /* FMLayoutLabel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FMLayoutLabel.m; sourceTree = ""; }; C3973875248F705000A7A2C2 /* LS_HomeActivityCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LS_HomeActivityCell.m; sourceTree = ""; }; C3973876248F705000A7A2C2 /* FMCollectionCustomDecoration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FMCollectionCustomDecoration.h; sourceTree = ""; }; C399E9A124AEC11D00353B76 /* FMAotuSizeReusableView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FMAotuSizeReusableView.h; sourceTree = ""; }; C399E9A224AEC11D00353B76 /* FMAotuSizeReusableView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FMAotuSizeReusableView.m; sourceTree = ""; }; C3C47B9D24BAC2810020C071 /* FMCombineViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FMCombineViewController.h; sourceTree = ""; }; C3C47B9E24BAC2810020C071 /* FMCombineViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FMCombineViewController.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 6003F587195388D20070C39A /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */, 6003F592195388D20070C39A /* UIKit.framework in Frameworks */, 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */, ADA669444312E818D0F6D99C /* Pods_FMLayoutKit_Example.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 6003F5AB195388D20070C39A /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 6003F5B0195388D20070C39A /* XCTest.framework in Frameworks */, 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */, 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */, 3BFF6A316B994187A788CFD9 /* Pods_FMLayoutKit_Tests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 6003F581195388D10070C39A = { isa = PBXGroup; children = ( 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */, 6003F593195388D20070C39A /* Example for FMLayoutKit */, 6003F5B5195388D20070C39A /* Tests */, 6003F58C195388D20070C39A /* Frameworks */, 6003F58B195388D20070C39A /* Products */, 700796DF9A3CFC35B3E6E2B9 /* Pods */, ); sourceTree = ""; }; 6003F58B195388D20070C39A /* Products */ = { isa = PBXGroup; children = ( 6003F58A195388D20070C39A /* FMLayoutKit.app */, 6003F5AE195388D20070C39A /* FMLayoutKit_Tests.xctest */, ); name = Products; sourceTree = ""; }; 6003F58C195388D20070C39A /* Frameworks */ = { isa = PBXGroup; children = ( 6003F58D195388D20070C39A /* Foundation.framework */, 6003F58F195388D20070C39A /* CoreGraphics.framework */, 6003F591195388D20070C39A /* UIKit.framework */, 6003F5AF195388D20070C39A /* XCTest.framework */, 3E1FF4A9BE374E5DE19B3342 /* Pods_FMLayoutKit_Example.framework */, 05923D8C8C630E1B426CA144 /* Pods_FMLayoutKit_Tests.framework */, ); name = Frameworks; sourceTree = ""; }; 6003F593195388D20070C39A /* Example for FMLayoutKit */ = { isa = PBXGroup; children = ( 6003F59C195388D20070C39A /* FMAppDelegate.h */, 6003F59D195388D20070C39A /* FMAppDelegate.m */, 873B8AEA1B1F5CCA007FD442 /* Main.storyboard */, 6003F5A5195388D20070C39A /* FMViewController.h */, 6003F5A6195388D20070C39A /* FMViewController.m */, C397386A248F704F00A7A2C2 /* FMAddViewController.h */, C3973870248F704F00A7A2C2 /* FMAddViewController.m */, C34E98512497ABE600E8EC44 /* FMHorizontalLayoutController.h */, C34E98522497ABE600E8EC44 /* FMHorizontalLayoutController.m */, C3C47B9D24BAC2810020C071 /* FMCombineViewController.h */, C3C47B9E24BAC2810020C071 /* FMCombineViewController.m */, C3973869248F704F00A7A2C2 /* FMCollectionCustomCell.h */, C3973873248F704F00A7A2C2 /* FMCollectionCustomCell.m */, C3973876248F705000A7A2C2 /* FMCollectionCustomDecoration.h */, C3973867248F704E00A7A2C2 /* FMCollectionCustomDecoration.m */, C3973868248F704F00A7A2C2 /* FMCollectionNavTitleView.h */, C3973871248F704F00A7A2C2 /* FMCollectionNavTitleView.m */, C397386E248F704F00A7A2C2 /* FMCollViewController.h */, C397386F248F704F00A7A2C2 /* FMCollViewController.m */, C397386B248F704F00A7A2C2 /* FMExcuteTimeTool.h */, C3973872248F704F00A7A2C2 /* FMExcuteTimeTool.m */, C397386C248F704F00A7A2C2 /* FMLayoutLabel.h */, C3973874248F705000A7A2C2 /* FMLayoutLabel.m */, C385260E24AC6AAE00386DBB /* FMFPSLabel.h */, C385260F24AC6AAE00386DBB /* FMFPSLabel.m */, C397386D248F704F00A7A2C2 /* LS_HomeActivityCell.h */, C3973875248F705000A7A2C2 /* LS_HomeActivityCell.m */, C399E9A124AEC11D00353B76 /* FMAotuSizeReusableView.h */, C399E9A224AEC11D00353B76 /* FMAotuSizeReusableView.m */, C34E984C2497A9ED00E8EC44 /* FMCollectionViewCell.h */, C34E984D2497A9ED00E8EC44 /* FMCollectionViewCell.m */, C34E984E2497A9ED00E8EC44 /* FMCollectionViewCell.xib */, 71719F9D1E33DC2100824A3D /* LaunchScreen.storyboard */, 6003F5A8195388D20070C39A /* Images.xcassets */, 6003F594195388D20070C39A /* Supporting Files */, ); name = "Example for FMLayoutKit"; path = FMLayoutKit; sourceTree = ""; }; 6003F594195388D20070C39A /* Supporting Files */ = { isa = PBXGroup; children = ( 6003F595195388D20070C39A /* FMLayoutKit-Info.plist */, 6003F596195388D20070C39A /* InfoPlist.strings */, 6003F599195388D20070C39A /* main.m */, 6003F59B195388D20070C39A /* FMLayoutKit-Prefix.pch */, ); name = "Supporting Files"; sourceTree = ""; }; 6003F5B5195388D20070C39A /* Tests */ = { isa = PBXGroup; children = ( 6003F5BB195388D20070C39A /* Tests.m */, 6003F5B6195388D20070C39A /* Supporting Files */, ); path = Tests; sourceTree = ""; }; 6003F5B6195388D20070C39A /* Supporting Files */ = { isa = PBXGroup; children = ( 6003F5B7195388D20070C39A /* Tests-Info.plist */, 6003F5B8195388D20070C39A /* InfoPlist.strings */, 606FC2411953D9B200FFA9A0 /* Tests-Prefix.pch */, ); name = "Supporting Files"; sourceTree = ""; }; 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */ = { isa = PBXGroup; children = ( 04E8703A16484F3E1A933C88 /* FMLayoutKit.podspec */, 26DEFFE1DA7457947895DDDC /* README.md */, 2A07CACD9869F5819B6A0803 /* LICENSE */, ); name = "Podspec Metadata"; sourceTree = ""; }; 700796DF9A3CFC35B3E6E2B9 /* Pods */ = { isa = PBXGroup; children = ( 0C1C4C8575B73D703C9D0B5D /* Pods-FMLayoutKit_Example.debug.xcconfig */, 17F812EE8B554502C8DA01FA /* Pods-FMLayoutKit_Example.release.xcconfig */, 4ECA8A4093CF864F4FA6C5CA /* Pods-FMLayoutKit_Tests.debug.xcconfig */, A8EFB03ECBAF6C997935840C /* Pods-FMLayoutKit_Tests.release.xcconfig */, ); path = Pods; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 6003F589195388D20070C39A /* FMLayoutKit_Example */ = { isa = PBXNativeTarget; buildConfigurationList = 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "FMLayoutKit_Example" */; buildPhases = ( F6034618A8944DCB8BA13160 /* [CP] Check Pods Manifest.lock */, 6003F586195388D20070C39A /* Sources */, 6003F587195388D20070C39A /* Frameworks */, 6003F588195388D20070C39A /* Resources */, 873C41F871FCACDC54DB3051 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); dependencies = ( ); name = FMLayoutKit_Example; productName = FMLayoutKit; productReference = 6003F58A195388D20070C39A /* FMLayoutKit.app */; productType = "com.apple.product-type.application"; }; 6003F5AD195388D20070C39A /* FMLayoutKit_Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "FMLayoutKit_Tests" */; buildPhases = ( 70D615FDCB17048872CB0778 /* [CP] Check Pods Manifest.lock */, 6003F5AA195388D20070C39A /* Sources */, 6003F5AB195388D20070C39A /* Frameworks */, 6003F5AC195388D20070C39A /* Resources */, ); buildRules = ( ); dependencies = ( 6003F5B4195388D20070C39A /* PBXTargetDependency */, ); name = FMLayoutKit_Tests; productName = FMLayoutKitTests; productReference = 6003F5AE195388D20070C39A /* FMLayoutKit_Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 6003F582195388D10070C39A /* Project object */ = { isa = PBXProject; attributes = { CLASSPREFIX = FM; LastUpgradeCheck = 0720; ORGANIZATIONNAME = "zhoufaming251@163.com"; TargetAttributes = { 6003F589195388D20070C39A = { DevelopmentTeam = T82JQ7P486; }; 6003F5AD195388D20070C39A = { TestTargetID = 6003F589195388D20070C39A; }; }; }; buildConfigurationList = 6003F585195388D10070C39A /* Build configuration list for PBXProject "FMLayoutKit" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( English, en, Base, ); mainGroup = 6003F581195388D10070C39A; productRefGroup = 6003F58B195388D20070C39A /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 6003F589195388D20070C39A /* FMLayoutKit_Example */, 6003F5AD195388D20070C39A /* FMLayoutKit_Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 6003F588195388D20070C39A /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 873B8AEB1B1F5CCA007FD442 /* Main.storyboard in Resources */, 71719F9F1E33DC2100824A3D /* LaunchScreen.storyboard in Resources */, 6003F5A9195388D20070C39A /* Images.xcassets in Resources */, C34E98502497A9ED00E8EC44 /* FMCollectionViewCell.xib in Resources */, 6003F598195388D20070C39A /* InfoPlist.strings in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; 6003F5AC195388D20070C39A /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 6003F5BA195388D20070C39A /* InfoPlist.strings in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ 70D615FDCB17048872CB0778 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( ); inputPaths = ( "${PODS_PODFILE_DIR_PATH}/Podfile.lock", "${PODS_ROOT}/Manifest.lock", ); name = "[CP] Check Pods Manifest.lock"; outputFileListPaths = ( ); outputPaths = ( "$(DERIVED_FILE_DIR)/Pods-FMLayoutKit_Tests-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; 873C41F871FCACDC54DB3051 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-FMLayoutKit_Example/Pods-FMLayoutKit_Example-frameworks.sh", "${BUILT_PRODUCTS_DIR}/FMLayoutKit/FMLayoutKit.framework", "${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FMLayoutKit.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Masonry.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-FMLayoutKit_Example/Pods-FMLayoutKit_Example-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; F6034618A8944DCB8BA13160 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( ); inputPaths = ( "${PODS_PODFILE_DIR_PATH}/Podfile.lock", "${PODS_ROOT}/Manifest.lock", ); name = "[CP] Check Pods Manifest.lock"; outputFileListPaths = ( ); outputPaths = ( "$(DERIVED_FILE_DIR)/Pods-FMLayoutKit_Example-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 6003F586195388D20070C39A /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 6003F59E195388D20070C39A /* FMAppDelegate.m in Sources */, C3973878248F705000A7A2C2 /* FMCollViewController.m in Sources */, 6003F5A7195388D20070C39A /* FMViewController.m in Sources */, C3C47B9F24BAC2810020C071 /* FMCombineViewController.m in Sources */, C385261024AC6AAE00386DBB /* FMFPSLabel.m in Sources */, C397387D248F705000A7A2C2 /* FMLayoutLabel.m in Sources */, C34E98532497ABE600E8EC44 /* FMHorizontalLayoutController.m in Sources */, C397387B248F705000A7A2C2 /* FMExcuteTimeTool.m in Sources */, C397387A248F705000A7A2C2 /* FMCollectionNavTitleView.m in Sources */, C399E9A324AEC11D00353B76 /* FMAotuSizeReusableView.m in Sources */, C397387E248F705000A7A2C2 /* LS_HomeActivityCell.m in Sources */, C34E984F2497A9ED00E8EC44 /* FMCollectionViewCell.m in Sources */, 6003F59A195388D20070C39A /* main.m in Sources */, C397387C248F705000A7A2C2 /* FMCollectionCustomCell.m in Sources */, C3973877248F705000A7A2C2 /* FMCollectionCustomDecoration.m in Sources */, C3973879248F705000A7A2C2 /* FMAddViewController.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 6003F5AA195388D20070C39A /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 6003F5BC195388D20070C39A /* Tests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ 6003F5B4195388D20070C39A /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 6003F589195388D20070C39A /* FMLayoutKit_Example */; targetProxy = 6003F5B3195388D20070C39A /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ 6003F596195388D20070C39A /* InfoPlist.strings */ = { isa = PBXVariantGroup; children = ( 6003F597195388D20070C39A /* en */, ); name = InfoPlist.strings; sourceTree = ""; }; 6003F5B8195388D20070C39A /* InfoPlist.strings */ = { isa = PBXVariantGroup; children = ( 6003F5B9195388D20070C39A /* en */, ); name = InfoPlist.strings; sourceTree = ""; }; 71719F9D1E33DC2100824A3D /* LaunchScreen.storyboard */ = { isa = PBXVariantGroup; children = ( 71719F9E1E33DC2100824A3D /* Base */, ); name = LaunchScreen.storyboard; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 6003F5BD195388D20070C39A /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 9.3; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; 6003F5BE195388D20070C39A /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = YES; ENABLE_NS_ASSERTIONS = NO; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 9.3; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; name = Release; }; 6003F5C0195388D20070C39A /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 0C1C4C8575B73D703C9D0B5D /* Pods-FMLayoutKit_Example.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; DEVELOPMENT_TEAM = T82JQ7P486; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "FMLayoutKit/FMLayoutKit-Prefix.pch"; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", "COCOAPODS=1", ); INFOPLIST_FILE = "FMLayoutKit/FMLayoutKit-Info.plist"; MODULE_NAME = ExampleApp; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = FMLayoutKit; SWIFT_VERSION = 4.0; WRAPPER_EXTENSION = app; }; name = Debug; }; 6003F5C1195388D20070C39A /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 17F812EE8B554502C8DA01FA /* Pods-FMLayoutKit_Example.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; DEVELOPMENT_TEAM = T82JQ7P486; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "FMLayoutKit/FMLayoutKit-Prefix.pch"; INFOPLIST_FILE = "FMLayoutKit/FMLayoutKit-Info.plist"; MODULE_NAME = ExampleApp; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = FMLayoutKit; SWIFT_VERSION = 4.0; WRAPPER_EXTENSION = app; }; name = Release; }; 6003F5C3195388D20070C39A /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 4ECA8A4093CF864F4FA6C5CA /* Pods-FMLayoutKit_Tests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; FRAMEWORK_SEARCH_PATHS = ( "$(PLATFORM_DIR)/Developer/Library/Frameworks", "$(inherited)", "$(DEVELOPER_FRAMEWORKS_DIR)", ); GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "Tests/Tests-Prefix.pch"; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); INFOPLIST_FILE = "Tests/Tests-Info.plist"; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/FMLayoutKit_Example.app/FMLayoutKit_Example"; WRAPPER_EXTENSION = xctest; }; name = Debug; }; 6003F5C4195388D20070C39A /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = A8EFB03ECBAF6C997935840C /* Pods-FMLayoutKit_Tests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; FRAMEWORK_SEARCH_PATHS = ( "$(PLATFORM_DIR)/Developer/Library/Frameworks", "$(inherited)", "$(DEVELOPER_FRAMEWORKS_DIR)", ); GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "Tests/Tests-Prefix.pch"; INFOPLIST_FILE = "Tests/Tests-Info.plist"; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/FMLayoutKit_Example.app/FMLayoutKit_Example"; WRAPPER_EXTENSION = xctest; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 6003F585195388D10070C39A /* Build configuration list for PBXProject "FMLayoutKit" */ = { isa = XCConfigurationList; buildConfigurations = ( 6003F5BD195388D20070C39A /* Debug */, 6003F5BE195388D20070C39A /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "FMLayoutKit_Example" */ = { isa = XCConfigurationList; buildConfigurations = ( 6003F5C0195388D20070C39A /* Debug */, 6003F5C1195388D20070C39A /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "FMLayoutKit_Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 6003F5C3195388D20070C39A /* Debug */, 6003F5C4195388D20070C39A /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 6003F582195388D10070C39A /* Project object */; } ================================================ FILE: Example/FMLayoutKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Example/FMLayoutKit.xcodeproj/xcshareddata/xcschemes/FMLayoutKit-Example.xcscheme ================================================ ================================================ FILE: Example/FMLayoutKit.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Example/FMLayoutKit.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Example/FMLayoutKitFramework/FMLayoutKit.framework/Headers/FMCollectionLayoutAttributes.h ================================================ // // FMCollectionLayoutAttributes.h // FMLayoutKit // // Created by 周发明 on 2020/3/25. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import #import "FMLayoutBaseSection.h" NS_ASSUME_NONNULL_BEGIN @interface FMCollectionLayoutAttributes : UICollectionViewLayoutAttributes @property(nonatomic, assign)FMLayoutDirection direction; + (instancetype)headerAttributesWithSection:(FMLayoutBaseSection *)section; - (instancetype)updateHeaderAttributesWithSection:(FMLayoutBaseSection *)section; + (instancetype)suspensionShowHeaderAttributes:(FMLayoutBaseSection *)section; + (instancetype)footerAttributesWithSection:(FMLayoutBaseSection *)section; - (instancetype)updateFooterAttributesWithSection:(FMLayoutBaseSection *)section; + (instancetype)bgAttributesWithSection:(FMLayoutBaseSection *)section; - (instancetype)updateBgAttributesWithSection:(FMLayoutBaseSection *)section; - (void)_onlyUpdateOffsetWith:(FMLayoutBaseSection *)section; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FMLayoutKitFramework/FMLayoutKit.framework/Headers/FMCollectionViewDelegateDataSourceProvider.h ================================================ // // FMCollectionViewDelegateDataSourceProvider.h // FMLayoutKit // // Created by 郑桂华 on 2021/3/27. // #import #import NS_ASSUME_NONNULL_BEGIN @class FMLayoutBaseSection; @interface FMCollectionViewDelegateDataSourceProvider : NSObject ///重写了set get 目标指向->layout.sections @property(nonatomic, strong)NSMutableArray *sections; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FMLayoutKitFramework/FMLayoutKit.framework/Headers/FMKVOArrayObject.h ================================================ // // FMKVOArrayObject.h // FMCollectionLayout // // Created by 周发明 on 2020/6/5. // #import NS_ASSUME_NONNULL_BEGIN @interface FMKVOArrayObject : NSObject @property (strong,nonatomic)NSMutableArray *targetArray; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FMLayoutKitFramework/FMLayoutKit.framework/Headers/FMLayout.h ================================================ // // FMLayout.h // FMLayoutKit // // Created by 周发明 on 2020/6/16. // #import #import "FMLayoutBaseSection.h" #import "FMLayoutHeader.h" #import "FMLayoutFooter.h" #import "FMLayoutBackground.h" #import "FMCollectionLayoutAttributes.h" NS_ASSUME_NONNULL_BEGIN @interface FMLayout : UICollectionViewLayout @property(nonatomic, assign)FMLayoutDirection direction; @property(nonatomic, strong)NSMutableArray *sections; ///最后固定边距 跟section的inset无关 contentSize会自动加上去 @property(nonatomic, assign)CGFloat fixedLastMargin; ///是否只计算改变的布局 NO为每一次 都是重新计算所有布局 @property(nonatomic, assign)BOOL reLayoutOlnyChanged; ///最小可滑动的大小 横向-高度 纵向-宽度 @property(nonatomic, assign)CGFloat minContentSize; ///第一个Section的偏移量 @property(nonatomic, assign)CGFloat firstSectionOffset; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FMLayoutKitFramework/FMLayoutKit.framework/Headers/FMLayoutAbsoluteSection.h ================================================ // // FMLayoutAbsoluteSection.h // FMCollectionLayout // // Created by 周发明 on 2020/6/9. // #import "FMLayoutDynamicSection.h" NS_ASSUME_NONNULL_BEGIN typedef CGRect(^FMLayoutBaseSectionItemFrameBlock)(id section, NSInteger item); ///支持纵向插横向 @interface FMLayoutAbsoluteSection : FMLayoutDynamicSection @property(nonatomic, copy)FMLayoutBaseSectionItemFrameBlock frameBlock; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FMLayoutKitFramework/FMLayoutKit.framework/Headers/FMLayoutBackground.h ================================================ // // FMLayoutBackground.h // FMLayoutKit // // Created by 周发明 on 2020/3/27. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import "FMSupplementary.h" NS_ASSUME_NONNULL_BEGIN static NSString *const UICollectionElementKindSectionBackground = @"UICollectionElementKindSectionBackground"; @interface FMLayoutBackground : FMSupplementary + (instancetype)bgWithViewClass:(Class)viewClass; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FMLayoutKitFramework/FMLayoutKit.framework/Headers/FMLayoutBaseSection.h ================================================ // // FMLayoutBaseSection.h // FMLayoutKit // // Created by 周发明 on 2020/3/20. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import #import #import "FMLayoutDebugLog.h" typedef NS_ENUM(NSUInteger, FMLayoutHandleType) { /// 重新计算 重新布局该分组 FMLayoutHandleTypeReLayout, /// 只是分组偏移高度改变 FMLayoutHandleTypeOlnyChangeOffset, /// 追加布局 FMLayoutHandleTypeAppend }; ///布局方向 typedef NS_ENUM(NSUInteger, FMLayoutDirection) { ///垂直布局 FMLayoutDirectionVertical, ///水平布局 FMLayoutDirectionHorizontal }; ///Item布局方向 typedef NS_ENUM(NSUInteger, FMLayoutItemDirection) { ///水平左边开始 垂直上面开始 FMLayoutItemDirectionLeftTop, ///水平右边开始 垂直下面开始 FMLayoutItemDirectionRightBottom }; ///长按移动的方式 typedef NS_ENUM(NSUInteger, FMLayoutLongMoveType) { ///方格布局时 长按哪里 该cell的中心点就会跟着移动 FMLayoutLongMoveItem, ///列表布局时 上下移动 X不动 FMLayoutLongMoveTable, }; NS_ASSUME_NONNULL_BEGIN @class FMLayoutHeader, FMLayoutFooter, FMLayoutBackground, FMCollectionLayoutAttributes; @interface FMLayoutBaseSection : NSObject ///仅当布局生效之后才会有值 @property(nonatomic, weak)UICollectionView *collectionView; ///仅当布局生效之后才会有值 @property(nonatomic, strong)NSIndexPath *indexPath; ///是否需要重新计算 设置为NO 布局会重新计算 @property(nonatomic, assign)FMLayoutDirection direction; @property(nonatomic, assign)BOOL hasHandle; @property(nonatomic, assign)NSInteger handleItemStart;///重新计算哪一个开始 @property(nonatomic, assign)FMLayoutHandleType handleType; @property(nonatomic, assign)CGFloat changeOffset; @property(nonatomic, strong)FMCollectionLayoutAttributes * __nullable bgAttribute; @property(nonatomic, strong)FMCollectionLayoutAttributes * __nullable headerAttribute; @property(nonatomic, strong)FMCollectionLayoutAttributes * __nullable footerAttribute; @property(nonatomic, strong)NSArray *itemsAttribute; /// 分组偏移高度 @property(nonatomic, assign)CGFloat sectionOffset; /// 分组大小 纵向-高度 横向-宽度 @property(nonatomic, assign)CGFloat sectionSize; /// 分组内边距 @property(nonatomic, assign)UIEdgeInsets sectionInset; ///分组头部 @property(nonatomic, strong)FMLayoutHeader * __nullable header; ///分组底部 @property(nonatomic, strong)FMLayoutFooter * __nullable footer; ///分组背景 @property(nonatomic, strong)FMLayoutBackground * __nullable background; ///cell行间距 @property(nonatomic, assign)CGFloat lineSpace; ///cell间距 @property(nonatomic, assign)CGFloat itemSpace; ///cell列数 纵向-列数 横向-行数 @property(nonatomic, assign)NSInteger column; ///每一列的高度缓存 @property(nonatomic, strong)NSMutableDictionary *columnSizes; ///每一个分组的item个数 默认返回itemDatas.count @property(nonatomic, assign)NSInteger itemCount; ///cell数据数组 @property(nonatomic, strong)NSMutableArray *itemDatas; ///是否可以长按移动排序该分组 默认No 需配合FMLayoutView的enableLongPressDrag使用 @property(nonatomic, assign)BOOL canLongPressExchange; ///长按移动的方式 @property(nonatomic, assign)FMLayoutLongMoveType moveType; ///某一个item是否可以移动替换 @property(nonatomic, copy)BOOL(^canLongPressExchangeItem)(id section, NSInteger item); /// 显示隐藏 @property(nonatomic, assign, getter=isHidden)BOOL hidden; ///第一个Item的Y值 横向纵向有区别 @property(nonatomic, assign, readonly)CGFloat firstItemStartY; ///第一个Item的X值 横向纵向有区别 @property(nonatomic, assign, readonly)CGFloat firstItemStartX; ///配置一下Attributes @property(nonatomic, copy)void(^configureCellLayoutAttributes)(id section, UICollectionViewLayoutAttributes *attributes, NSInteger item); ///配置头部的block @property(nonatomic, copy)void(^configureHeaderData)(FMLayoutBaseSection *section, UICollectionReusableView *header); ///配置底部的block @property(nonatomic, copy)void(^configureFooterData)(FMLayoutBaseSection *section, UICollectionReusableView *footer); ///配置背景的block @property(nonatomic, copy)void(^configureBg)(FMLayoutBaseSection *section, UICollectionReusableView *bg); ///配置Cell的block @property(nonatomic, copy)void(^configureCellData)(FMLayoutBaseSection *section, UICollectionViewCell *cell, NSInteger item); ///cell点击事件 @property(nonatomic, copy)void(^clickCellBlock)(FMLayoutBaseSection *section, NSInteger item); + (instancetype)sectionWithSectionInset:(UIEdgeInsets)inset itemSpace:(CGFloat)itemSpace lineSpace:(CGFloat)lineSpace column:(NSInteger)column; ///标记某一个改变 即将刷新该分组的大小 主要用于动态分组 - (void)markChangeAt:(NSInteger)index; - (void)handleLayout; - (BOOL)intersectsRect:(CGRect)rect; - (void)prepareHeader; - (void)prepareFooter; - (void)prepareItems; - (void)prepareBackground; - (NSArray *)showLayoutAttributesInRect:(CGRect)rect; ///即将显示的头部布局 - (UICollectionViewLayoutAttributes *)showHeaderLayout; ///根据index计算出该布局对象 - (FMCollectionLayoutAttributes *)getItemAttributesWithIndex:(NSInteger)index; - (BOOL)prepareLayoutItemsIsOlnyChangeOffset; ///获取最小高度的列 - (NSInteger)getMinHeightColumn; - (CGFloat)getColumnMaxHeight; ///重置所有列的高度缓存 - (void)resetcolumnSizes; ///交叉布局时单一sention的大小 - (CGFloat)crossSingleSectionSize; - (void)exchangeObjectAtIndex:(NSInteger)index toIndex:(NSInteger)toIndex; - (UICollectionViewCell *)dequeueReusableCellForIndexPath:(NSIndexPath *)indexPath; - (UICollectionViewCell *)dequeueReusableCellForIndexPath:(NSIndexPath *)indexPath collectionView:(UICollectionView *)collectionView; - (void)registerCells; - (void)registerCellsWithCollectionView:(UICollectionView *)collectionView; - (void)reload; - (void)reloadItem:(NSInteger)item; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FMLayoutKitFramework/FMLayoutKit.framework/Headers/FMLayoutCombineSection.h ================================================ // // FMLayoutCombineSection.h // FMLayoutKit // // Created by 郑桂华 on 2020/7/12. // #import "FMLayoutBaseSection.h" NS_ASSUME_NONNULL_BEGIN ///可以将不同Cell, 不同的布局方式, 放到同一个分组去合并,只合并cell, 如果子分组有头部和底部讲被忽略,合并分组的头部与底部不影响配置, cell的点击事件已经在init方法中配置block分发到子分组上 合并分组不支持拖拽排序 想要支持 可以继承自该类重写canLongPressExchange的get方法 并实现- (void)exchangeObjectAtIndex:(NSInteger)index toIndex:(NSInteger)toIndex; @interface FMLayoutCombineSection : FMLayoutBaseSection @property(nonatomic, readonly)NSArray *subSections; + (instancetype)combineSections:(NSArray *)sections; - (void)appendSection:(FMLayoutBaseSection *)section; - (void)insetSection:(FMLayoutBaseSection *)section atIndex:(NSInteger)index; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FMLayoutKitFramework/FMLayoutKit.framework/Headers/FMLayoutCrossSection.h ================================================ // // FMLayoutCrossSection.h // FMLayoutKit // // Created by 周发明 on 2020/6/16. // #import "FMLayoutBaseSection.h" NS_ASSUME_NONNULL_BEGIN @interface FMLayoutCrossSection : FMLayoutBaseSection @property(nonatomic, assign, readonly)FMLayoutDirection crossDirection; /// 所有section计算获取最大的高度 @property(nonatomic, assign)BOOL autoMaxSize; /// 所有section计算获取最大的高度 @property(nonatomic, assign)CGFloat size; @property(nonatomic, assign)BOOL canReuseCell; @property(nonatomic, assign, readonly)CGFloat maxContentWidth; @property(nonatomic, strong)NSMutableArray *sections; @property(nonatomic, copy)void(^scrollDidScroll)(UICollectionView *collectionView, FMLayoutCrossSection *hSection); @property(nonatomic, copy)void(^configureCollectionView)(UICollectionView *collectionView, FMLayoutCrossSection *hSection); + (instancetype)sectionAutoWithSection:(FMLayoutBaseSection *)section; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FMLayoutKitFramework/FMLayoutKit.framework/Headers/FMLayoutCrossTransformSection.h ================================================ // // FMLayoutCrossTransformSection.h // FMLayoutKit // // Created by 郑桂华 on 2020/7/15. // #import "FMLayoutCrossSection.h" NS_ASSUME_NONNULL_BEGIN typedef NS_ENUM(NSUInteger, FMLayoutCrossTransformType) { ///什么都不做 FMLayoutCrossTransformNone, ///缩小0.9 + 0.1*进度 FMLayoutCrossTransformScale, ///简拼App首页样式 M_PI_4 * 0.5 * 进度 FMLayoutCrossTransformCrooked, ///折叠效果 FMLayoutCrossTransformFold, }; ///Cell是需要做处理的cell, progress是指cell中心点到屏幕边缘移动的进度 -1 ~ 1 0为在最中间 -1在左边 1在右边 typedef void(^FMLayoutCrossTransformBlock)(UICollectionViewCell *cell, CGFloat progress); ///当前仅针对横向做适配 更多的动画 @interface FMLayoutCrossTransformSection : FMLayoutCrossSection ///形变类型 @property(nonatomic, assign)FMLayoutCrossTransformType transformType; ///如果有该Block 则优先执行此block @property(nonatomic, copy)FMLayoutCrossTransformBlock __nullable transformBlock; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FMLayoutKitFramework/FMLayoutKit.framework/Headers/FMLayoutDebugLog.h ================================================ // // FMLayoutDebugLog.h // FMLayoutKit // // Created by 周发明 on 2020/6/17. // #import NS_ASSUME_NONNULL_BEGIN extern void FMLayoutLog(NSString *format); extern void FMLayoutOpenLog(void); extern void FMLayoutCloseLog(void); extern NSInteger FMLayoutRandomValue(NSInteger start, NSInteger end); NS_ASSUME_NONNULL_END ================================================ FILE: Example/FMLayoutKitFramework/FMLayoutKit.framework/Headers/FMLayoutDynamicSection.h ================================================ // // FMLayoutDynamicSection.h // FMLayoutKit // // Created by 周发明 on 2020/4/1. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import "FMLayoutBaseSection.h" #import "FMLayoutElement.h" NS_ASSUME_NONNULL_BEGIN ///返回cell大小的block 横向-返回宽度 纵向-返回高度 typedef CGFloat(^FMLayoutItemOtherBlock)(id section, NSInteger item); typedef CGFloat(^FMLayoutAutoHeightLaterBlock)(id section, NSInteger item, CGFloat autoHeight); ///动态 可以注册多种cell 宽度固定 高度可以自适应 但需要用block填充数据 需要设置deqCellReturnReuseId该block值以获取cell 高度亦可以通过手动计算heightBlock返回 手动计算优先级要高 @interface FMLayoutDynamicSection : FMLayoutBaseSection /// yes时 布局耗时比较长 是否自动计算高度 需设置configurationCell方法填充数据 仅支持纵向布局时使用 @property(nonatomic, assign)BOOL autoHeightFixedWidth; @property(nonatomic, copy)FMLayoutAutoHeightLaterBlock autoHeightLaterHander; ///cell固定一个方向的大小 纵向-宽度 横向-高度 @property(nonatomic, assign)CGFloat cellFixedSize; ///需要注册的cell元素 @property(nonatomic, strong)NSArray *cellElements; ///固定单一分组 当固定单一分组时 可以不用手动配置deqCellReturnReuseId @property(nonatomic, strong)FMLayoutElement *cellElement; ///获取cell的复用FMLayoutElement @property(nonatomic, copy)FMLayoutElement *(^deqCellReturnElement)(FMLayoutDynamicSection *section, NSInteger item); ///填充数据 仅当autoHeightFixedWidth为Yes时有用 @property(nonatomic, copy)void(^configurationCell)(FMLayoutDynamicSection *section, UICollectionViewCell *cell, NSInteger item); ///block返回手动计算的高度 优先级比自动的高 @property(nonatomic, copy)FMLayoutItemOtherBlock otherBlock; - (CGFloat)autoHeightVerticalWithWidth:(CGFloat)fixedWidth index:(NSInteger)index; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FMLayoutKitFramework/FMLayoutKit.framework/Headers/FMLayoutElement.h ================================================ // // FMLayoutElement.h // FMLayoutKit // // Created by 周发明 on 2020/4/1. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import #import NS_ASSUME_NONNULL_BEGIN @interface FMLayoutElement : NSObject @property(nonatomic, copy)NSString *reuseIdentifier; @property(nonatomic, assign)BOOL isNib; @property(nonatomic, weak)Class viewClass;///视图的类 + (instancetype)elementWithViewClass:(Class)vCalss; + (instancetype)elementWithViewClass:(Class)vCalss isNib:(BOOL)isNib; + (instancetype)elementWithViewClass:(Class)vCalss isNib:(BOOL)isNib reuseIdentifier:(NSString *)reuseIdentifier; - (void)registerElementWithCollection:(UICollectionView *)collectionView; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FMLayoutKitFramework/FMLayoutKit.framework/Headers/FMLayoutFillSection.h ================================================ // // FMLayoutFillSection.h // FMCollectionLayout // // Created by 周发明 on 2020/4/11. // #import "FMLayoutDynamicSection.h" NS_ASSUME_NONNULL_BEGIN ///返回cell大小的block typedef CGSize(^FMLayoutItemSizeBlock)(id section, NSInteger item); ///支持纵向插横向 只可以上对齐以及左对齐 @interface FMLayoutFillSection : FMLayoutDynamicSection @property(nonatomic, copy)FMLayoutItemSizeBlock sizeBlock; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FMLayoutKitFramework/FMLayoutKit.framework/Headers/FMLayoutFixedSection.h ================================================ // // FMLayoutFixedSection.h // FMLayoutKit // // Created by 周发明 on 2020/4/1. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import "FMLayoutBaseSection.h" #import "FMLayoutElement.h" NS_ASSUME_NONNULL_BEGIN ///固定cell的大小 单一一种cell样式 支持同样cell是否可以横向滚动 内嵌collectionView 支持纵向插横向 @interface FMLayoutFixedSection : FMLayoutBaseSection @property(nonatomic, assign)CGSize itemSize;///分组cell大小 @property(nonatomic, strong)FMLayoutElement *cellElement;///固定分组 @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FMLayoutKitFramework/FMLayoutKit.framework/Headers/FMLayoutFooter.h ================================================ // // FMLayoutFooter.h // FMLayoutKit // // Created by 周发明 on 2020/3/20. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import "FMSupplementary.h" NS_ASSUME_NONNULL_BEGIN @interface FMLayoutFooter : FMSupplementary /// 距离最后Item的距离 纵向-上方 横向-左边 @property(nonatomic, assign)CGFloat topMargin; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FMLayoutKitFramework/FMLayoutKit.framework/Headers/FMLayoutHeader.h ================================================ // // FMLayoutHeader.h // FMLayoutKit // // Created by 周发明 on 2020/3/20. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import "FMSupplementary.h" NS_ASSUME_NONNULL_BEGIN /// 悬浮方式 typedef NS_ENUM(NSInteger, FMLayoutHeaderType) { ///跟着滚动 FMLayoutHeaderTypeFixed, ///悬浮在顶部 跟着section动 FMLayoutHeaderTypeSuspension, ///悬浮在顶部 不跟随section动 如果出现多个可能会被覆盖 FMLayoutHeaderTypeSuspensionAlways, ///仅支持在第一个头部 下拉放大效果 FMLayoutHeaderTypeSuspensionBigger }; @interface FMLayoutHeader : FMSupplementary /// 显示方式 是悬浮 还是跟着滚动 默认跟着滚动 @property(nonatomic, assign)FMLayoutHeaderType type; /// 悬浮模式时距离顶部的高度 可以来设置两个悬浮的方式 多个顶部悬浮时 可以通过这个来达到层叠悬浮的模式 @property(nonatomic, assign)CGFloat suspensionTopMargin; /// 距离第一个Item的距离 纵向-下方 横向-右边 @property(nonatomic, assign)CGFloat lastMargin; ///是否黏在顶部 目前仅支持FMLayoutHeaderTypeSuspensionAlways, FMLayoutHeaderTypeSuspensionBigger悬浮模式 不同的type效果不同 FMLayoutHeaderTypeSuspensionAlways是下拉黏在当前位置 上拉黏在顶部 而FMLayoutHeaderTypeSuspensionBiggers是上拉黏在顶部 下拉时放大效果 @property(nonatomic, assign)BOOL isStickTop; /// 缩放模式(SuspensionBigger)下最小值 横向-宽度 纵向-高度 该值请务必小于size 默认是0 @property(nonatomic, assign)CGFloat minSize; /// 缩放模式(SuspensionBigger)下最大值 横向-宽度 纵向-高度 该值请务必大于size 默认是CGFLOAT_MAX @property(nonatomic, assign)CGFloat maxSize; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FMLayoutKitFramework/FMLayoutKit.framework/Headers/FMLayoutKit-umbrella.h ================================================ #ifdef __OBJC__ #import #else #ifndef FOUNDATION_EXPORT #if defined(__cplusplus) #define FOUNDATION_EXPORT extern "C" #else #define FOUNDATION_EXPORT extern #endif #endif #endif #import "FMLayoutBackground.h" #import "FMLayoutElement.h" #import "FMLayoutFooter.h" #import "FMLayoutHeader.h" #import "FMSupplementary.h" #import "FMCollectionLayoutAttributes.h" #import "FMKVOArrayObject.h" #import "FMLayout.h" #import "FMLayoutView.h" #import "FMTeslaLayoutView.h" #import "FMTeslaSuspensionHeightChangeDelegate.h" #import "FMLayoutCrossSection.h" #import "FMLayoutAbsoluteSection.h" #import "FMLayoutBaseSection.h" #import "FMLayoutDynamicSection.h" #import "FMLayoutFillSection.h" #import "FMLayoutFixedSection.h" #import "FMLayoutLabelSection.h" FOUNDATION_EXPORT double FMLayoutKitVersionNumber; FOUNDATION_EXPORT const unsigned char FMLayoutKitVersionString[]; ================================================ FILE: Example/FMLayoutKitFramework/FMLayoutKit.framework/Headers/FMLayoutKit.h ================================================ // // FMLayoutKit.h // FMLayoutKit // // Created by 周发明 on 2020/6/9. // #ifndef FMLayoutKit_h #define FMLayoutKit_h #import "FMTeslaLayoutView.h" #import "FMLayoutView.h" #import "FMLayout.h" #import "FMCollectionLayoutAttributes.h" #import "FMTeslaSuspensionHeightChangeDelegate.h" #import "FMLayoutFixedSection.h" #import "FMLayoutDynamicSection.h" #import "FMLayoutLabelSection.h" #import "FMLayoutFillSection.h" #import "FMLayoutAbsoluteSection.h" #import "FMLayoutCrossSection.h" #import "FMLayoutCrossTransformSection.h" #import "FMLayoutCombineSection.h" #import "FMLayoutScaleSection.h" #import "FMSupplementary.h" #import "FMLayoutHeader.h" #import "FMLayoutFooter.h" #import "FMLayoutBackground.h" #endif /* FMLayoutKit_h */ ================================================ FILE: Example/FMLayoutKitFramework/FMLayoutKit.framework/Headers/FMLayoutLabelSection.h ================================================ // // FMLayoutLabelSection.h // FMCollectionLayout // // Created by 周发明 on 2020/4/8. // #import "FMLayoutDynamicSection.h" #import "FMLayoutElement.h" NS_ASSUME_NONNULL_BEGIN ///返回cell大小的block typedef CGFloat(^FMLayoutItemWidthBlock)(id section, NSInteger item); ///当到第多少个的时候超出最大行 可移除数据处理 itemDatas会清理 否则frame为zero typedef CGFloat(^FMLayoutOverItemBlock)(id section, NSInteger item); ///标签式布局 根据文本伸缩布局 宽度不够 换行 适用于历史搜索记录 sku选择等样式 @interface FMLayoutLabelSection : FMLayoutDynamicSection ///最大行数 超出讲不显示 纵向布局时生效 @property(nonatomic, assign)NSInteger maxLine; ///cell固定的高度 @property(nonatomic, assign)CGFloat cellFixedHeight; ///cell最大宽度 不设置的话 就是collection的宽度减去左右分组内边距 @property(nonatomic, assign)CGFloat cellMaxWidth; ///block返回手动计算的宽度 @property(nonatomic, copy)FMLayoutItemWidthBlock widthBlock; ///block返回手动计算的宽度 @property(nonatomic, copy)FMLayoutOverItemBlock overItemBlock; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FMLayoutKitFramework/FMLayoutKit.framework/Headers/FMLayoutScaleSection.h ================================================ // // FMLayoutScaleSection.h // FMLayoutKit // // Created by 郑桂华 on 2020/7/20. // #import "FMLayoutDynamicSection.h" NS_ASSUME_NONNULL_BEGIN ///支持两种设置固定大小的方式 一种直接给数组sizeNums 一种给比例字符串scales 后设置的生效 @interface FMLayoutScaleSection : FMLayoutDynamicSection /// 纵向布局 则是宽度比例 横向布局 则是高度比例 例如纵向布局时该值为: 1:2:3 则就是3列 宽度比为剩下的值的比例 仅支持当前样式 可以是小数值 但不能为非数值类型 @property(nonatomic, copy)NSString *scales; ///每一列的固定大小 如:@[@100, @200] 则表示两列 一个固定宽度为100 另外一列为200 共两列 @property(nonatomic, strong)NSArray *sizeNums; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FMLayoutKitFramework/FMLayoutKit.framework/Headers/FMLayoutView.h ================================================ // // FMLayoutView.h // FMLayoutKit // // Created by 周发明 on 2020/4/1. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import #import "FMLayout.h" NS_ASSUME_NONNULL_BEGIN @interface FMLayoutView : UICollectionView @property(nonatomic, weak)FMLayout *layout; ///重写了set get 目标指向->layout.sections @property(nonatomic)NSMutableArray *sections; @property(nonatomic, assign)BOOL reloadOlnyChanged; ///是否允许长按拖拽排序 不支持夸分组 分组需要开启canLongPressExchange才可以移动拖拽排序 @property(nonatomic, assign)BOOL enableLongPressDrag; ///长按拖拽开始时配置cell显示的样式 @property(nonatomic, copy)UIView *(^configureSourceView)(UICollectionViewCell *sourceCell); - (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout NS_UNAVAILABLE; - (instancetype)initHorizontal; - (instancetype)initHorizontalWithFrame:(CGRect)frame; /// 循环遍历出更改过的sections 如果有过增删分组 请使用原有的reloadData方法 - (void)reloadChangedSectionsData; ///获取到滚动到indexPath位置偏移量 如果获取到的不准确 请先调用layoutIfNeeded方法 - (CGPoint)contentOffsetScrollToIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UICollectionViewScrollPosition)scrollPosition; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FMLayoutKitFramework/FMLayoutKit.framework/Headers/FMSupplementary.h ================================================ // // FMSupplementary.h // FMLayoutKit // // Created by 周发明 on 2020/3/20. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import "FMLayoutElement.h" typedef NS_ENUM(NSInteger, FMLayoutZIndex) { ///最底层 头部 底部 Item的下方 FMLayoutZIndexBg = -9999, ///Item的下方 FMLayoutZIndexBackOfItem = -1, /// 自动悬浮可能会被覆盖 FMLayoutZIndexAuto = 0, /// Item的上方 FMLayoutZIndexFrontOfItem = 1, /// 最最上方 FMLayoutZIndexFrontAlways = 9999 }; NS_ASSUME_NONNULL_BEGIN /// 请使用子类Footer, Header, Background @interface FMSupplementary : FMLayoutElement ///该Element的大小 纵向-高度 横向-宽度 @property(nonatomic, assign)CGFloat size; ///视图层级 最上方还是最下方等 @property(nonatomic, assign)FMLayoutZIndex zIndex; ///内边距 HeaderFooter受sectionInset影响 Background不受sectionInset影响 @property(nonatomic, assign)UIEdgeInsets inset; ///Element类型 Header Footer Background等 @property(nonatomic, copy, readonly)NSString *elementKind; ///是否自适应高度 仅当垂直布局时可用 @property(nonatomic, assign)BOOL autoHeight; @property(nonatomic, copy)void(^configureDataAutoHeight)(UICollectionReusableView *view); + (instancetype)elementSize:(CGFloat)size viewClass:(Class)vClass; + (instancetype)elementSize:(CGFloat)size viewClass:(Class)vClass isNib:(BOOL)isNib; + (instancetype)elementSize:(CGFloat)size viewClass:(Class)vClass isNib:(BOOL)isNib reuseIdentifier:(NSString *)reuseIdentifier; - (UICollectionReusableView *)dequeueReusableViewWithCollection:(UICollectionView *)collectionView indexPath:(NSIndexPath *)indexPath; - (void)updateHeightWithCollection:(UICollectionView *)collectionView indexPath:(NSIndexPath *)indexPath maxWidth:(CGFloat)maxWidth; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FMLayoutKitFramework/FMLayoutKit.framework/Headers/FMTeslaLayoutView.h ================================================ // // FMTeslaLayoutView.h // FMCollectionLayout_Example // // Created by 周发明 on 2020/4/8. // Copyright © 2020 周发明. All rights reserved. // #import NS_ASSUME_NONNULL_BEGIN @class FMLayoutView, FMTeslaLayoutView, FMLayoutBaseSection; @protocol FMTeslaLayoutViewDelegate @optional ///滚动结束事件 - (void)tesla:(FMTeslaLayoutView *)tesla didScrollEnd:(NSInteger)index currentScrollView:(UIScrollView *)scrollView; ///滚动事件 - (void)tesla:(FMTeslaLayoutView *)tesla scrollViewDidScroll:(UIScrollView *)scrollView; /// 当前上下滚动的事件 - (void)tesla:(FMTeslaLayoutView *)tesla currentScrollViewScrollDidScroll:(UIScrollView *)currentScrollView contentOffset:(CGPoint)contentOffset; /// 配置FMCollectionLayoutView ///2 - (void)tesla:(FMTeslaLayoutView *)tesla currentShowScrollView:(UIScrollView *)scrollView index:(NSInteger)index; ///0 即将根据Index创建FMCollectionLayoutView - (void)tesla:(FMTeslaLayoutView *)tesla willCreateScrollViewWithIndex:(NSInteger)index; ///0.5 根据Index自己创建FMCollectionLayoutView shareHeight为共享头部的高度 请将shareHeight顶部空出来并且请保持不使用contentInset 如果返回nil会自动创建FMLayoutView - (UIScrollView *)tesla:(FMTeslaLayoutView *)tesla customCreateWithIndex:(NSInteger)index shareHeight:(CGFloat)shareHeight; ///1 根据Index创建完毕UIScrollView - (void)tesla:(FMTeslaLayoutView *)tesla didCreatedScrollViewWithIndex:(NSInteger)index scrollView:(UIScrollView *)scrollView; /// 悬停标签控制view的尺寸最小高度 可以留着做效果 - (CGFloat)shareSuspensionMinHeightWithTesla:(FMTeslaLayoutView *)tesla; @end @protocol FMTeslaLayoutViewDataSource @required - (NSInteger)numberOfScreenInTesla:(FMTeslaLayoutView *)tesla; @optional - (NSArray *)shareSectionsInTesla:(FMTeslaLayoutView *)tesla; @end @class FMLayoutBaseSection; @interface FMTeslaLayoutView : UIView @property(nonatomic, weak)id delegate; @property(nonatomic, weak)id dataSource; @property(nonatomic, assign)BOOL horizontalCanScroll; @property(nonatomic, assign)BOOL allShareStickTop; @property(nonatomic, assign)NSInteger selectIndex; @property(nonatomic, assign)BOOL isLoadSubView; @property(nonatomic, assign)CGFloat shareHeight; @property(nonatomic, strong, readonly)FMLayoutView *shareLayoutView; - (void)reLoadSubViews; - (void)reloadData; - (void)reloadDataWithIndex:(NSInteger)index; - (void)scrollToIndex:(NSInteger)index animated:(BOOL)animated; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FMLayoutKitFramework/FMLayoutKit.framework/Headers/FMTeslaSuspensionHeightChangeDelegate.h ================================================ // // FMTeslaSuspensionHeightChangeDelegate.h // FMCollectionLayout // // Created by 周发明 on 2020/5/13. // #import #import NS_ASSUME_NONNULL_BEGIN @protocol FMTeslaSuspensionHeightChangeDelegate - (void)teslaSuspensionHeaderShouldShowHeight:(CGFloat)showHeight; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FMLayoutKitFramework/FMLayoutKit.framework/Modules/module.modulemap ================================================ framework module FMLayoutKit { umbrella header "FMLayoutKit-umbrella.h" export * module * { export * } } ================================================ FILE: Example/FMLayoutKitFramework/FMLayoutKit.framework/_CodeSignature/CodeResources ================================================ files Headers/FMCollectionLayoutAttributes.h O30CaMucsbKG9WZDD3g+/zKOfdM= Headers/FMCollectionViewDelegateDataSourceProvider.h ev11njieIDCjXwxq6tE+0Go8Q2U= Headers/FMKVOArrayObject.h kcnRWMH4+X3NQn5BnR4efXkPI48= Headers/FMLayout.h GQflgCCxMGkdLFIzyju1R2oJpf8= Headers/FMLayoutAbsoluteSection.h O2MA6nxtIs47HrBwUMOfcGnKJ0o= Headers/FMLayoutBackground.h VDMpTbXT56ILF3enWgcXnqMGjMw= Headers/FMLayoutBaseSection.h /jt+WcYC5h4CPHpOd36eSQTRBaQ= Headers/FMLayoutCombineSection.h 9Ca3BaGs0c0NZfHxfZBVe0ls80w= Headers/FMLayoutCrossSection.h o9roPsaYR9oNzgGMFa75Mgdza+Y= Headers/FMLayoutCrossTransformSection.h U0NpzET9KhE6GXk9fud72RNE3lQ= Headers/FMLayoutDebugLog.h hcHKMAS/zM85rSoKqtsh6YPUy8w= Headers/FMLayoutDynamicSection.h HuPBUS7LR6FPj2xsGw0DepkUn4s= Headers/FMLayoutElement.h 8j97vy5ReOxOZXWPyyMjpBjkw5o= Headers/FMLayoutFillSection.h q1u3flkbJnUv725iYsAygE/6IW8= Headers/FMLayoutFixedSection.h MaPJ7tBFI85i25VGlklMiKKpzDE= Headers/FMLayoutFooter.h 2lb118tQJQgTVN+H8Og17xOvvhE= Headers/FMLayoutHeader.h 2wulFPpiYi/uV9uGVsKHMJCern0= Headers/FMLayoutKit-umbrella.h NilO12VNPzuBwk9x0e+lUmull3c= Headers/FMLayoutKit.h HIOrlmnsHlyNgbdt0mpA4dFeWBc= Headers/FMLayoutLabelSection.h ycPX8RMIU6oksfjdGsVVn9O5TEI= Headers/FMLayoutScaleSection.h gSjqmu/leF1yywOB6KoxeRlRgEA= Headers/FMLayoutView.h lP9zIEONqVArA35PEiIK+U+ZNvU= Headers/FMSupplementary.h 4a81sKmC/RMUO21JmLjBKfzkkMw= Headers/FMTeslaLayoutView.h MwC3uPYp+7202ev6w/XfyvYLCys= Headers/FMTeslaSuspensionHeightChangeDelegate.h lOgFWZxDriaARd5TuLHcp2YF6cw= Info.plist 5NI7zkvtvlP1PUJdEbD/5J1CORQ= Modules/module.modulemap Z/5Z445TliUtpHrk7ROMmxzLDDs= files2 Headers/FMCollectionLayoutAttributes.h hash O30CaMucsbKG9WZDD3g+/zKOfdM= hash2 SCNBzW5LNIJojXnqfuLkihBO9jxcvnaqvxxfo7C5ZSU= Headers/FMCollectionViewDelegateDataSourceProvider.h hash ev11njieIDCjXwxq6tE+0Go8Q2U= hash2 hmN+CbBZ5zDyEvRMSd6A4eviJMA/TyC5tlorNzw5fnc= Headers/FMKVOArrayObject.h hash kcnRWMH4+X3NQn5BnR4efXkPI48= hash2 0KMHK5kWPwHQZh/osJ5KJXYeAdvZCy6/8D9IMJkw2SA= Headers/FMLayout.h hash GQflgCCxMGkdLFIzyju1R2oJpf8= hash2 H67WFCXwOBJ9siR0RKfVNt6BrkIzHgl/zwkxIbbNpbo= Headers/FMLayoutAbsoluteSection.h hash O2MA6nxtIs47HrBwUMOfcGnKJ0o= hash2 iHDQ1jmsfUo7qcQ9OTjQkgp96/rrOotyC9htTOWlNR0= Headers/FMLayoutBackground.h hash VDMpTbXT56ILF3enWgcXnqMGjMw= hash2 CW8h/vOzmlw2IZWcpW2jxe1PxDARpIxonuIDQmlIbO0= Headers/FMLayoutBaseSection.h hash /jt+WcYC5h4CPHpOd36eSQTRBaQ= hash2 batXXhqHW6BZLaMuSziNhp9yQAxbau9enfI6FpqOhoU= Headers/FMLayoutCombineSection.h hash 9Ca3BaGs0c0NZfHxfZBVe0ls80w= hash2 PMvd1uBvRZLMthhOlow1a0S+2bJDgb988cjE6bNZv8A= Headers/FMLayoutCrossSection.h hash o9roPsaYR9oNzgGMFa75Mgdza+Y= hash2 mvztFegbd5j2kvLnIwTnffY9pnYNIRvz4g/nx++OxOU= Headers/FMLayoutCrossTransformSection.h hash U0NpzET9KhE6GXk9fud72RNE3lQ= hash2 sl96qMNZLLBY2KBdLqxoaLG3SXlrSAHqX/SSBR0McCU= Headers/FMLayoutDebugLog.h hash hcHKMAS/zM85rSoKqtsh6YPUy8w= hash2 taTztq608Z0h6SkQDJaxSV3a2QYVQ2JRAb3lLKD2ZHQ= Headers/FMLayoutDynamicSection.h hash HuPBUS7LR6FPj2xsGw0DepkUn4s= hash2 Ej6/nfzrs2yDH+Xyv7AXjHNuabjb1IjuJABodcY4PAg= Headers/FMLayoutElement.h hash 8j97vy5ReOxOZXWPyyMjpBjkw5o= hash2 cQd54yq/XVSc9SxhSuoeR4dvAjTmHq91IFYzq/2Wm7k= Headers/FMLayoutFillSection.h hash q1u3flkbJnUv725iYsAygE/6IW8= hash2 hIeJINDY21gLv90VaEso9+R63BPmrJhsaU555Y3GehQ= Headers/FMLayoutFixedSection.h hash MaPJ7tBFI85i25VGlklMiKKpzDE= hash2 OaeTbT6Ir6FA5F8e9U2Uj12RqsNm2eqidKj65UP+nII= Headers/FMLayoutFooter.h hash 2lb118tQJQgTVN+H8Og17xOvvhE= hash2 BzXtLCIkyAliHRZhU/pptph0GD8qO5vqHm4qpOIi5Fs= Headers/FMLayoutHeader.h hash 2wulFPpiYi/uV9uGVsKHMJCern0= hash2 yqZkxJvTMCrIsIuwdJdd5DlZ248yYOjlPoKLsgyXG7k= Headers/FMLayoutKit-umbrella.h hash NilO12VNPzuBwk9x0e+lUmull3c= hash2 E3e3VBmNAwNU19lpVXQEHYxEkSaaWAbBJY0Eq58c8Ws= Headers/FMLayoutKit.h hash HIOrlmnsHlyNgbdt0mpA4dFeWBc= hash2 s/tvERCyPoaAw5jgZwhSjMp98KLnuCelRQ5bcINp3Cw= Headers/FMLayoutLabelSection.h hash ycPX8RMIU6oksfjdGsVVn9O5TEI= hash2 4Ak8oYcQ4Spvazli4pEKXOPJsAZshRCbULAUUh/aYLY= Headers/FMLayoutScaleSection.h hash gSjqmu/leF1yywOB6KoxeRlRgEA= hash2 ghd2zI3OpDzgd2XwCmOTli/Mmhv2IVNQ2O8qGVf8Pzc= Headers/FMLayoutView.h hash lP9zIEONqVArA35PEiIK+U+ZNvU= hash2 wx1am9ZXc6sIjDDUjDzFt5WiPAZ2qiHc8qqqladCHTk= Headers/FMSupplementary.h hash 4a81sKmC/RMUO21JmLjBKfzkkMw= hash2 6YuaHMqNEUl3gOPsuX/Ih+Du453H5qJkiy8w6TBQcIo= Headers/FMTeslaLayoutView.h hash MwC3uPYp+7202ev6w/XfyvYLCys= hash2 LmsHrUMgKAW/6tk+QQYlrokJ+VC02DZvvASDEW4pmMs= Headers/FMTeslaSuspensionHeightChangeDelegate.h hash lOgFWZxDriaARd5TuLHcp2YF6cw= hash2 9Ku3TOJdLs0MlcrBFJzVg/LUZdqDeGMT7KTainEGyPE= Modules/module.modulemap hash Z/5Z445TliUtpHrk7ROMmxzLDDs= hash2 2Leh+uJxOIj87iJ/CeSmmbcCjX20OMUO5G6x3eou49I= rules ^.* ^.*\.lproj/ optional weight 1000 ^.*\.lproj/locversion.plist$ omit weight 1100 ^Base\.lproj/ weight 1010 ^version.plist$ rules2 .*\.dSYM($|/) weight 11 ^(.*/)?\.DS_Store$ omit weight 2000 ^.* ^.*\.lproj/ optional weight 1000 ^.*\.lproj/locversion.plist$ omit weight 1100 ^Base\.lproj/ weight 1010 ^Info\.plist$ omit weight 20 ^PkgInfo$ omit weight 20 ^embedded\.provisionprofile$ weight 20 ^version\.plist$ weight 20 ================================================ FILE: Example/FrameworkTmp/Release-iphoneos/FMLayoutKit/FMLayoutKit.framework/Headers/FMCollectionLayoutAttributes.h ================================================ // // FMCollectionLayoutAttributes.h // FMLayoutKit // // Created by 周发明 on 2020/3/25. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import #import "FMLayoutBaseSection.h" NS_ASSUME_NONNULL_BEGIN @interface FMCollectionLayoutAttributes : UICollectionViewLayoutAttributes @property(nonatomic, assign)FMLayoutDirection direction; + (instancetype)headerAttributesWithSection:(FMLayoutBaseSection *)section; - (instancetype)updateHeaderAttributesWithSection:(FMLayoutBaseSection *)section; + (instancetype)suspensionShowHeaderAttributes:(FMLayoutBaseSection *)section; + (instancetype)footerAttributesWithSection:(FMLayoutBaseSection *)section; - (instancetype)updateFooterAttributesWithSection:(FMLayoutBaseSection *)section; + (instancetype)bgAttributesWithSection:(FMLayoutBaseSection *)section; - (instancetype)updateBgAttributesWithSection:(FMLayoutBaseSection *)section; - (void)_onlyUpdateOffsetWith:(FMLayoutBaseSection *)section; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphoneos/FMLayoutKit/FMLayoutKit.framework/Headers/FMCollectionViewDelegateDataSourceProvider.h ================================================ // // FMCollectionViewDelegateDataSourceProvider.h // FMLayoutKit // // Created by 郑桂华 on 2021/3/27. // #import #import NS_ASSUME_NONNULL_BEGIN @class FMLayoutBaseSection; @interface FMCollectionViewDelegateDataSourceProvider : NSObject ///重写了set get 目标指向->layout.sections @property(nonatomic, strong)NSMutableArray *sections; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphoneos/FMLayoutKit/FMLayoutKit.framework/Headers/FMKVOArrayObject.h ================================================ // // FMKVOArrayObject.h // FMCollectionLayout // // Created by 周发明 on 2020/6/5. // #import NS_ASSUME_NONNULL_BEGIN @interface FMKVOArrayObject : NSObject @property (strong,nonatomic)NSMutableArray *targetArray; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphoneos/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayout.h ================================================ // // FMLayout.h // FMLayoutKit // // Created by 周发明 on 2020/6/16. // #import #import "FMLayoutBaseSection.h" #import "FMLayoutHeader.h" #import "FMLayoutFooter.h" #import "FMLayoutBackground.h" #import "FMCollectionLayoutAttributes.h" NS_ASSUME_NONNULL_BEGIN @interface FMLayout : UICollectionViewLayout @property(nonatomic, assign)FMLayoutDirection direction; @property(nonatomic, strong)NSMutableArray *sections; ///最后固定边距 跟section的inset无关 contentSize会自动加上去 @property(nonatomic, assign)CGFloat fixedLastMargin; ///是否只计算改变的布局 NO为每一次 都是重新计算所有布局 @property(nonatomic, assign)BOOL reLayoutOlnyChanged; ///最小可滑动的大小 横向-高度 纵向-宽度 @property(nonatomic, assign)CGFloat minContentSize; ///第一个Section的偏移量 @property(nonatomic, assign)CGFloat firstSectionOffset; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphoneos/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayoutAbsoluteSection.h ================================================ // // FMLayoutAbsoluteSection.h // FMCollectionLayout // // Created by 周发明 on 2020/6/9. // #import "FMLayoutDynamicSection.h" NS_ASSUME_NONNULL_BEGIN typedef CGRect(^FMLayoutBaseSectionItemFrameBlock)(id section, NSInteger item); ///支持纵向插横向 @interface FMLayoutAbsoluteSection : FMLayoutDynamicSection @property(nonatomic, copy)FMLayoutBaseSectionItemFrameBlock frameBlock; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphoneos/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayoutBackground.h ================================================ // // FMLayoutBackground.h // FMLayoutKit // // Created by 周发明 on 2020/3/27. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import "FMSupplementary.h" NS_ASSUME_NONNULL_BEGIN static NSString *const UICollectionElementKindSectionBackground = @"UICollectionElementKindSectionBackground"; @interface FMLayoutBackground : FMSupplementary + (instancetype)bgWithViewClass:(Class)viewClass; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphoneos/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayoutBaseSection.h ================================================ // // FMLayoutBaseSection.h // FMLayoutKit // // Created by 周发明 on 2020/3/20. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import #import #import "FMLayoutDebugLog.h" typedef NS_ENUM(NSUInteger, FMLayoutHandleType) { /// 重新计算 重新布局该分组 FMLayoutHandleTypeReLayout, /// 只是分组偏移高度改变 FMLayoutHandleTypeOlnyChangeOffset, /// 追加布局 FMLayoutHandleTypeAppend }; ///布局方向 typedef NS_ENUM(NSUInteger, FMLayoutDirection) { ///垂直布局 FMLayoutDirectionVertical, ///水平布局 FMLayoutDirectionHorizontal }; ///Item布局方向 typedef NS_ENUM(NSUInteger, FMLayoutItemDirection) { ///水平左边开始 垂直上面开始 FMLayoutItemDirectionLeftTop, ///水平右边开始 垂直下面开始 FMLayoutItemDirectionRightBottom }; ///长按移动的方式 typedef NS_ENUM(NSUInteger, FMLayoutLongMoveType) { ///方格布局时 长按哪里 该cell的中心点就会跟着移动 FMLayoutLongMoveItem, ///列表布局时 上下移动 X不动 FMLayoutLongMoveTable, }; NS_ASSUME_NONNULL_BEGIN @class FMLayoutHeader, FMLayoutFooter, FMLayoutBackground, FMCollectionLayoutAttributes; @interface FMLayoutBaseSection : NSObject ///仅当布局生效之后才会有值 @property(nonatomic, weak)UICollectionView *collectionView; ///仅当布局生效之后才会有值 @property(nonatomic, strong)NSIndexPath *indexPath; ///是否需要重新计算 设置为NO 布局会重新计算 @property(nonatomic, assign)FMLayoutDirection direction; @property(nonatomic, assign)BOOL hasHandle; @property(nonatomic, assign)NSInteger handleItemStart;///重新计算哪一个开始 @property(nonatomic, assign)FMLayoutHandleType handleType; @property(nonatomic, assign)CGFloat changeOffset; @property(nonatomic, strong)FMCollectionLayoutAttributes * __nullable bgAttribute; @property(nonatomic, strong)FMCollectionLayoutAttributes * __nullable headerAttribute; @property(nonatomic, strong)FMCollectionLayoutAttributes * __nullable footerAttribute; @property(nonatomic, strong)NSArray *itemsAttribute; /// 分组偏移高度 @property(nonatomic, assign)CGFloat sectionOffset; /// 分组大小 纵向-高度 横向-宽度 @property(nonatomic, assign)CGFloat sectionSize; /// 分组内边距 @property(nonatomic, assign)UIEdgeInsets sectionInset; ///分组头部 @property(nonatomic, strong)FMLayoutHeader * __nullable header; ///分组底部 @property(nonatomic, strong)FMLayoutFooter * __nullable footer; ///分组背景 @property(nonatomic, strong)FMLayoutBackground * __nullable background; ///cell行间距 @property(nonatomic, assign)CGFloat lineSpace; ///cell间距 @property(nonatomic, assign)CGFloat itemSpace; ///cell列数 纵向-列数 横向-行数 @property(nonatomic, assign)NSInteger column; ///每一列的高度缓存 @property(nonatomic, strong)NSMutableDictionary *columnSizes; ///每一个分组的item个数 默认返回itemDatas.count @property(nonatomic, assign)NSInteger itemCount; ///cell数据数组 @property(nonatomic, strong)NSMutableArray *itemDatas; ///是否可以长按移动排序该分组 默认No 需配合FMLayoutView的enableLongPressDrag使用 @property(nonatomic, assign)BOOL canLongPressExchange; ///长按移动的方式 @property(nonatomic, assign)FMLayoutLongMoveType moveType; ///某一个item是否可以移动替换 @property(nonatomic, copy)BOOL(^canLongPressExchangeItem)(id section, NSInteger item); /// 显示隐藏 @property(nonatomic, assign, getter=isHidden)BOOL hidden; ///第一个Item的Y值 横向纵向有区别 @property(nonatomic, assign, readonly)CGFloat firstItemStartY; ///第一个Item的X值 横向纵向有区别 @property(nonatomic, assign, readonly)CGFloat firstItemStartX; ///配置一下Attributes @property(nonatomic, copy)void(^configureCellLayoutAttributes)(id section, UICollectionViewLayoutAttributes *attributes, NSInteger item); ///配置头部的block @property(nonatomic, copy)void(^configureHeaderData)(FMLayoutBaseSection *section, UICollectionReusableView *header); ///配置底部的block @property(nonatomic, copy)void(^configureFooterData)(FMLayoutBaseSection *section, UICollectionReusableView *footer); ///配置背景的block @property(nonatomic, copy)void(^configureBg)(FMLayoutBaseSection *section, UICollectionReusableView *bg); ///配置Cell的block @property(nonatomic, copy)void(^configureCellData)(FMLayoutBaseSection *section, UICollectionViewCell *cell, NSInteger item); ///cell点击事件 @property(nonatomic, copy)void(^clickCellBlock)(FMLayoutBaseSection *section, NSInteger item); + (instancetype)sectionWithSectionInset:(UIEdgeInsets)inset itemSpace:(CGFloat)itemSpace lineSpace:(CGFloat)lineSpace column:(NSInteger)column; ///标记某一个改变 即将刷新该分组的大小 主要用于动态分组 - (void)markChangeAt:(NSInteger)index; - (void)handleLayout; - (BOOL)intersectsRect:(CGRect)rect; - (void)prepareHeader; - (void)prepareFooter; - (void)prepareItems; - (void)prepareBackground; - (NSArray *)showLayoutAttributesInRect:(CGRect)rect; ///即将显示的头部布局 - (UICollectionViewLayoutAttributes *)showHeaderLayout; ///根据index计算出该布局对象 - (FMCollectionLayoutAttributes *)getItemAttributesWithIndex:(NSInteger)index; - (BOOL)prepareLayoutItemsIsOlnyChangeOffset; ///获取最小高度的列 - (NSInteger)getMinHeightColumn; - (CGFloat)getColumnMaxHeight; ///重置所有列的高度缓存 - (void)resetcolumnSizes; ///交叉布局时单一sention的大小 - (CGFloat)crossSingleSectionSize; - (void)exchangeObjectAtIndex:(NSInteger)index toIndex:(NSInteger)toIndex; - (UICollectionViewCell *)dequeueReusableCellForIndexPath:(NSIndexPath *)indexPath; - (UICollectionViewCell *)dequeueReusableCellForIndexPath:(NSIndexPath *)indexPath collectionView:(UICollectionView *)collectionView; - (void)registerCells; - (void)registerCellsWithCollectionView:(UICollectionView *)collectionView; - (void)reload; - (void)reloadItem:(NSInteger)item; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphoneos/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayoutCombineSection.h ================================================ // // FMLayoutCombineSection.h // FMLayoutKit // // Created by 郑桂华 on 2020/7/12. // #import "FMLayoutBaseSection.h" NS_ASSUME_NONNULL_BEGIN ///可以将不同Cell, 不同的布局方式, 放到同一个分组去合并,只合并cell, 如果子分组有头部和底部讲被忽略,合并分组的头部与底部不影响配置, cell的点击事件已经在init方法中配置block分发到子分组上 合并分组不支持拖拽排序 想要支持 可以继承自该类重写canLongPressExchange的get方法 并实现- (void)exchangeObjectAtIndex:(NSInteger)index toIndex:(NSInteger)toIndex; @interface FMLayoutCombineSection : FMLayoutBaseSection @property(nonatomic, readonly)NSArray *subSections; + (instancetype)combineSections:(NSArray *)sections; - (void)appendSection:(FMLayoutBaseSection *)section; - (void)insetSection:(FMLayoutBaseSection *)section atIndex:(NSInteger)index; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphoneos/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayoutCrossSection.h ================================================ // // FMLayoutCrossSection.h // FMLayoutKit // // Created by 周发明 on 2020/6/16. // #import "FMLayoutBaseSection.h" NS_ASSUME_NONNULL_BEGIN @interface FMLayoutCrossSection : FMLayoutBaseSection @property(nonatomic, assign, readonly)FMLayoutDirection crossDirection; /// 所有section计算获取最大的高度 @property(nonatomic, assign)BOOL autoMaxSize; /// 所有section计算获取最大的高度 @property(nonatomic, assign)CGFloat size; @property(nonatomic, assign)BOOL canReuseCell; @property(nonatomic, assign, readonly)CGFloat maxContentWidth; @property(nonatomic, strong)NSMutableArray *sections; @property(nonatomic, copy)void(^scrollDidScroll)(UICollectionView *collectionView, FMLayoutCrossSection *hSection); @property(nonatomic, copy)void(^configureCollectionView)(UICollectionView *collectionView, FMLayoutCrossSection *hSection); + (instancetype)sectionAutoWithSection:(FMLayoutBaseSection *)section; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphoneos/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayoutCrossTransformSection.h ================================================ // // FMLayoutCrossTransformSection.h // FMLayoutKit // // Created by 郑桂华 on 2020/7/15. // #import "FMLayoutCrossSection.h" NS_ASSUME_NONNULL_BEGIN typedef NS_ENUM(NSUInteger, FMLayoutCrossTransformType) { ///什么都不做 FMLayoutCrossTransformNone, ///缩小0.9 + 0.1*进度 FMLayoutCrossTransformScale, ///简拼App首页样式 M_PI_4 * 0.5 * 进度 FMLayoutCrossTransformCrooked, ///折叠效果 FMLayoutCrossTransformFold, }; ///Cell是需要做处理的cell, progress是指cell中心点到屏幕边缘移动的进度 -1 ~ 1 0为在最中间 -1在左边 1在右边 typedef void(^FMLayoutCrossTransformBlock)(UICollectionViewCell *cell, CGFloat progress); ///当前仅针对横向做适配 更多的动画 @interface FMLayoutCrossTransformSection : FMLayoutCrossSection ///形变类型 @property(nonatomic, assign)FMLayoutCrossTransformType transformType; ///如果有该Block 则优先执行此block @property(nonatomic, copy)FMLayoutCrossTransformBlock __nullable transformBlock; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphoneos/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayoutDebugLog.h ================================================ // // FMLayoutDebugLog.h // FMLayoutKit // // Created by 周发明 on 2020/6/17. // #import NS_ASSUME_NONNULL_BEGIN extern void FMLayoutLog(NSString *format); extern void FMLayoutOpenLog(void); extern void FMLayoutCloseLog(void); extern NSInteger FMLayoutRandomValue(NSInteger start, NSInteger end); NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphoneos/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayoutDynamicSection.h ================================================ // // FMLayoutDynamicSection.h // FMLayoutKit // // Created by 周发明 on 2020/4/1. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import "FMLayoutBaseSection.h" #import "FMLayoutElement.h" NS_ASSUME_NONNULL_BEGIN ///返回cell大小的block 横向-返回宽度 纵向-返回高度 typedef CGFloat(^FMLayoutItemOtherBlock)(id section, NSInteger item); typedef CGFloat(^FMLayoutAutoHeightLaterBlock)(id section, NSInteger item, CGFloat autoHeight); ///动态 可以注册多种cell 宽度固定 高度可以自适应 但需要用block填充数据 需要设置deqCellReturnReuseId该block值以获取cell 高度亦可以通过手动计算heightBlock返回 手动计算优先级要高 @interface FMLayoutDynamicSection : FMLayoutBaseSection /// yes时 布局耗时比较长 是否自动计算高度 需设置configurationCell方法填充数据 仅支持纵向布局时使用 @property(nonatomic, assign)BOOL autoHeightFixedWidth; @property(nonatomic, copy)FMLayoutAutoHeightLaterBlock autoHeightLaterHander; ///cell固定一个方向的大小 纵向-宽度 横向-高度 @property(nonatomic, assign)CGFloat cellFixedSize; ///需要注册的cell元素 @property(nonatomic, strong)NSArray *cellElements; ///固定单一分组 当固定单一分组时 可以不用手动配置deqCellReturnReuseId @property(nonatomic, strong)FMLayoutElement *cellElement; ///获取cell的复用FMLayoutElement @property(nonatomic, copy)FMLayoutElement *(^deqCellReturnElement)(FMLayoutDynamicSection *section, NSInteger item); ///填充数据 仅当autoHeightFixedWidth为Yes时有用 @property(nonatomic, copy)void(^configurationCell)(FMLayoutDynamicSection *section, UICollectionViewCell *cell, NSInteger item); ///block返回手动计算的高度 优先级比自动的高 @property(nonatomic, copy)FMLayoutItemOtherBlock otherBlock; - (CGFloat)autoHeightVerticalWithWidth:(CGFloat)fixedWidth index:(NSInteger)index; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphoneos/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayoutElement.h ================================================ // // FMLayoutElement.h // FMLayoutKit // // Created by 周发明 on 2020/4/1. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import #import NS_ASSUME_NONNULL_BEGIN @interface FMLayoutElement : NSObject @property(nonatomic, copy)NSString *reuseIdentifier; @property(nonatomic, assign)BOOL isNib; @property(nonatomic, weak)Class viewClass;///视图的类 + (instancetype)elementWithViewClass:(Class)vCalss; + (instancetype)elementWithViewClass:(Class)vCalss isNib:(BOOL)isNib; + (instancetype)elementWithViewClass:(Class)vCalss isNib:(BOOL)isNib reuseIdentifier:(NSString *)reuseIdentifier; - (void)registerElementWithCollection:(UICollectionView *)collectionView; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphoneos/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayoutFillSection.h ================================================ // // FMLayoutFillSection.h // FMCollectionLayout // // Created by 周发明 on 2020/4/11. // #import "FMLayoutDynamicSection.h" NS_ASSUME_NONNULL_BEGIN ///返回cell大小的block typedef CGSize(^FMLayoutItemSizeBlock)(id section, NSInteger item); ///支持纵向插横向 只可以上对齐以及左对齐 @interface FMLayoutFillSection : FMLayoutDynamicSection @property(nonatomic, copy)FMLayoutItemSizeBlock sizeBlock; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphoneos/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayoutFixedSection.h ================================================ // // FMLayoutFixedSection.h // FMLayoutKit // // Created by 周发明 on 2020/4/1. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import "FMLayoutBaseSection.h" #import "FMLayoutElement.h" NS_ASSUME_NONNULL_BEGIN ///固定cell的大小 单一一种cell样式 支持同样cell是否可以横向滚动 内嵌collectionView 支持纵向插横向 @interface FMLayoutFixedSection : FMLayoutBaseSection @property(nonatomic, assign)CGSize itemSize;///分组cell大小 @property(nonatomic, strong)FMLayoutElement *cellElement;///固定分组 @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphoneos/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayoutFooter.h ================================================ // // FMLayoutFooter.h // FMLayoutKit // // Created by 周发明 on 2020/3/20. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import "FMSupplementary.h" NS_ASSUME_NONNULL_BEGIN @interface FMLayoutFooter : FMSupplementary /// 距离最后Item的距离 纵向-上方 横向-左边 @property(nonatomic, assign)CGFloat topMargin; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphoneos/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayoutHeader.h ================================================ // // FMLayoutHeader.h // FMLayoutKit // // Created by 周发明 on 2020/3/20. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import "FMSupplementary.h" NS_ASSUME_NONNULL_BEGIN /// 悬浮方式 typedef NS_ENUM(NSInteger, FMLayoutHeaderType) { ///跟着滚动 FMLayoutHeaderTypeFixed, ///悬浮在顶部 跟着section动 FMLayoutHeaderTypeSuspension, ///悬浮在顶部 不跟随section动 如果出现多个可能会被覆盖 FMLayoutHeaderTypeSuspensionAlways, ///仅支持在第一个头部 下拉放大效果 FMLayoutHeaderTypeSuspensionBigger }; @interface FMLayoutHeader : FMSupplementary /// 显示方式 是悬浮 还是跟着滚动 默认跟着滚动 @property(nonatomic, assign)FMLayoutHeaderType type; /// 悬浮模式时距离顶部的高度 可以来设置两个悬浮的方式 多个顶部悬浮时 可以通过这个来达到层叠悬浮的模式 @property(nonatomic, assign)CGFloat suspensionTopMargin; /// 距离第一个Item的距离 纵向-下方 横向-右边 @property(nonatomic, assign)CGFloat lastMargin; ///是否黏在顶部 目前仅支持FMLayoutHeaderTypeSuspensionAlways, FMLayoutHeaderTypeSuspensionBigger悬浮模式 不同的type效果不同 FMLayoutHeaderTypeSuspensionAlways是下拉黏在当前位置 上拉黏在顶部 而FMLayoutHeaderTypeSuspensionBiggers是上拉黏在顶部 下拉时放大效果 @property(nonatomic, assign)BOOL isStickTop; /// 缩放模式(SuspensionBigger)下最小值 横向-宽度 纵向-高度 该值请务必小于size 默认是0 @property(nonatomic, assign)CGFloat minSize; /// 缩放模式(SuspensionBigger)下最大值 横向-宽度 纵向-高度 该值请务必大于size 默认是CGFLOAT_MAX @property(nonatomic, assign)CGFloat maxSize; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphoneos/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayoutKit-umbrella.h ================================================ #ifdef __OBJC__ #import #else #ifndef FOUNDATION_EXPORT #if defined(__cplusplus) #define FOUNDATION_EXPORT extern "C" #else #define FOUNDATION_EXPORT extern #endif #endif #endif #import "FMLayoutBackground.h" #import "FMLayoutElement.h" #import "FMLayoutFooter.h" #import "FMLayoutHeader.h" #import "FMSupplementary.h" #import "FMCollectionLayoutAttributes.h" #import "FMKVOArrayObject.h" #import "FMLayout.h" #import "FMLayoutView.h" #import "FMTeslaLayoutView.h" #import "FMTeslaSuspensionHeightChangeDelegate.h" #import "FMLayoutCrossSection.h" #import "FMLayoutAbsoluteSection.h" #import "FMLayoutBaseSection.h" #import "FMLayoutDynamicSection.h" #import "FMLayoutFillSection.h" #import "FMLayoutFixedSection.h" #import "FMLayoutLabelSection.h" FOUNDATION_EXPORT double FMLayoutKitVersionNumber; FOUNDATION_EXPORT const unsigned char FMLayoutKitVersionString[]; ================================================ FILE: Example/FrameworkTmp/Release-iphoneos/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayoutKit.h ================================================ // // FMLayoutKit.h // FMLayoutKit // // Created by 周发明 on 2020/6/9. // #ifndef FMLayoutKit_h #define FMLayoutKit_h #import "FMTeslaLayoutView.h" #import "FMLayoutView.h" #import "FMLayout.h" #import "FMCollectionLayoutAttributes.h" #import "FMTeslaSuspensionHeightChangeDelegate.h" #import "FMLayoutFixedSection.h" #import "FMLayoutDynamicSection.h" #import "FMLayoutLabelSection.h" #import "FMLayoutFillSection.h" #import "FMLayoutAbsoluteSection.h" #import "FMLayoutCrossSection.h" #import "FMLayoutCrossTransformSection.h" #import "FMLayoutCombineSection.h" #import "FMLayoutScaleSection.h" #import "FMSupplementary.h" #import "FMLayoutHeader.h" #import "FMLayoutFooter.h" #import "FMLayoutBackground.h" #endif /* FMLayoutKit_h */ ================================================ FILE: Example/FrameworkTmp/Release-iphoneos/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayoutLabelSection.h ================================================ // // FMLayoutLabelSection.h // FMCollectionLayout // // Created by 周发明 on 2020/4/8. // #import "FMLayoutDynamicSection.h" #import "FMLayoutElement.h" NS_ASSUME_NONNULL_BEGIN ///返回cell大小的block typedef CGFloat(^FMLayoutItemWidthBlock)(id section, NSInteger item); ///当到第多少个的时候超出最大行 可移除数据处理 itemDatas会清理 否则frame为zero typedef CGFloat(^FMLayoutOverItemBlock)(id section, NSInteger item); ///标签式布局 根据文本伸缩布局 宽度不够 换行 适用于历史搜索记录 sku选择等样式 @interface FMLayoutLabelSection : FMLayoutDynamicSection ///最大行数 超出讲不显示 纵向布局时生效 @property(nonatomic, assign)NSInteger maxLine; ///cell固定的高度 @property(nonatomic, assign)CGFloat cellFixedHeight; ///cell最大宽度 不设置的话 就是collection的宽度减去左右分组内边距 @property(nonatomic, assign)CGFloat cellMaxWidth; ///block返回手动计算的宽度 @property(nonatomic, copy)FMLayoutItemWidthBlock widthBlock; ///block返回手动计算的宽度 @property(nonatomic, copy)FMLayoutOverItemBlock overItemBlock; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphoneos/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayoutScaleSection.h ================================================ // // FMLayoutScaleSection.h // FMLayoutKit // // Created by 郑桂华 on 2020/7/20. // #import "FMLayoutDynamicSection.h" NS_ASSUME_NONNULL_BEGIN ///支持两种设置固定大小的方式 一种直接给数组sizeNums 一种给比例字符串scales 后设置的生效 @interface FMLayoutScaleSection : FMLayoutDynamicSection /// 纵向布局 则是宽度比例 横向布局 则是高度比例 例如纵向布局时该值为: 1:2:3 则就是3列 宽度比为剩下的值的比例 仅支持当前样式 可以是小数值 但不能为非数值类型 @property(nonatomic, copy)NSString *scales; ///每一列的固定大小 如:@[@100, @200] 则表示两列 一个固定宽度为100 另外一列为200 共两列 @property(nonatomic, strong)NSArray *sizeNums; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphoneos/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayoutView.h ================================================ // // FMLayoutView.h // FMLayoutKit // // Created by 周发明 on 2020/4/1. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import #import "FMLayout.h" NS_ASSUME_NONNULL_BEGIN @interface FMLayoutView : UICollectionView @property(nonatomic, weak)FMLayout *layout; ///重写了set get 目标指向->layout.sections @property(nonatomic)NSMutableArray *sections; @property(nonatomic, assign)BOOL reloadOlnyChanged; ///是否允许长按拖拽排序 不支持夸分组 分组需要开启canLongPressExchange才可以移动拖拽排序 @property(nonatomic, assign)BOOL enableLongPressDrag; ///长按拖拽开始时配置cell显示的样式 @property(nonatomic, copy)UIView *(^configureSourceView)(UICollectionViewCell *sourceCell); - (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout NS_UNAVAILABLE; - (instancetype)initHorizontal; - (instancetype)initHorizontalWithFrame:(CGRect)frame; /// 循环遍历出更改过的sections 如果有过增删分组 请使用原有的reloadData方法 - (void)reloadChangedSectionsData; ///获取到滚动到indexPath位置偏移量 如果获取到的不准确 请先调用layoutIfNeeded方法 - (CGPoint)contentOffsetScrollToIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UICollectionViewScrollPosition)scrollPosition; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphoneos/FMLayoutKit/FMLayoutKit.framework/Headers/FMSupplementary.h ================================================ // // FMSupplementary.h // FMLayoutKit // // Created by 周发明 on 2020/3/20. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import "FMLayoutElement.h" typedef NS_ENUM(NSInteger, FMLayoutZIndex) { ///最底层 头部 底部 Item的下方 FMLayoutZIndexBg = -9999, ///Item的下方 FMLayoutZIndexBackOfItem = -1, /// 自动悬浮可能会被覆盖 FMLayoutZIndexAuto = 0, /// Item的上方 FMLayoutZIndexFrontOfItem = 1, /// 最最上方 FMLayoutZIndexFrontAlways = 9999 }; NS_ASSUME_NONNULL_BEGIN /// 请使用子类Footer, Header, Background @interface FMSupplementary : FMLayoutElement ///该Element的大小 纵向-高度 横向-宽度 @property(nonatomic, assign)CGFloat size; ///视图层级 最上方还是最下方等 @property(nonatomic, assign)FMLayoutZIndex zIndex; ///内边距 HeaderFooter受sectionInset影响 Background不受sectionInset影响 @property(nonatomic, assign)UIEdgeInsets inset; ///Element类型 Header Footer Background等 @property(nonatomic, copy, readonly)NSString *elementKind; ///是否自适应高度 仅当垂直布局时可用 @property(nonatomic, assign)BOOL autoHeight; @property(nonatomic, copy)void(^configureDataAutoHeight)(UICollectionReusableView *view); + (instancetype)elementSize:(CGFloat)size viewClass:(Class)vClass; + (instancetype)elementSize:(CGFloat)size viewClass:(Class)vClass isNib:(BOOL)isNib; + (instancetype)elementSize:(CGFloat)size viewClass:(Class)vClass isNib:(BOOL)isNib reuseIdentifier:(NSString *)reuseIdentifier; - (UICollectionReusableView *)dequeueReusableViewWithCollection:(UICollectionView *)collectionView indexPath:(NSIndexPath *)indexPath; - (void)updateHeightWithCollection:(UICollectionView *)collectionView indexPath:(NSIndexPath *)indexPath maxWidth:(CGFloat)maxWidth; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphoneos/FMLayoutKit/FMLayoutKit.framework/Headers/FMTeslaLayoutView.h ================================================ // // FMTeslaLayoutView.h // FMCollectionLayout_Example // // Created by 周发明 on 2020/4/8. // Copyright © 2020 周发明. All rights reserved. // #import NS_ASSUME_NONNULL_BEGIN @class FMLayoutView, FMTeslaLayoutView, FMLayoutBaseSection; @protocol FMTeslaLayoutViewDelegate @optional ///滚动结束事件 - (void)tesla:(FMTeslaLayoutView *)tesla didScrollEnd:(NSInteger)index currentScrollView:(UIScrollView *)scrollView; ///滚动事件 - (void)tesla:(FMTeslaLayoutView *)tesla scrollViewDidScroll:(UIScrollView *)scrollView; /// 当前上下滚动的事件 - (void)tesla:(FMTeslaLayoutView *)tesla currentScrollViewScrollDidScroll:(UIScrollView *)currentScrollView contentOffset:(CGPoint)contentOffset; /// 配置FMCollectionLayoutView ///2 - (void)tesla:(FMTeslaLayoutView *)tesla currentShowScrollView:(UIScrollView *)scrollView index:(NSInteger)index; ///0 即将根据Index创建FMCollectionLayoutView - (void)tesla:(FMTeslaLayoutView *)tesla willCreateScrollViewWithIndex:(NSInteger)index; ///0.5 根据Index自己创建FMCollectionLayoutView shareHeight为共享头部的高度 请将shareHeight顶部空出来并且请保持不使用contentInset 如果返回nil会自动创建FMLayoutView - (UIScrollView *)tesla:(FMTeslaLayoutView *)tesla customCreateWithIndex:(NSInteger)index shareHeight:(CGFloat)shareHeight; ///1 根据Index创建完毕UIScrollView - (void)tesla:(FMTeslaLayoutView *)tesla didCreatedScrollViewWithIndex:(NSInteger)index scrollView:(UIScrollView *)scrollView; /// 悬停标签控制view的尺寸最小高度 可以留着做效果 - (CGFloat)shareSuspensionMinHeightWithTesla:(FMTeslaLayoutView *)tesla; @end @protocol FMTeslaLayoutViewDataSource @required - (NSInteger)numberOfScreenInTesla:(FMTeslaLayoutView *)tesla; @optional - (NSArray *)shareSectionsInTesla:(FMTeslaLayoutView *)tesla; @end @class FMLayoutBaseSection; @interface FMTeslaLayoutView : UIView @property(nonatomic, weak)id delegate; @property(nonatomic, weak)id dataSource; @property(nonatomic, assign)BOOL horizontalCanScroll; @property(nonatomic, assign)BOOL allShareStickTop; @property(nonatomic, assign)NSInteger selectIndex; @property(nonatomic, assign)BOOL isLoadSubView; @property(nonatomic, assign)CGFloat shareHeight; @property(nonatomic, strong, readonly)FMLayoutView *shareLayoutView; - (void)reLoadSubViews; - (void)reloadData; - (void)reloadDataWithIndex:(NSInteger)index; - (void)scrollToIndex:(NSInteger)index animated:(BOOL)animated; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphoneos/FMLayoutKit/FMLayoutKit.framework/Headers/FMTeslaSuspensionHeightChangeDelegate.h ================================================ // // FMTeslaSuspensionHeightChangeDelegate.h // FMCollectionLayout // // Created by 周发明 on 2020/5/13. // #import #import NS_ASSUME_NONNULL_BEGIN @protocol FMTeslaSuspensionHeightChangeDelegate - (void)teslaSuspensionHeaderShouldShowHeight:(CGFloat)showHeight; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphoneos/FMLayoutKit/FMLayoutKit.framework/Modules/module.modulemap ================================================ framework module FMLayoutKit { umbrella header "FMLayoutKit-umbrella.h" export * module * { export * } } ================================================ FILE: Example/FrameworkTmp/Release-iphoneos/FMLayoutKit/FMLayoutKit.framework.dSYM/Contents/Info.plist ================================================ CFBundleDevelopmentRegion English CFBundleIdentifier com.apple.xcode.dsym.org.cocoapods.FMLayoutKit CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType dSYM CFBundleSignature ???? CFBundleShortVersionString 1.0.0 CFBundleVersion 1 ================================================ FILE: Example/FrameworkTmp/Release-iphonesimulator/FMLayoutKit/FMLayoutKit.framework/Headers/FMCollectionLayoutAttributes.h ================================================ // // FMCollectionLayoutAttributes.h // FMLayoutKit // // Created by 周发明 on 2020/3/25. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import #import "FMLayoutBaseSection.h" NS_ASSUME_NONNULL_BEGIN @interface FMCollectionLayoutAttributes : UICollectionViewLayoutAttributes @property(nonatomic, assign)FMLayoutDirection direction; + (instancetype)headerAttributesWithSection:(FMLayoutBaseSection *)section; - (instancetype)updateHeaderAttributesWithSection:(FMLayoutBaseSection *)section; + (instancetype)suspensionShowHeaderAttributes:(FMLayoutBaseSection *)section; + (instancetype)footerAttributesWithSection:(FMLayoutBaseSection *)section; - (instancetype)updateFooterAttributesWithSection:(FMLayoutBaseSection *)section; + (instancetype)bgAttributesWithSection:(FMLayoutBaseSection *)section; - (instancetype)updateBgAttributesWithSection:(FMLayoutBaseSection *)section; - (void)_onlyUpdateOffsetWith:(FMLayoutBaseSection *)section; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphonesimulator/FMLayoutKit/FMLayoutKit.framework/Headers/FMCollectionViewDelegateDataSourceProvider.h ================================================ // // FMCollectionViewDelegateDataSourceProvider.h // FMLayoutKit // // Created by 郑桂华 on 2021/3/27. // #import #import NS_ASSUME_NONNULL_BEGIN @class FMLayoutBaseSection; @interface FMCollectionViewDelegateDataSourceProvider : NSObject ///重写了set get 目标指向->layout.sections @property(nonatomic, strong)NSMutableArray *sections; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphonesimulator/FMLayoutKit/FMLayoutKit.framework/Headers/FMKVOArrayObject.h ================================================ // // FMKVOArrayObject.h // FMCollectionLayout // // Created by 周发明 on 2020/6/5. // #import NS_ASSUME_NONNULL_BEGIN @interface FMKVOArrayObject : NSObject @property (strong,nonatomic)NSMutableArray *targetArray; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphonesimulator/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayout.h ================================================ // // FMLayout.h // FMLayoutKit // // Created by 周发明 on 2020/6/16. // #import #import "FMLayoutBaseSection.h" #import "FMLayoutHeader.h" #import "FMLayoutFooter.h" #import "FMLayoutBackground.h" #import "FMCollectionLayoutAttributes.h" NS_ASSUME_NONNULL_BEGIN @interface FMLayout : UICollectionViewLayout @property(nonatomic, assign)FMLayoutDirection direction; @property(nonatomic, strong)NSMutableArray *sections; ///最后固定边距 跟section的inset无关 contentSize会自动加上去 @property(nonatomic, assign)CGFloat fixedLastMargin; ///是否只计算改变的布局 NO为每一次 都是重新计算所有布局 @property(nonatomic, assign)BOOL reLayoutOlnyChanged; ///最小可滑动的大小 横向-高度 纵向-宽度 @property(nonatomic, assign)CGFloat minContentSize; ///第一个Section的偏移量 @property(nonatomic, assign)CGFloat firstSectionOffset; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphonesimulator/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayoutAbsoluteSection.h ================================================ // // FMLayoutAbsoluteSection.h // FMCollectionLayout // // Created by 周发明 on 2020/6/9. // #import "FMLayoutDynamicSection.h" NS_ASSUME_NONNULL_BEGIN typedef CGRect(^FMLayoutBaseSectionItemFrameBlock)(id section, NSInteger item); ///支持纵向插横向 @interface FMLayoutAbsoluteSection : FMLayoutDynamicSection @property(nonatomic, copy)FMLayoutBaseSectionItemFrameBlock frameBlock; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphonesimulator/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayoutBackground.h ================================================ // // FMLayoutBackground.h // FMLayoutKit // // Created by 周发明 on 2020/3/27. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import "FMSupplementary.h" NS_ASSUME_NONNULL_BEGIN static NSString *const UICollectionElementKindSectionBackground = @"UICollectionElementKindSectionBackground"; @interface FMLayoutBackground : FMSupplementary + (instancetype)bgWithViewClass:(Class)viewClass; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphonesimulator/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayoutBaseSection.h ================================================ // // FMLayoutBaseSection.h // FMLayoutKit // // Created by 周发明 on 2020/3/20. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import #import #import "FMLayoutDebugLog.h" typedef NS_ENUM(NSUInteger, FMLayoutHandleType) { /// 重新计算 重新布局该分组 FMLayoutHandleTypeReLayout, /// 只是分组偏移高度改变 FMLayoutHandleTypeOlnyChangeOffset, /// 追加布局 FMLayoutHandleTypeAppend }; ///布局方向 typedef NS_ENUM(NSUInteger, FMLayoutDirection) { ///垂直布局 FMLayoutDirectionVertical, ///水平布局 FMLayoutDirectionHorizontal }; ///Item布局方向 typedef NS_ENUM(NSUInteger, FMLayoutItemDirection) { ///水平左边开始 垂直上面开始 FMLayoutItemDirectionLeftTop, ///水平右边开始 垂直下面开始 FMLayoutItemDirectionRightBottom }; ///长按移动的方式 typedef NS_ENUM(NSUInteger, FMLayoutLongMoveType) { ///方格布局时 长按哪里 该cell的中心点就会跟着移动 FMLayoutLongMoveItem, ///列表布局时 上下移动 X不动 FMLayoutLongMoveTable, }; NS_ASSUME_NONNULL_BEGIN @class FMLayoutHeader, FMLayoutFooter, FMLayoutBackground, FMCollectionLayoutAttributes; @interface FMLayoutBaseSection : NSObject ///仅当布局生效之后才会有值 @property(nonatomic, weak)UICollectionView *collectionView; ///仅当布局生效之后才会有值 @property(nonatomic, strong)NSIndexPath *indexPath; ///是否需要重新计算 设置为NO 布局会重新计算 @property(nonatomic, assign)FMLayoutDirection direction; @property(nonatomic, assign)BOOL hasHandle; @property(nonatomic, assign)NSInteger handleItemStart;///重新计算哪一个开始 @property(nonatomic, assign)FMLayoutHandleType handleType; @property(nonatomic, assign)CGFloat changeOffset; @property(nonatomic, strong)FMCollectionLayoutAttributes * __nullable bgAttribute; @property(nonatomic, strong)FMCollectionLayoutAttributes * __nullable headerAttribute; @property(nonatomic, strong)FMCollectionLayoutAttributes * __nullable footerAttribute; @property(nonatomic, strong)NSArray *itemsAttribute; /// 分组偏移高度 @property(nonatomic, assign)CGFloat sectionOffset; /// 分组大小 纵向-高度 横向-宽度 @property(nonatomic, assign)CGFloat sectionSize; /// 分组内边距 @property(nonatomic, assign)UIEdgeInsets sectionInset; ///分组头部 @property(nonatomic, strong)FMLayoutHeader * __nullable header; ///分组底部 @property(nonatomic, strong)FMLayoutFooter * __nullable footer; ///分组背景 @property(nonatomic, strong)FMLayoutBackground * __nullable background; ///cell行间距 @property(nonatomic, assign)CGFloat lineSpace; ///cell间距 @property(nonatomic, assign)CGFloat itemSpace; ///cell列数 纵向-列数 横向-行数 @property(nonatomic, assign)NSInteger column; ///每一列的高度缓存 @property(nonatomic, strong)NSMutableDictionary *columnSizes; ///每一个分组的item个数 默认返回itemDatas.count @property(nonatomic, assign)NSInteger itemCount; ///cell数据数组 @property(nonatomic, strong)NSMutableArray *itemDatas; ///是否可以长按移动排序该分组 默认No 需配合FMLayoutView的enableLongPressDrag使用 @property(nonatomic, assign)BOOL canLongPressExchange; ///长按移动的方式 @property(nonatomic, assign)FMLayoutLongMoveType moveType; ///某一个item是否可以移动替换 @property(nonatomic, copy)BOOL(^canLongPressExchangeItem)(id section, NSInteger item); /// 显示隐藏 @property(nonatomic, assign, getter=isHidden)BOOL hidden; ///第一个Item的Y值 横向纵向有区别 @property(nonatomic, assign, readonly)CGFloat firstItemStartY; ///第一个Item的X值 横向纵向有区别 @property(nonatomic, assign, readonly)CGFloat firstItemStartX; ///配置一下Attributes @property(nonatomic, copy)void(^configureCellLayoutAttributes)(id section, UICollectionViewLayoutAttributes *attributes, NSInteger item); ///配置头部的block @property(nonatomic, copy)void(^configureHeaderData)(FMLayoutBaseSection *section, UICollectionReusableView *header); ///配置底部的block @property(nonatomic, copy)void(^configureFooterData)(FMLayoutBaseSection *section, UICollectionReusableView *footer); ///配置背景的block @property(nonatomic, copy)void(^configureBg)(FMLayoutBaseSection *section, UICollectionReusableView *bg); ///配置Cell的block @property(nonatomic, copy)void(^configureCellData)(FMLayoutBaseSection *section, UICollectionViewCell *cell, NSInteger item); ///cell点击事件 @property(nonatomic, copy)void(^clickCellBlock)(FMLayoutBaseSection *section, NSInteger item); + (instancetype)sectionWithSectionInset:(UIEdgeInsets)inset itemSpace:(CGFloat)itemSpace lineSpace:(CGFloat)lineSpace column:(NSInteger)column; ///标记某一个改变 即将刷新该分组的大小 主要用于动态分组 - (void)markChangeAt:(NSInteger)index; - (void)handleLayout; - (BOOL)intersectsRect:(CGRect)rect; - (void)prepareHeader; - (void)prepareFooter; - (void)prepareItems; - (void)prepareBackground; - (NSArray *)showLayoutAttributesInRect:(CGRect)rect; ///即将显示的头部布局 - (UICollectionViewLayoutAttributes *)showHeaderLayout; ///根据index计算出该布局对象 - (FMCollectionLayoutAttributes *)getItemAttributesWithIndex:(NSInteger)index; - (BOOL)prepareLayoutItemsIsOlnyChangeOffset; ///获取最小高度的列 - (NSInteger)getMinHeightColumn; - (CGFloat)getColumnMaxHeight; ///重置所有列的高度缓存 - (void)resetcolumnSizes; ///交叉布局时单一sention的大小 - (CGFloat)crossSingleSectionSize; - (void)exchangeObjectAtIndex:(NSInteger)index toIndex:(NSInteger)toIndex; - (UICollectionViewCell *)dequeueReusableCellForIndexPath:(NSIndexPath *)indexPath; - (UICollectionViewCell *)dequeueReusableCellForIndexPath:(NSIndexPath *)indexPath collectionView:(UICollectionView *)collectionView; - (void)registerCells; - (void)registerCellsWithCollectionView:(UICollectionView *)collectionView; - (void)reload; - (void)reloadItem:(NSInteger)item; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphonesimulator/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayoutCombineSection.h ================================================ // // FMLayoutCombineSection.h // FMLayoutKit // // Created by 郑桂华 on 2020/7/12. // #import "FMLayoutBaseSection.h" NS_ASSUME_NONNULL_BEGIN ///可以将不同Cell, 不同的布局方式, 放到同一个分组去合并,只合并cell, 如果子分组有头部和底部讲被忽略,合并分组的头部与底部不影响配置, cell的点击事件已经在init方法中配置block分发到子分组上 合并分组不支持拖拽排序 想要支持 可以继承自该类重写canLongPressExchange的get方法 并实现- (void)exchangeObjectAtIndex:(NSInteger)index toIndex:(NSInteger)toIndex; @interface FMLayoutCombineSection : FMLayoutBaseSection @property(nonatomic, readonly)NSArray *subSections; + (instancetype)combineSections:(NSArray *)sections; - (void)appendSection:(FMLayoutBaseSection *)section; - (void)insetSection:(FMLayoutBaseSection *)section atIndex:(NSInteger)index; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphonesimulator/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayoutCrossSection.h ================================================ // // FMLayoutCrossSection.h // FMLayoutKit // // Created by 周发明 on 2020/6/16. // #import "FMLayoutBaseSection.h" NS_ASSUME_NONNULL_BEGIN @interface FMLayoutCrossSection : FMLayoutBaseSection @property(nonatomic, assign, readonly)FMLayoutDirection crossDirection; /// 所有section计算获取最大的高度 @property(nonatomic, assign)BOOL autoMaxSize; /// 所有section计算获取最大的高度 @property(nonatomic, assign)CGFloat size; @property(nonatomic, assign)BOOL canReuseCell; @property(nonatomic, assign, readonly)CGFloat maxContentWidth; @property(nonatomic, strong)NSMutableArray *sections; @property(nonatomic, copy)void(^scrollDidScroll)(UICollectionView *collectionView, FMLayoutCrossSection *hSection); @property(nonatomic, copy)void(^configureCollectionView)(UICollectionView *collectionView, FMLayoutCrossSection *hSection); + (instancetype)sectionAutoWithSection:(FMLayoutBaseSection *)section; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphonesimulator/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayoutCrossTransformSection.h ================================================ // // FMLayoutCrossTransformSection.h // FMLayoutKit // // Created by 郑桂华 on 2020/7/15. // #import "FMLayoutCrossSection.h" NS_ASSUME_NONNULL_BEGIN typedef NS_ENUM(NSUInteger, FMLayoutCrossTransformType) { ///什么都不做 FMLayoutCrossTransformNone, ///缩小0.9 + 0.1*进度 FMLayoutCrossTransformScale, ///简拼App首页样式 M_PI_4 * 0.5 * 进度 FMLayoutCrossTransformCrooked, ///折叠效果 FMLayoutCrossTransformFold, }; ///Cell是需要做处理的cell, progress是指cell中心点到屏幕边缘移动的进度 -1 ~ 1 0为在最中间 -1在左边 1在右边 typedef void(^FMLayoutCrossTransformBlock)(UICollectionViewCell *cell, CGFloat progress); ///当前仅针对横向做适配 更多的动画 @interface FMLayoutCrossTransformSection : FMLayoutCrossSection ///形变类型 @property(nonatomic, assign)FMLayoutCrossTransformType transformType; ///如果有该Block 则优先执行此block @property(nonatomic, copy)FMLayoutCrossTransformBlock __nullable transformBlock; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphonesimulator/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayoutDebugLog.h ================================================ // // FMLayoutDebugLog.h // FMLayoutKit // // Created by 周发明 on 2020/6/17. // #import NS_ASSUME_NONNULL_BEGIN extern void FMLayoutLog(NSString *format); extern void FMLayoutOpenLog(void); extern void FMLayoutCloseLog(void); extern NSInteger FMLayoutRandomValue(NSInteger start, NSInteger end); NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphonesimulator/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayoutDynamicSection.h ================================================ // // FMLayoutDynamicSection.h // FMLayoutKit // // Created by 周发明 on 2020/4/1. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import "FMLayoutBaseSection.h" #import "FMLayoutElement.h" NS_ASSUME_NONNULL_BEGIN ///返回cell大小的block 横向-返回宽度 纵向-返回高度 typedef CGFloat(^FMLayoutItemOtherBlock)(id section, NSInteger item); typedef CGFloat(^FMLayoutAutoHeightLaterBlock)(id section, NSInteger item, CGFloat autoHeight); ///动态 可以注册多种cell 宽度固定 高度可以自适应 但需要用block填充数据 需要设置deqCellReturnReuseId该block值以获取cell 高度亦可以通过手动计算heightBlock返回 手动计算优先级要高 @interface FMLayoutDynamicSection : FMLayoutBaseSection /// yes时 布局耗时比较长 是否自动计算高度 需设置configurationCell方法填充数据 仅支持纵向布局时使用 @property(nonatomic, assign)BOOL autoHeightFixedWidth; @property(nonatomic, copy)FMLayoutAutoHeightLaterBlock autoHeightLaterHander; ///cell固定一个方向的大小 纵向-宽度 横向-高度 @property(nonatomic, assign)CGFloat cellFixedSize; ///需要注册的cell元素 @property(nonatomic, strong)NSArray *cellElements; ///固定单一分组 当固定单一分组时 可以不用手动配置deqCellReturnReuseId @property(nonatomic, strong)FMLayoutElement *cellElement; ///获取cell的复用FMLayoutElement @property(nonatomic, copy)FMLayoutElement *(^deqCellReturnElement)(FMLayoutDynamicSection *section, NSInteger item); ///填充数据 仅当autoHeightFixedWidth为Yes时有用 @property(nonatomic, copy)void(^configurationCell)(FMLayoutDynamicSection *section, UICollectionViewCell *cell, NSInteger item); ///block返回手动计算的高度 优先级比自动的高 @property(nonatomic, copy)FMLayoutItemOtherBlock otherBlock; - (CGFloat)autoHeightVerticalWithWidth:(CGFloat)fixedWidth index:(NSInteger)index; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphonesimulator/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayoutElement.h ================================================ // // FMLayoutElement.h // FMLayoutKit // // Created by 周发明 on 2020/4/1. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import #import NS_ASSUME_NONNULL_BEGIN @interface FMLayoutElement : NSObject @property(nonatomic, copy)NSString *reuseIdentifier; @property(nonatomic, assign)BOOL isNib; @property(nonatomic, weak)Class viewClass;///视图的类 + (instancetype)elementWithViewClass:(Class)vCalss; + (instancetype)elementWithViewClass:(Class)vCalss isNib:(BOOL)isNib; + (instancetype)elementWithViewClass:(Class)vCalss isNib:(BOOL)isNib reuseIdentifier:(NSString *)reuseIdentifier; - (void)registerElementWithCollection:(UICollectionView *)collectionView; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphonesimulator/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayoutFillSection.h ================================================ // // FMLayoutFillSection.h // FMCollectionLayout // // Created by 周发明 on 2020/4/11. // #import "FMLayoutDynamicSection.h" NS_ASSUME_NONNULL_BEGIN ///返回cell大小的block typedef CGSize(^FMLayoutItemSizeBlock)(id section, NSInteger item); ///支持纵向插横向 只可以上对齐以及左对齐 @interface FMLayoutFillSection : FMLayoutDynamicSection @property(nonatomic, copy)FMLayoutItemSizeBlock sizeBlock; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphonesimulator/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayoutFixedSection.h ================================================ // // FMLayoutFixedSection.h // FMLayoutKit // // Created by 周发明 on 2020/4/1. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import "FMLayoutBaseSection.h" #import "FMLayoutElement.h" NS_ASSUME_NONNULL_BEGIN ///固定cell的大小 单一一种cell样式 支持同样cell是否可以横向滚动 内嵌collectionView 支持纵向插横向 @interface FMLayoutFixedSection : FMLayoutBaseSection @property(nonatomic, assign)CGSize itemSize;///分组cell大小 @property(nonatomic, strong)FMLayoutElement *cellElement;///固定分组 @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphonesimulator/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayoutFooter.h ================================================ // // FMLayoutFooter.h // FMLayoutKit // // Created by 周发明 on 2020/3/20. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import "FMSupplementary.h" NS_ASSUME_NONNULL_BEGIN @interface FMLayoutFooter : FMSupplementary /// 距离最后Item的距离 纵向-上方 横向-左边 @property(nonatomic, assign)CGFloat topMargin; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphonesimulator/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayoutHeader.h ================================================ // // FMLayoutHeader.h // FMLayoutKit // // Created by 周发明 on 2020/3/20. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import "FMSupplementary.h" NS_ASSUME_NONNULL_BEGIN /// 悬浮方式 typedef NS_ENUM(NSInteger, FMLayoutHeaderType) { ///跟着滚动 FMLayoutHeaderTypeFixed, ///悬浮在顶部 跟着section动 FMLayoutHeaderTypeSuspension, ///悬浮在顶部 不跟随section动 如果出现多个可能会被覆盖 FMLayoutHeaderTypeSuspensionAlways, ///仅支持在第一个头部 下拉放大效果 FMLayoutHeaderTypeSuspensionBigger }; @interface FMLayoutHeader : FMSupplementary /// 显示方式 是悬浮 还是跟着滚动 默认跟着滚动 @property(nonatomic, assign)FMLayoutHeaderType type; /// 悬浮模式时距离顶部的高度 可以来设置两个悬浮的方式 多个顶部悬浮时 可以通过这个来达到层叠悬浮的模式 @property(nonatomic, assign)CGFloat suspensionTopMargin; /// 距离第一个Item的距离 纵向-下方 横向-右边 @property(nonatomic, assign)CGFloat lastMargin; ///是否黏在顶部 目前仅支持FMLayoutHeaderTypeSuspensionAlways, FMLayoutHeaderTypeSuspensionBigger悬浮模式 不同的type效果不同 FMLayoutHeaderTypeSuspensionAlways是下拉黏在当前位置 上拉黏在顶部 而FMLayoutHeaderTypeSuspensionBiggers是上拉黏在顶部 下拉时放大效果 @property(nonatomic, assign)BOOL isStickTop; /// 缩放模式(SuspensionBigger)下最小值 横向-宽度 纵向-高度 该值请务必小于size 默认是0 @property(nonatomic, assign)CGFloat minSize; /// 缩放模式(SuspensionBigger)下最大值 横向-宽度 纵向-高度 该值请务必大于size 默认是CGFLOAT_MAX @property(nonatomic, assign)CGFloat maxSize; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphonesimulator/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayoutKit-umbrella.h ================================================ #ifdef __OBJC__ #import #else #ifndef FOUNDATION_EXPORT #if defined(__cplusplus) #define FOUNDATION_EXPORT extern "C" #else #define FOUNDATION_EXPORT extern #endif #endif #endif #import "FMLayoutBackground.h" #import "FMLayoutElement.h" #import "FMLayoutFooter.h" #import "FMLayoutHeader.h" #import "FMSupplementary.h" #import "FMCollectionLayoutAttributes.h" #import "FMKVOArrayObject.h" #import "FMLayout.h" #import "FMLayoutView.h" #import "FMTeslaLayoutView.h" #import "FMTeslaSuspensionHeightChangeDelegate.h" #import "FMLayoutCrossSection.h" #import "FMLayoutAbsoluteSection.h" #import "FMLayoutBaseSection.h" #import "FMLayoutDynamicSection.h" #import "FMLayoutFillSection.h" #import "FMLayoutFixedSection.h" #import "FMLayoutLabelSection.h" FOUNDATION_EXPORT double FMLayoutKitVersionNumber; FOUNDATION_EXPORT const unsigned char FMLayoutKitVersionString[]; ================================================ FILE: Example/FrameworkTmp/Release-iphonesimulator/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayoutKit.h ================================================ // // FMLayoutKit.h // FMLayoutKit // // Created by 周发明 on 2020/6/9. // #ifndef FMLayoutKit_h #define FMLayoutKit_h #import "FMTeslaLayoutView.h" #import "FMLayoutView.h" #import "FMLayout.h" #import "FMCollectionLayoutAttributes.h" #import "FMTeslaSuspensionHeightChangeDelegate.h" #import "FMLayoutFixedSection.h" #import "FMLayoutDynamicSection.h" #import "FMLayoutLabelSection.h" #import "FMLayoutFillSection.h" #import "FMLayoutAbsoluteSection.h" #import "FMLayoutCrossSection.h" #import "FMLayoutCrossTransformSection.h" #import "FMLayoutCombineSection.h" #import "FMLayoutScaleSection.h" #import "FMSupplementary.h" #import "FMLayoutHeader.h" #import "FMLayoutFooter.h" #import "FMLayoutBackground.h" #endif /* FMLayoutKit_h */ ================================================ FILE: Example/FrameworkTmp/Release-iphonesimulator/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayoutLabelSection.h ================================================ // // FMLayoutLabelSection.h // FMCollectionLayout // // Created by 周发明 on 2020/4/8. // #import "FMLayoutDynamicSection.h" #import "FMLayoutElement.h" NS_ASSUME_NONNULL_BEGIN ///返回cell大小的block typedef CGFloat(^FMLayoutItemWidthBlock)(id section, NSInteger item); ///当到第多少个的时候超出最大行 可移除数据处理 itemDatas会清理 否则frame为zero typedef CGFloat(^FMLayoutOverItemBlock)(id section, NSInteger item); ///标签式布局 根据文本伸缩布局 宽度不够 换行 适用于历史搜索记录 sku选择等样式 @interface FMLayoutLabelSection : FMLayoutDynamicSection ///最大行数 超出讲不显示 纵向布局时生效 @property(nonatomic, assign)NSInteger maxLine; ///cell固定的高度 @property(nonatomic, assign)CGFloat cellFixedHeight; ///cell最大宽度 不设置的话 就是collection的宽度减去左右分组内边距 @property(nonatomic, assign)CGFloat cellMaxWidth; ///block返回手动计算的宽度 @property(nonatomic, copy)FMLayoutItemWidthBlock widthBlock; ///block返回手动计算的宽度 @property(nonatomic, copy)FMLayoutOverItemBlock overItemBlock; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphonesimulator/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayoutScaleSection.h ================================================ // // FMLayoutScaleSection.h // FMLayoutKit // // Created by 郑桂华 on 2020/7/20. // #import "FMLayoutDynamicSection.h" NS_ASSUME_NONNULL_BEGIN ///支持两种设置固定大小的方式 一种直接给数组sizeNums 一种给比例字符串scales 后设置的生效 @interface FMLayoutScaleSection : FMLayoutDynamicSection /// 纵向布局 则是宽度比例 横向布局 则是高度比例 例如纵向布局时该值为: 1:2:3 则就是3列 宽度比为剩下的值的比例 仅支持当前样式 可以是小数值 但不能为非数值类型 @property(nonatomic, copy)NSString *scales; ///每一列的固定大小 如:@[@100, @200] 则表示两列 一个固定宽度为100 另外一列为200 共两列 @property(nonatomic, strong)NSArray *sizeNums; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphonesimulator/FMLayoutKit/FMLayoutKit.framework/Headers/FMLayoutView.h ================================================ // // FMLayoutView.h // FMLayoutKit // // Created by 周发明 on 2020/4/1. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import #import "FMLayout.h" NS_ASSUME_NONNULL_BEGIN @interface FMLayoutView : UICollectionView @property(nonatomic, weak)FMLayout *layout; ///重写了set get 目标指向->layout.sections @property(nonatomic)NSMutableArray *sections; @property(nonatomic, assign)BOOL reloadOlnyChanged; ///是否允许长按拖拽排序 不支持夸分组 分组需要开启canLongPressExchange才可以移动拖拽排序 @property(nonatomic, assign)BOOL enableLongPressDrag; ///长按拖拽开始时配置cell显示的样式 @property(nonatomic, copy)UIView *(^configureSourceView)(UICollectionViewCell *sourceCell); - (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout NS_UNAVAILABLE; - (instancetype)initHorizontal; - (instancetype)initHorizontalWithFrame:(CGRect)frame; /// 循环遍历出更改过的sections 如果有过增删分组 请使用原有的reloadData方法 - (void)reloadChangedSectionsData; ///获取到滚动到indexPath位置偏移量 如果获取到的不准确 请先调用layoutIfNeeded方法 - (CGPoint)contentOffsetScrollToIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UICollectionViewScrollPosition)scrollPosition; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphonesimulator/FMLayoutKit/FMLayoutKit.framework/Headers/FMSupplementary.h ================================================ // // FMSupplementary.h // FMLayoutKit // // Created by 周发明 on 2020/3/20. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import "FMLayoutElement.h" typedef NS_ENUM(NSInteger, FMLayoutZIndex) { ///最底层 头部 底部 Item的下方 FMLayoutZIndexBg = -9999, ///Item的下方 FMLayoutZIndexBackOfItem = -1, /// 自动悬浮可能会被覆盖 FMLayoutZIndexAuto = 0, /// Item的上方 FMLayoutZIndexFrontOfItem = 1, /// 最最上方 FMLayoutZIndexFrontAlways = 9999 }; NS_ASSUME_NONNULL_BEGIN /// 请使用子类Footer, Header, Background @interface FMSupplementary : FMLayoutElement ///该Element的大小 纵向-高度 横向-宽度 @property(nonatomic, assign)CGFloat size; ///视图层级 最上方还是最下方等 @property(nonatomic, assign)FMLayoutZIndex zIndex; ///内边距 HeaderFooter受sectionInset影响 Background不受sectionInset影响 @property(nonatomic, assign)UIEdgeInsets inset; ///Element类型 Header Footer Background等 @property(nonatomic, copy, readonly)NSString *elementKind; ///是否自适应高度 仅当垂直布局时可用 @property(nonatomic, assign)BOOL autoHeight; @property(nonatomic, copy)void(^configureDataAutoHeight)(UICollectionReusableView *view); + (instancetype)elementSize:(CGFloat)size viewClass:(Class)vClass; + (instancetype)elementSize:(CGFloat)size viewClass:(Class)vClass isNib:(BOOL)isNib; + (instancetype)elementSize:(CGFloat)size viewClass:(Class)vClass isNib:(BOOL)isNib reuseIdentifier:(NSString *)reuseIdentifier; - (UICollectionReusableView *)dequeueReusableViewWithCollection:(UICollectionView *)collectionView indexPath:(NSIndexPath *)indexPath; - (void)updateHeightWithCollection:(UICollectionView *)collectionView indexPath:(NSIndexPath *)indexPath maxWidth:(CGFloat)maxWidth; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphonesimulator/FMLayoutKit/FMLayoutKit.framework/Headers/FMTeslaLayoutView.h ================================================ // // FMTeslaLayoutView.h // FMCollectionLayout_Example // // Created by 周发明 on 2020/4/8. // Copyright © 2020 周发明. All rights reserved. // #import NS_ASSUME_NONNULL_BEGIN @class FMLayoutView, FMTeslaLayoutView, FMLayoutBaseSection; @protocol FMTeslaLayoutViewDelegate @optional ///滚动结束事件 - (void)tesla:(FMTeslaLayoutView *)tesla didScrollEnd:(NSInteger)index currentScrollView:(UIScrollView *)scrollView; ///滚动事件 - (void)tesla:(FMTeslaLayoutView *)tesla scrollViewDidScroll:(UIScrollView *)scrollView; /// 当前上下滚动的事件 - (void)tesla:(FMTeslaLayoutView *)tesla currentScrollViewScrollDidScroll:(UIScrollView *)currentScrollView contentOffset:(CGPoint)contentOffset; /// 配置FMCollectionLayoutView ///2 - (void)tesla:(FMTeslaLayoutView *)tesla currentShowScrollView:(UIScrollView *)scrollView index:(NSInteger)index; ///0 即将根据Index创建FMCollectionLayoutView - (void)tesla:(FMTeslaLayoutView *)tesla willCreateScrollViewWithIndex:(NSInteger)index; ///0.5 根据Index自己创建FMCollectionLayoutView shareHeight为共享头部的高度 请将shareHeight顶部空出来并且请保持不使用contentInset 如果返回nil会自动创建FMLayoutView - (UIScrollView *)tesla:(FMTeslaLayoutView *)tesla customCreateWithIndex:(NSInteger)index shareHeight:(CGFloat)shareHeight; ///1 根据Index创建完毕UIScrollView - (void)tesla:(FMTeslaLayoutView *)tesla didCreatedScrollViewWithIndex:(NSInteger)index scrollView:(UIScrollView *)scrollView; /// 悬停标签控制view的尺寸最小高度 可以留着做效果 - (CGFloat)shareSuspensionMinHeightWithTesla:(FMTeslaLayoutView *)tesla; @end @protocol FMTeslaLayoutViewDataSource @required - (NSInteger)numberOfScreenInTesla:(FMTeslaLayoutView *)tesla; @optional - (NSArray *)shareSectionsInTesla:(FMTeslaLayoutView *)tesla; @end @class FMLayoutBaseSection; @interface FMTeslaLayoutView : UIView @property(nonatomic, weak)id delegate; @property(nonatomic, weak)id dataSource; @property(nonatomic, assign)BOOL horizontalCanScroll; @property(nonatomic, assign)BOOL allShareStickTop; @property(nonatomic, assign)NSInteger selectIndex; @property(nonatomic, assign)BOOL isLoadSubView; @property(nonatomic, assign)CGFloat shareHeight; @property(nonatomic, strong, readonly)FMLayoutView *shareLayoutView; - (void)reLoadSubViews; - (void)reloadData; - (void)reloadDataWithIndex:(NSInteger)index; - (void)scrollToIndex:(NSInteger)index animated:(BOOL)animated; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphonesimulator/FMLayoutKit/FMLayoutKit.framework/Headers/FMTeslaSuspensionHeightChangeDelegate.h ================================================ // // FMTeslaSuspensionHeightChangeDelegate.h // FMCollectionLayout // // Created by 周发明 on 2020/5/13. // #import #import NS_ASSUME_NONNULL_BEGIN @protocol FMTeslaSuspensionHeightChangeDelegate - (void)teslaSuspensionHeaderShouldShowHeight:(CGFloat)showHeight; @end NS_ASSUME_NONNULL_END ================================================ FILE: Example/FrameworkTmp/Release-iphonesimulator/FMLayoutKit/FMLayoutKit.framework/Modules/module.modulemap ================================================ framework module FMLayoutKit { umbrella header "FMLayoutKit-umbrella.h" export * module * { export * } } ================================================ FILE: Example/FrameworkTmp/Release-iphonesimulator/FMLayoutKit/FMLayoutKit.framework/_CodeSignature/CodeResources ================================================ files Headers/FMCollectionLayoutAttributes.h O30CaMucsbKG9WZDD3g+/zKOfdM= Headers/FMCollectionViewDelegateDataSourceProvider.h ev11njieIDCjXwxq6tE+0Go8Q2U= Headers/FMKVOArrayObject.h kcnRWMH4+X3NQn5BnR4efXkPI48= Headers/FMLayout.h GQflgCCxMGkdLFIzyju1R2oJpf8= Headers/FMLayoutAbsoluteSection.h O2MA6nxtIs47HrBwUMOfcGnKJ0o= Headers/FMLayoutBackground.h VDMpTbXT56ILF3enWgcXnqMGjMw= Headers/FMLayoutBaseSection.h /jt+WcYC5h4CPHpOd36eSQTRBaQ= Headers/FMLayoutCombineSection.h 9Ca3BaGs0c0NZfHxfZBVe0ls80w= Headers/FMLayoutCrossSection.h o9roPsaYR9oNzgGMFa75Mgdza+Y= Headers/FMLayoutCrossTransformSection.h U0NpzET9KhE6GXk9fud72RNE3lQ= Headers/FMLayoutDebugLog.h hcHKMAS/zM85rSoKqtsh6YPUy8w= Headers/FMLayoutDynamicSection.h HuPBUS7LR6FPj2xsGw0DepkUn4s= Headers/FMLayoutElement.h 8j97vy5ReOxOZXWPyyMjpBjkw5o= Headers/FMLayoutFillSection.h q1u3flkbJnUv725iYsAygE/6IW8= Headers/FMLayoutFixedSection.h MaPJ7tBFI85i25VGlklMiKKpzDE= Headers/FMLayoutFooter.h 2lb118tQJQgTVN+H8Og17xOvvhE= Headers/FMLayoutHeader.h 2wulFPpiYi/uV9uGVsKHMJCern0= Headers/FMLayoutKit-umbrella.h NilO12VNPzuBwk9x0e+lUmull3c= Headers/FMLayoutKit.h HIOrlmnsHlyNgbdt0mpA4dFeWBc= Headers/FMLayoutLabelSection.h ycPX8RMIU6oksfjdGsVVn9O5TEI= Headers/FMLayoutScaleSection.h gSjqmu/leF1yywOB6KoxeRlRgEA= Headers/FMLayoutView.h lP9zIEONqVArA35PEiIK+U+ZNvU= Headers/FMSupplementary.h 4a81sKmC/RMUO21JmLjBKfzkkMw= Headers/FMTeslaLayoutView.h MwC3uPYp+7202ev6w/XfyvYLCys= Headers/FMTeslaSuspensionHeightChangeDelegate.h lOgFWZxDriaARd5TuLHcp2YF6cw= Info.plist 5NI7zkvtvlP1PUJdEbD/5J1CORQ= Modules/module.modulemap Z/5Z445TliUtpHrk7ROMmxzLDDs= files2 Headers/FMCollectionLayoutAttributes.h hash O30CaMucsbKG9WZDD3g+/zKOfdM= hash2 SCNBzW5LNIJojXnqfuLkihBO9jxcvnaqvxxfo7C5ZSU= Headers/FMCollectionViewDelegateDataSourceProvider.h hash ev11njieIDCjXwxq6tE+0Go8Q2U= hash2 hmN+CbBZ5zDyEvRMSd6A4eviJMA/TyC5tlorNzw5fnc= Headers/FMKVOArrayObject.h hash kcnRWMH4+X3NQn5BnR4efXkPI48= hash2 0KMHK5kWPwHQZh/osJ5KJXYeAdvZCy6/8D9IMJkw2SA= Headers/FMLayout.h hash GQflgCCxMGkdLFIzyju1R2oJpf8= hash2 H67WFCXwOBJ9siR0RKfVNt6BrkIzHgl/zwkxIbbNpbo= Headers/FMLayoutAbsoluteSection.h hash O2MA6nxtIs47HrBwUMOfcGnKJ0o= hash2 iHDQ1jmsfUo7qcQ9OTjQkgp96/rrOotyC9htTOWlNR0= Headers/FMLayoutBackground.h hash VDMpTbXT56ILF3enWgcXnqMGjMw= hash2 CW8h/vOzmlw2IZWcpW2jxe1PxDARpIxonuIDQmlIbO0= Headers/FMLayoutBaseSection.h hash /jt+WcYC5h4CPHpOd36eSQTRBaQ= hash2 batXXhqHW6BZLaMuSziNhp9yQAxbau9enfI6FpqOhoU= Headers/FMLayoutCombineSection.h hash 9Ca3BaGs0c0NZfHxfZBVe0ls80w= hash2 PMvd1uBvRZLMthhOlow1a0S+2bJDgb988cjE6bNZv8A= Headers/FMLayoutCrossSection.h hash o9roPsaYR9oNzgGMFa75Mgdza+Y= hash2 mvztFegbd5j2kvLnIwTnffY9pnYNIRvz4g/nx++OxOU= Headers/FMLayoutCrossTransformSection.h hash U0NpzET9KhE6GXk9fud72RNE3lQ= hash2 sl96qMNZLLBY2KBdLqxoaLG3SXlrSAHqX/SSBR0McCU= Headers/FMLayoutDebugLog.h hash hcHKMAS/zM85rSoKqtsh6YPUy8w= hash2 taTztq608Z0h6SkQDJaxSV3a2QYVQ2JRAb3lLKD2ZHQ= Headers/FMLayoutDynamicSection.h hash HuPBUS7LR6FPj2xsGw0DepkUn4s= hash2 Ej6/nfzrs2yDH+Xyv7AXjHNuabjb1IjuJABodcY4PAg= Headers/FMLayoutElement.h hash 8j97vy5ReOxOZXWPyyMjpBjkw5o= hash2 cQd54yq/XVSc9SxhSuoeR4dvAjTmHq91IFYzq/2Wm7k= Headers/FMLayoutFillSection.h hash q1u3flkbJnUv725iYsAygE/6IW8= hash2 hIeJINDY21gLv90VaEso9+R63BPmrJhsaU555Y3GehQ= Headers/FMLayoutFixedSection.h hash MaPJ7tBFI85i25VGlklMiKKpzDE= hash2 OaeTbT6Ir6FA5F8e9U2Uj12RqsNm2eqidKj65UP+nII= Headers/FMLayoutFooter.h hash 2lb118tQJQgTVN+H8Og17xOvvhE= hash2 BzXtLCIkyAliHRZhU/pptph0GD8qO5vqHm4qpOIi5Fs= Headers/FMLayoutHeader.h hash 2wulFPpiYi/uV9uGVsKHMJCern0= hash2 yqZkxJvTMCrIsIuwdJdd5DlZ248yYOjlPoKLsgyXG7k= Headers/FMLayoutKit-umbrella.h hash NilO12VNPzuBwk9x0e+lUmull3c= hash2 E3e3VBmNAwNU19lpVXQEHYxEkSaaWAbBJY0Eq58c8Ws= Headers/FMLayoutKit.h hash HIOrlmnsHlyNgbdt0mpA4dFeWBc= hash2 s/tvERCyPoaAw5jgZwhSjMp98KLnuCelRQ5bcINp3Cw= Headers/FMLayoutLabelSection.h hash ycPX8RMIU6oksfjdGsVVn9O5TEI= hash2 4Ak8oYcQ4Spvazli4pEKXOPJsAZshRCbULAUUh/aYLY= Headers/FMLayoutScaleSection.h hash gSjqmu/leF1yywOB6KoxeRlRgEA= hash2 ghd2zI3OpDzgd2XwCmOTli/Mmhv2IVNQ2O8qGVf8Pzc= Headers/FMLayoutView.h hash lP9zIEONqVArA35PEiIK+U+ZNvU= hash2 wx1am9ZXc6sIjDDUjDzFt5WiPAZ2qiHc8qqqladCHTk= Headers/FMSupplementary.h hash 4a81sKmC/RMUO21JmLjBKfzkkMw= hash2 6YuaHMqNEUl3gOPsuX/Ih+Du453H5qJkiy8w6TBQcIo= Headers/FMTeslaLayoutView.h hash MwC3uPYp+7202ev6w/XfyvYLCys= hash2 LmsHrUMgKAW/6tk+QQYlrokJ+VC02DZvvASDEW4pmMs= Headers/FMTeslaSuspensionHeightChangeDelegate.h hash lOgFWZxDriaARd5TuLHcp2YF6cw= hash2 9Ku3TOJdLs0MlcrBFJzVg/LUZdqDeGMT7KTainEGyPE= Modules/module.modulemap hash Z/5Z445TliUtpHrk7ROMmxzLDDs= hash2 2Leh+uJxOIj87iJ/CeSmmbcCjX20OMUO5G6x3eou49I= rules ^.* ^.*\.lproj/ optional weight 1000 ^.*\.lproj/locversion.plist$ omit weight 1100 ^Base\.lproj/ weight 1010 ^version.plist$ rules2 .*\.dSYM($|/) weight 11 ^(.*/)?\.DS_Store$ omit weight 2000 ^.* ^.*\.lproj/ optional weight 1000 ^.*\.lproj/locversion.plist$ omit weight 1100 ^Base\.lproj/ weight 1010 ^Info\.plist$ omit weight 20 ^PkgInfo$ omit weight 20 ^embedded\.provisionprofile$ weight 20 ^version\.plist$ weight 20 ================================================ FILE: Example/FrameworkTmp/Release-iphonesimulator/FMLayoutKit/FMLayoutKit.framework.dSYM/Contents/Info.plist ================================================ CFBundleDevelopmentRegion English CFBundleIdentifier com.apple.xcode.dsym.org.cocoapods.FMLayoutKit CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType dSYM CFBundleSignature ???? CFBundleShortVersionString 1.0.0 CFBundleVersion 1 ================================================ FILE: Example/Podfile ================================================ use_frameworks! platform :ios, '8.0' target 'FMLayoutKit_Example' do pod 'FMLayoutKit', :path => '../' pod 'Masonry' # pod 'MJRefresh' target 'FMLayoutKit_Tests' do inherit! :search_paths end end ================================================ FILE: Example/Pods/Local Podspecs/FMLayoutKit.podspec.json ================================================ { "name": "FMLayoutKit", "version": "1.0.0", "summary": "A short description of FMLayoutKit.", "description": "TODO: Add long description of the pod here.", "homepage": "https://github.com/Coder_FM/FMLayoutKit", "license": { "type": "MIT", "file": "LICENSE" }, "authors": { "Coder_FM": "zhoufaming251@163.com" }, "source": { "git": "https://github.com/Coder_FM/FMLayoutKit.git", "tag": "1.0.0" }, "platforms": { "ios": "8.0" }, "source_files": "FMLayoutKit/Classes/**/*" } ================================================ FILE: Example/Pods/Masonry/LICENSE ================================================ Copyright (c) 2011-2012 Masonry Team - https://github.com/Masonry Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: Example/Pods/Masonry/Masonry/MASCompositeConstraint.h ================================================ // // MASCompositeConstraint.h // Masonry // // Created by Jonas Budelmann on 21/07/13. // Copyright (c) 2013 cloudling. All rights reserved. // #import "MASConstraint.h" #import "MASUtilities.h" /** * A group of MASConstraint objects */ @interface MASCompositeConstraint : MASConstraint /** * Creates a composite with a predefined array of children * * @param children child MASConstraints * * @return a composite constraint */ - (id)initWithChildren:(NSArray *)children; @end ================================================ FILE: Example/Pods/Masonry/Masonry/MASCompositeConstraint.m ================================================ // // MASCompositeConstraint.m // Masonry // // Created by Jonas Budelmann on 21/07/13. // Copyright (c) 2013 cloudling. All rights reserved. // #import "MASCompositeConstraint.h" #import "MASConstraint+Private.h" @interface MASCompositeConstraint () @property (nonatomic, strong) id mas_key; @property (nonatomic, strong) NSMutableArray *childConstraints; @end @implementation MASCompositeConstraint - (id)initWithChildren:(NSArray *)children { self = [super init]; if (!self) return nil; _childConstraints = [children mutableCopy]; for (MASConstraint *constraint in _childConstraints) { constraint.delegate = self; } return self; } #pragma mark - MASConstraintDelegate - (void)constraint:(MASConstraint *)constraint shouldBeReplacedWithConstraint:(MASConstraint *)replacementConstraint { NSUInteger index = [self.childConstraints indexOfObject:constraint]; NSAssert(index != NSNotFound, @"Could not find constraint %@", constraint); [self.childConstraints replaceObjectAtIndex:index withObject:replacementConstraint]; } - (MASConstraint *)constraint:(MASConstraint __unused *)constraint addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute { id strongDelegate = self.delegate; MASConstraint *newConstraint = [strongDelegate constraint:self addConstraintWithLayoutAttribute:layoutAttribute]; newConstraint.delegate = self; [self.childConstraints addObject:newConstraint]; return newConstraint; } #pragma mark - NSLayoutConstraint multiplier proxies - (MASConstraint * (^)(CGFloat))multipliedBy { return ^id(CGFloat multiplier) { for (MASConstraint *constraint in self.childConstraints) { constraint.multipliedBy(multiplier); } return self; }; } - (MASConstraint * (^)(CGFloat))dividedBy { return ^id(CGFloat divider) { for (MASConstraint *constraint in self.childConstraints) { constraint.dividedBy(divider); } return self; }; } #pragma mark - MASLayoutPriority proxy - (MASConstraint * (^)(MASLayoutPriority))priority { return ^id(MASLayoutPriority priority) { for (MASConstraint *constraint in self.childConstraints) { constraint.priority(priority); } return self; }; } #pragma mark - NSLayoutRelation proxy - (MASConstraint * (^)(id, NSLayoutRelation))equalToWithRelation { return ^id(id attr, NSLayoutRelation relation) { for (MASConstraint *constraint in self.childConstraints.copy) { constraint.equalToWithRelation(attr, relation); } return self; }; } #pragma mark - attribute chaining - (MASConstraint *)addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute { [self constraint:self addConstraintWithLayoutAttribute:layoutAttribute]; return self; } #pragma mark - Animator proxy #if TARGET_OS_MAC && !(TARGET_OS_IPHONE || TARGET_OS_TV) - (MASConstraint *)animator { for (MASConstraint *constraint in self.childConstraints) { [constraint animator]; } return self; } #endif #pragma mark - debug helpers - (MASConstraint * (^)(id))key { return ^id(id key) { self.mas_key = key; int i = 0; for (MASConstraint *constraint in self.childConstraints) { constraint.key([NSString stringWithFormat:@"%@[%d]", key, i++]); } return self; }; } #pragma mark - NSLayoutConstraint constant setters - (void)setInsets:(MASEdgeInsets)insets { for (MASConstraint *constraint in self.childConstraints) { constraint.insets = insets; } } - (void)setInset:(CGFloat)inset { for (MASConstraint *constraint in self.childConstraints) { constraint.inset = inset; } } - (void)setOffset:(CGFloat)offset { for (MASConstraint *constraint in self.childConstraints) { constraint.offset = offset; } } - (void)setSizeOffset:(CGSize)sizeOffset { for (MASConstraint *constraint in self.childConstraints) { constraint.sizeOffset = sizeOffset; } } - (void)setCenterOffset:(CGPoint)centerOffset { for (MASConstraint *constraint in self.childConstraints) { constraint.centerOffset = centerOffset; } } #pragma mark - MASConstraint - (void)activate { for (MASConstraint *constraint in self.childConstraints) { [constraint activate]; } } - (void)deactivate { for (MASConstraint *constraint in self.childConstraints) { [constraint deactivate]; } } - (void)install { for (MASConstraint *constraint in self.childConstraints) { constraint.updateExisting = self.updateExisting; [constraint install]; } } - (void)uninstall { for (MASConstraint *constraint in self.childConstraints) { [constraint uninstall]; } } @end ================================================ FILE: Example/Pods/Masonry/Masonry/MASConstraint+Private.h ================================================ // // MASConstraint+Private.h // Masonry // // Created by Nick Tymchenko on 29/04/14. // Copyright (c) 2014 cloudling. All rights reserved. // #import "MASConstraint.h" @protocol MASConstraintDelegate; @interface MASConstraint () /** * Whether or not to check for an existing constraint instead of adding constraint */ @property (nonatomic, assign) BOOL updateExisting; /** * Usually MASConstraintMaker but could be a parent MASConstraint */ @property (nonatomic, weak) id delegate; /** * Based on a provided value type, is equal to calling: * NSNumber - setOffset: * NSValue with CGPoint - setPointOffset: * NSValue with CGSize - setSizeOffset: * NSValue with MASEdgeInsets - setInsets: */ - (void)setLayoutConstantWithValue:(NSValue *)value; @end @interface MASConstraint (Abstract) /** * Sets the constraint relation to given NSLayoutRelation * returns a block which accepts one of the following: * MASViewAttribute, UIView, NSValue, NSArray * see readme for more details. */ - (MASConstraint * (^)(id, NSLayoutRelation))equalToWithRelation; /** * Override to set a custom chaining behaviour */ - (MASConstraint *)addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute; @end @protocol MASConstraintDelegate /** * Notifies the delegate when the constraint needs to be replaced with another constraint. For example * A MASViewConstraint may turn into a MASCompositeConstraint when an array is passed to one of the equality blocks */ - (void)constraint:(MASConstraint *)constraint shouldBeReplacedWithConstraint:(MASConstraint *)replacementConstraint; - (MASConstraint *)constraint:(MASConstraint *)constraint addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute; @end ================================================ FILE: Example/Pods/Masonry/Masonry/MASConstraint.h ================================================ // // MASConstraint.h // Masonry // // Created by Jonas Budelmann on 22/07/13. // Copyright (c) 2013 cloudling. All rights reserved. // #import "MASUtilities.h" /** * Enables Constraints to be created with chainable syntax * Constraint can represent single NSLayoutConstraint (MASViewConstraint) * or a group of NSLayoutConstraints (MASComposisteConstraint) */ @interface MASConstraint : NSObject // Chaining Support /** * Modifies the NSLayoutConstraint constant, * only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following * NSLayoutAttributeTop, NSLayoutAttributeLeft, NSLayoutAttributeBottom, NSLayoutAttributeRight */ - (MASConstraint * (^)(MASEdgeInsets insets))insets; /** * Modifies the NSLayoutConstraint constant, * only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following * NSLayoutAttributeTop, NSLayoutAttributeLeft, NSLayoutAttributeBottom, NSLayoutAttributeRight */ - (MASConstraint * (^)(CGFloat inset))inset; /** * Modifies the NSLayoutConstraint constant, * only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following * NSLayoutAttributeWidth, NSLayoutAttributeHeight */ - (MASConstraint * (^)(CGSize offset))sizeOffset; /** * Modifies the NSLayoutConstraint constant, * only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following * NSLayoutAttributeCenterX, NSLayoutAttributeCenterY */ - (MASConstraint * (^)(CGPoint offset))centerOffset; /** * Modifies the NSLayoutConstraint constant */ - (MASConstraint * (^)(CGFloat offset))offset; /** * Modifies the NSLayoutConstraint constant based on a value type */ - (MASConstraint * (^)(NSValue *value))valueOffset; /** * Sets the NSLayoutConstraint multiplier property */ - (MASConstraint * (^)(CGFloat multiplier))multipliedBy; /** * Sets the NSLayoutConstraint multiplier to 1.0/dividedBy */ - (MASConstraint * (^)(CGFloat divider))dividedBy; /** * Sets the NSLayoutConstraint priority to a float or MASLayoutPriority */ - (MASConstraint * (^)(MASLayoutPriority priority))priority; /** * Sets the NSLayoutConstraint priority to MASLayoutPriorityLow */ - (MASConstraint * (^)(void))priorityLow; /** * Sets the NSLayoutConstraint priority to MASLayoutPriorityMedium */ - (MASConstraint * (^)(void))priorityMedium; /** * Sets the NSLayoutConstraint priority to MASLayoutPriorityHigh */ - (MASConstraint * (^)(void))priorityHigh; /** * Sets the constraint relation to NSLayoutRelationEqual * returns a block which accepts one of the following: * MASViewAttribute, UIView, NSValue, NSArray * see readme for more details. */ - (MASConstraint * (^)(id attr))equalTo; /** * Sets the constraint relation to NSLayoutRelationGreaterThanOrEqual * returns a block which accepts one of the following: * MASViewAttribute, UIView, NSValue, NSArray * see readme for more details. */ - (MASConstraint * (^)(id attr))greaterThanOrEqualTo; /** * Sets the constraint relation to NSLayoutRelationLessThanOrEqual * returns a block which accepts one of the following: * MASViewAttribute, UIView, NSValue, NSArray * see readme for more details. */ - (MASConstraint * (^)(id attr))lessThanOrEqualTo; /** * Optional semantic property which has no effect but improves the readability of constraint */ - (MASConstraint *)with; /** * Optional semantic property which has no effect but improves the readability of constraint */ - (MASConstraint *)and; /** * Creates a new MASCompositeConstraint with the called attribute and reciever */ - (MASConstraint *)left; - (MASConstraint *)top; - (MASConstraint *)right; - (MASConstraint *)bottom; - (MASConstraint *)leading; - (MASConstraint *)trailing; - (MASConstraint *)width; - (MASConstraint *)height; - (MASConstraint *)centerX; - (MASConstraint *)centerY; - (MASConstraint *)baseline; #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) - (MASConstraint *)firstBaseline; - (MASConstraint *)lastBaseline; #endif #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) - (MASConstraint *)leftMargin; - (MASConstraint *)rightMargin; - (MASConstraint *)topMargin; - (MASConstraint *)bottomMargin; - (MASConstraint *)leadingMargin; - (MASConstraint *)trailingMargin; - (MASConstraint *)centerXWithinMargins; - (MASConstraint *)centerYWithinMargins; #endif /** * Sets the constraint debug name */ - (MASConstraint * (^)(id key))key; // NSLayoutConstraint constant Setters // for use outside of mas_updateConstraints/mas_makeConstraints blocks /** * Modifies the NSLayoutConstraint constant, * only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following * NSLayoutAttributeTop, NSLayoutAttributeLeft, NSLayoutAttributeBottom, NSLayoutAttributeRight */ - (void)setInsets:(MASEdgeInsets)insets; /** * Modifies the NSLayoutConstraint constant, * only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following * NSLayoutAttributeTop, NSLayoutAttributeLeft, NSLayoutAttributeBottom, NSLayoutAttributeRight */ - (void)setInset:(CGFloat)inset; /** * Modifies the NSLayoutConstraint constant, * only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following * NSLayoutAttributeWidth, NSLayoutAttributeHeight */ - (void)setSizeOffset:(CGSize)sizeOffset; /** * Modifies the NSLayoutConstraint constant, * only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following * NSLayoutAttributeCenterX, NSLayoutAttributeCenterY */ - (void)setCenterOffset:(CGPoint)centerOffset; /** * Modifies the NSLayoutConstraint constant */ - (void)setOffset:(CGFloat)offset; // NSLayoutConstraint Installation support #if TARGET_OS_MAC && !(TARGET_OS_IPHONE || TARGET_OS_TV) /** * Whether or not to go through the animator proxy when modifying the constraint */ @property (nonatomic, copy, readonly) MASConstraint *animator; #endif /** * Activates an NSLayoutConstraint if it's supported by an OS. * Invokes install otherwise. */ - (void)activate; /** * Deactivates previously installed/activated NSLayoutConstraint. */ - (void)deactivate; /** * Creates a NSLayoutConstraint and adds it to the appropriate view. */ - (void)install; /** * Removes previously installed NSLayoutConstraint */ - (void)uninstall; @end /** * Convenience auto-boxing macros for MASConstraint methods. * * Defining MAS_SHORTHAND_GLOBALS will turn on auto-boxing for default syntax. * A potential drawback of this is that the unprefixed macros will appear in global scope. */ #define mas_equalTo(...) equalTo(MASBoxValue((__VA_ARGS__))) #define mas_greaterThanOrEqualTo(...) greaterThanOrEqualTo(MASBoxValue((__VA_ARGS__))) #define mas_lessThanOrEqualTo(...) lessThanOrEqualTo(MASBoxValue((__VA_ARGS__))) #define mas_offset(...) valueOffset(MASBoxValue((__VA_ARGS__))) #ifdef MAS_SHORTHAND_GLOBALS #define equalTo(...) mas_equalTo(__VA_ARGS__) #define greaterThanOrEqualTo(...) mas_greaterThanOrEqualTo(__VA_ARGS__) #define lessThanOrEqualTo(...) mas_lessThanOrEqualTo(__VA_ARGS__) #define offset(...) mas_offset(__VA_ARGS__) #endif @interface MASConstraint (AutoboxingSupport) /** * Aliases to corresponding relation methods (for shorthand macros) * Also needed to aid autocompletion */ - (MASConstraint * (^)(id attr))mas_equalTo; - (MASConstraint * (^)(id attr))mas_greaterThanOrEqualTo; - (MASConstraint * (^)(id attr))mas_lessThanOrEqualTo; /** * A dummy method to aid autocompletion */ - (MASConstraint * (^)(id offset))mas_offset; @end ================================================ FILE: Example/Pods/Masonry/Masonry/MASConstraint.m ================================================ // // MASConstraint.m // Masonry // // Created by Nick Tymchenko on 1/20/14. // #import "MASConstraint.h" #import "MASConstraint+Private.h" #define MASMethodNotImplemented() \ @throw [NSException exceptionWithName:NSInternalInconsistencyException \ reason:[NSString stringWithFormat:@"You must override %@ in a subclass.", NSStringFromSelector(_cmd)] \ userInfo:nil] @implementation MASConstraint #pragma mark - Init - (id)init { NSAssert(![self isMemberOfClass:[MASConstraint class]], @"MASConstraint is an abstract class, you should not instantiate it directly."); return [super init]; } #pragma mark - NSLayoutRelation proxies - (MASConstraint * (^)(id))equalTo { return ^id(id attribute) { return self.equalToWithRelation(attribute, NSLayoutRelationEqual); }; } - (MASConstraint * (^)(id))mas_equalTo { return ^id(id attribute) { return self.equalToWithRelation(attribute, NSLayoutRelationEqual); }; } - (MASConstraint * (^)(id))greaterThanOrEqualTo { return ^id(id attribute) { return self.equalToWithRelation(attribute, NSLayoutRelationGreaterThanOrEqual); }; } - (MASConstraint * (^)(id))mas_greaterThanOrEqualTo { return ^id(id attribute) { return self.equalToWithRelation(attribute, NSLayoutRelationGreaterThanOrEqual); }; } - (MASConstraint * (^)(id))lessThanOrEqualTo { return ^id(id attribute) { return self.equalToWithRelation(attribute, NSLayoutRelationLessThanOrEqual); }; } - (MASConstraint * (^)(id))mas_lessThanOrEqualTo { return ^id(id attribute) { return self.equalToWithRelation(attribute, NSLayoutRelationLessThanOrEqual); }; } #pragma mark - MASLayoutPriority proxies - (MASConstraint * (^)(void))priorityLow { return ^id{ self.priority(MASLayoutPriorityDefaultLow); return self; }; } - (MASConstraint * (^)(void))priorityMedium { return ^id{ self.priority(MASLayoutPriorityDefaultMedium); return self; }; } - (MASConstraint * (^)(void))priorityHigh { return ^id{ self.priority(MASLayoutPriorityDefaultHigh); return self; }; } #pragma mark - NSLayoutConstraint constant proxies - (MASConstraint * (^)(MASEdgeInsets))insets { return ^id(MASEdgeInsets insets){ self.insets = insets; return self; }; } - (MASConstraint * (^)(CGFloat))inset { return ^id(CGFloat inset){ self.inset = inset; return self; }; } - (MASConstraint * (^)(CGSize))sizeOffset { return ^id(CGSize offset) { self.sizeOffset = offset; return self; }; } - (MASConstraint * (^)(CGPoint))centerOffset { return ^id(CGPoint offset) { self.centerOffset = offset; return self; }; } - (MASConstraint * (^)(CGFloat))offset { return ^id(CGFloat offset){ self.offset = offset; return self; }; } - (MASConstraint * (^)(NSValue *value))valueOffset { return ^id(NSValue *offset) { NSAssert([offset isKindOfClass:NSValue.class], @"expected an NSValue offset, got: %@", offset); [self setLayoutConstantWithValue:offset]; return self; }; } - (MASConstraint * (^)(id offset))mas_offset { // Will never be called due to macro return nil; } #pragma mark - NSLayoutConstraint constant setter - (void)setLayoutConstantWithValue:(NSValue *)value { if ([value isKindOfClass:NSNumber.class]) { self.offset = [(NSNumber *)value doubleValue]; } else if (strcmp(value.objCType, @encode(CGPoint)) == 0) { CGPoint point; [value getValue:&point]; self.centerOffset = point; } else if (strcmp(value.objCType, @encode(CGSize)) == 0) { CGSize size; [value getValue:&size]; self.sizeOffset = size; } else if (strcmp(value.objCType, @encode(MASEdgeInsets)) == 0) { MASEdgeInsets insets; [value getValue:&insets]; self.insets = insets; } else { NSAssert(NO, @"attempting to set layout constant with unsupported value: %@", value); } } #pragma mark - Semantic properties - (MASConstraint *)with { return self; } - (MASConstraint *)and { return self; } #pragma mark - Chaining - (MASConstraint *)addConstraintWithLayoutAttribute:(NSLayoutAttribute __unused)layoutAttribute { MASMethodNotImplemented(); } - (MASConstraint *)left { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeft]; } - (MASConstraint *)top { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTop]; } - (MASConstraint *)right { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeRight]; } - (MASConstraint *)bottom { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeBottom]; } - (MASConstraint *)leading { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeading]; } - (MASConstraint *)trailing { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTrailing]; } - (MASConstraint *)width { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeWidth]; } - (MASConstraint *)height { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeHeight]; } - (MASConstraint *)centerX { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterX]; } - (MASConstraint *)centerY { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterY]; } - (MASConstraint *)baseline { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeBaseline]; } #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) - (MASConstraint *)firstBaseline { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeFirstBaseline]; } - (MASConstraint *)lastBaseline { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLastBaseline]; } #endif #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) - (MASConstraint *)leftMargin { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeftMargin]; } - (MASConstraint *)rightMargin { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeRightMargin]; } - (MASConstraint *)topMargin { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTopMargin]; } - (MASConstraint *)bottomMargin { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeBottomMargin]; } - (MASConstraint *)leadingMargin { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeadingMargin]; } - (MASConstraint *)trailingMargin { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTrailingMargin]; } - (MASConstraint *)centerXWithinMargins { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterXWithinMargins]; } - (MASConstraint *)centerYWithinMargins { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterYWithinMargins]; } #endif #pragma mark - Abstract - (MASConstraint * (^)(CGFloat multiplier))multipliedBy { MASMethodNotImplemented(); } - (MASConstraint * (^)(CGFloat divider))dividedBy { MASMethodNotImplemented(); } - (MASConstraint * (^)(MASLayoutPriority priority))priority { MASMethodNotImplemented(); } - (MASConstraint * (^)(id, NSLayoutRelation))equalToWithRelation { MASMethodNotImplemented(); } - (MASConstraint * (^)(id key))key { MASMethodNotImplemented(); } - (void)setInsets:(MASEdgeInsets __unused)insets { MASMethodNotImplemented(); } - (void)setInset:(CGFloat __unused)inset { MASMethodNotImplemented(); } - (void)setSizeOffset:(CGSize __unused)sizeOffset { MASMethodNotImplemented(); } - (void)setCenterOffset:(CGPoint __unused)centerOffset { MASMethodNotImplemented(); } - (void)setOffset:(CGFloat __unused)offset { MASMethodNotImplemented(); } #if TARGET_OS_MAC && !(TARGET_OS_IPHONE || TARGET_OS_TV) - (MASConstraint *)animator { MASMethodNotImplemented(); } #endif - (void)activate { MASMethodNotImplemented(); } - (void)deactivate { MASMethodNotImplemented(); } - (void)install { MASMethodNotImplemented(); } - (void)uninstall { MASMethodNotImplemented(); } @end ================================================ FILE: Example/Pods/Masonry/Masonry/MASConstraintMaker.h ================================================ // // MASConstraintMaker.h // Masonry // // Created by Jonas Budelmann on 20/07/13. // Copyright (c) 2013 cloudling. All rights reserved. // #import "MASConstraint.h" #import "MASUtilities.h" typedef NS_OPTIONS(NSInteger, MASAttribute) { MASAttributeLeft = 1 << NSLayoutAttributeLeft, MASAttributeRight = 1 << NSLayoutAttributeRight, MASAttributeTop = 1 << NSLayoutAttributeTop, MASAttributeBottom = 1 << NSLayoutAttributeBottom, MASAttributeLeading = 1 << NSLayoutAttributeLeading, MASAttributeTrailing = 1 << NSLayoutAttributeTrailing, MASAttributeWidth = 1 << NSLayoutAttributeWidth, MASAttributeHeight = 1 << NSLayoutAttributeHeight, MASAttributeCenterX = 1 << NSLayoutAttributeCenterX, MASAttributeCenterY = 1 << NSLayoutAttributeCenterY, MASAttributeBaseline = 1 << NSLayoutAttributeBaseline, #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) MASAttributeFirstBaseline = 1 << NSLayoutAttributeFirstBaseline, MASAttributeLastBaseline = 1 << NSLayoutAttributeLastBaseline, #endif #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) MASAttributeLeftMargin = 1 << NSLayoutAttributeLeftMargin, MASAttributeRightMargin = 1 << NSLayoutAttributeRightMargin, MASAttributeTopMargin = 1 << NSLayoutAttributeTopMargin, MASAttributeBottomMargin = 1 << NSLayoutAttributeBottomMargin, MASAttributeLeadingMargin = 1 << NSLayoutAttributeLeadingMargin, MASAttributeTrailingMargin = 1 << NSLayoutAttributeTrailingMargin, MASAttributeCenterXWithinMargins = 1 << NSLayoutAttributeCenterXWithinMargins, MASAttributeCenterYWithinMargins = 1 << NSLayoutAttributeCenterYWithinMargins, #endif }; /** * Provides factory methods for creating MASConstraints. * Constraints are collected until they are ready to be installed * */ @interface MASConstraintMaker : NSObject /** * The following properties return a new MASViewConstraint * with the first item set to the makers associated view and the appropriate MASViewAttribute */ @property (nonatomic, strong, readonly) MASConstraint *left; @property (nonatomic, strong, readonly) MASConstraint *top; @property (nonatomic, strong, readonly) MASConstraint *right; @property (nonatomic, strong, readonly) MASConstraint *bottom; @property (nonatomic, strong, readonly) MASConstraint *leading; @property (nonatomic, strong, readonly) MASConstraint *trailing; @property (nonatomic, strong, readonly) MASConstraint *width; @property (nonatomic, strong, readonly) MASConstraint *height; @property (nonatomic, strong, readonly) MASConstraint *centerX; @property (nonatomic, strong, readonly) MASConstraint *centerY; @property (nonatomic, strong, readonly) MASConstraint *baseline; #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) @property (nonatomic, strong, readonly) MASConstraint *firstBaseline; @property (nonatomic, strong, readonly) MASConstraint *lastBaseline; #endif #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) @property (nonatomic, strong, readonly) MASConstraint *leftMargin; @property (nonatomic, strong, readonly) MASConstraint *rightMargin; @property (nonatomic, strong, readonly) MASConstraint *topMargin; @property (nonatomic, strong, readonly) MASConstraint *bottomMargin; @property (nonatomic, strong, readonly) MASConstraint *leadingMargin; @property (nonatomic, strong, readonly) MASConstraint *trailingMargin; @property (nonatomic, strong, readonly) MASConstraint *centerXWithinMargins; @property (nonatomic, strong, readonly) MASConstraint *centerYWithinMargins; #endif /** * Returns a block which creates a new MASCompositeConstraint with the first item set * to the makers associated view and children corresponding to the set bits in the * MASAttribute parameter. Combine multiple attributes via binary-or. */ @property (nonatomic, strong, readonly) MASConstraint *(^attributes)(MASAttribute attrs); /** * Creates a MASCompositeConstraint with type MASCompositeConstraintTypeEdges * which generates the appropriate MASViewConstraint children (top, left, bottom, right) * with the first item set to the makers associated view */ @property (nonatomic, strong, readonly) MASConstraint *edges; /** * Creates a MASCompositeConstraint with type MASCompositeConstraintTypeSize * which generates the appropriate MASViewConstraint children (width, height) * with the first item set to the makers associated view */ @property (nonatomic, strong, readonly) MASConstraint *size; /** * Creates a MASCompositeConstraint with type MASCompositeConstraintTypeCenter * which generates the appropriate MASViewConstraint children (centerX, centerY) * with the first item set to the makers associated view */ @property (nonatomic, strong, readonly) MASConstraint *center; /** * Whether or not to check for an existing constraint instead of adding constraint */ @property (nonatomic, assign) BOOL updateExisting; /** * Whether or not to remove existing constraints prior to installing */ @property (nonatomic, assign) BOOL removeExisting; /** * initialises the maker with a default view * * @param view any MASConstraint are created with this view as the first item * * @return a new MASConstraintMaker */ - (id)initWithView:(MAS_VIEW *)view; /** * Calls install method on any MASConstraints which have been created by this maker * * @return an array of all the installed MASConstraints */ - (NSArray *)install; - (MASConstraint * (^)(dispatch_block_t))group; @end ================================================ FILE: Example/Pods/Masonry/Masonry/MASConstraintMaker.m ================================================ // // MASConstraintMaker.m // Masonry // // Created by Jonas Budelmann on 20/07/13. // Copyright (c) 2013 cloudling. All rights reserved. // #import "MASConstraintMaker.h" #import "MASViewConstraint.h" #import "MASCompositeConstraint.h" #import "MASConstraint+Private.h" #import "MASViewAttribute.h" #import "View+MASAdditions.h" @interface MASConstraintMaker () @property (nonatomic, weak) MAS_VIEW *view; @property (nonatomic, strong) NSMutableArray *constraints; @end @implementation MASConstraintMaker - (id)initWithView:(MAS_VIEW *)view { self = [super init]; if (!self) return nil; self.view = view; self.constraints = NSMutableArray.new; return self; } - (NSArray *)install { if (self.removeExisting) { NSArray *installedConstraints = [MASViewConstraint installedConstraintsForView:self.view]; for (MASConstraint *constraint in installedConstraints) { [constraint uninstall]; } } NSArray *constraints = self.constraints.copy; for (MASConstraint *constraint in constraints) { constraint.updateExisting = self.updateExisting; [constraint install]; } [self.constraints removeAllObjects]; return constraints; } #pragma mark - MASConstraintDelegate - (void)constraint:(MASConstraint *)constraint shouldBeReplacedWithConstraint:(MASConstraint *)replacementConstraint { NSUInteger index = [self.constraints indexOfObject:constraint]; NSAssert(index != NSNotFound, @"Could not find constraint %@", constraint); [self.constraints replaceObjectAtIndex:index withObject:replacementConstraint]; } - (MASConstraint *)constraint:(MASConstraint *)constraint addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute { MASViewAttribute *viewAttribute = [[MASViewAttribute alloc] initWithView:self.view layoutAttribute:layoutAttribute]; MASViewConstraint *newConstraint = [[MASViewConstraint alloc] initWithFirstViewAttribute:viewAttribute]; if ([constraint isKindOfClass:MASViewConstraint.class]) { //replace with composite constraint NSArray *children = @[constraint, newConstraint]; MASCompositeConstraint *compositeConstraint = [[MASCompositeConstraint alloc] initWithChildren:children]; compositeConstraint.delegate = self; [self constraint:constraint shouldBeReplacedWithConstraint:compositeConstraint]; return compositeConstraint; } if (!constraint) { newConstraint.delegate = self; [self.constraints addObject:newConstraint]; } return newConstraint; } - (MASConstraint *)addConstraintWithAttributes:(MASAttribute)attrs { __unused MASAttribute anyAttribute = (MASAttributeLeft | MASAttributeRight | MASAttributeTop | MASAttributeBottom | MASAttributeLeading | MASAttributeTrailing | MASAttributeWidth | MASAttributeHeight | MASAttributeCenterX | MASAttributeCenterY | MASAttributeBaseline #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) | MASAttributeFirstBaseline | MASAttributeLastBaseline #endif #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) | MASAttributeLeftMargin | MASAttributeRightMargin | MASAttributeTopMargin | MASAttributeBottomMargin | MASAttributeLeadingMargin | MASAttributeTrailingMargin | MASAttributeCenterXWithinMargins | MASAttributeCenterYWithinMargins #endif ); NSAssert((attrs & anyAttribute) != 0, @"You didn't pass any attribute to make.attributes(...)"); NSMutableArray *attributes = [NSMutableArray array]; if (attrs & MASAttributeLeft) [attributes addObject:self.view.mas_left]; if (attrs & MASAttributeRight) [attributes addObject:self.view.mas_right]; if (attrs & MASAttributeTop) [attributes addObject:self.view.mas_top]; if (attrs & MASAttributeBottom) [attributes addObject:self.view.mas_bottom]; if (attrs & MASAttributeLeading) [attributes addObject:self.view.mas_leading]; if (attrs & MASAttributeTrailing) [attributes addObject:self.view.mas_trailing]; if (attrs & MASAttributeWidth) [attributes addObject:self.view.mas_width]; if (attrs & MASAttributeHeight) [attributes addObject:self.view.mas_height]; if (attrs & MASAttributeCenterX) [attributes addObject:self.view.mas_centerX]; if (attrs & MASAttributeCenterY) [attributes addObject:self.view.mas_centerY]; if (attrs & MASAttributeBaseline) [attributes addObject:self.view.mas_baseline]; #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) if (attrs & MASAttributeFirstBaseline) [attributes addObject:self.view.mas_firstBaseline]; if (attrs & MASAttributeLastBaseline) [attributes addObject:self.view.mas_lastBaseline]; #endif #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) if (attrs & MASAttributeLeftMargin) [attributes addObject:self.view.mas_leftMargin]; if (attrs & MASAttributeRightMargin) [attributes addObject:self.view.mas_rightMargin]; if (attrs & MASAttributeTopMargin) [attributes addObject:self.view.mas_topMargin]; if (attrs & MASAttributeBottomMargin) [attributes addObject:self.view.mas_bottomMargin]; if (attrs & MASAttributeLeadingMargin) [attributes addObject:self.view.mas_leadingMargin]; if (attrs & MASAttributeTrailingMargin) [attributes addObject:self.view.mas_trailingMargin]; if (attrs & MASAttributeCenterXWithinMargins) [attributes addObject:self.view.mas_centerXWithinMargins]; if (attrs & MASAttributeCenterYWithinMargins) [attributes addObject:self.view.mas_centerYWithinMargins]; #endif NSMutableArray *children = [NSMutableArray arrayWithCapacity:attributes.count]; for (MASViewAttribute *a in attributes) { [children addObject:[[MASViewConstraint alloc] initWithFirstViewAttribute:a]]; } MASCompositeConstraint *constraint = [[MASCompositeConstraint alloc] initWithChildren:children]; constraint.delegate = self; [self.constraints addObject:constraint]; return constraint; } #pragma mark - standard Attributes - (MASConstraint *)addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute { return [self constraint:nil addConstraintWithLayoutAttribute:layoutAttribute]; } - (MASConstraint *)left { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeft]; } - (MASConstraint *)top { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTop]; } - (MASConstraint *)right { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeRight]; } - (MASConstraint *)bottom { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeBottom]; } - (MASConstraint *)leading { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeading]; } - (MASConstraint *)trailing { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTrailing]; } - (MASConstraint *)width { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeWidth]; } - (MASConstraint *)height { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeHeight]; } - (MASConstraint *)centerX { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterX]; } - (MASConstraint *)centerY { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterY]; } - (MASConstraint *)baseline { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeBaseline]; } - (MASConstraint *(^)(MASAttribute))attributes { return ^(MASAttribute attrs){ return [self addConstraintWithAttributes:attrs]; }; } #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) - (MASConstraint *)firstBaseline { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeFirstBaseline]; } - (MASConstraint *)lastBaseline { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLastBaseline]; } #endif #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) - (MASConstraint *)leftMargin { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeftMargin]; } - (MASConstraint *)rightMargin { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeRightMargin]; } - (MASConstraint *)topMargin { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTopMargin]; } - (MASConstraint *)bottomMargin { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeBottomMargin]; } - (MASConstraint *)leadingMargin { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeadingMargin]; } - (MASConstraint *)trailingMargin { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTrailingMargin]; } - (MASConstraint *)centerXWithinMargins { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterXWithinMargins]; } - (MASConstraint *)centerYWithinMargins { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterYWithinMargins]; } #endif #pragma mark - composite Attributes - (MASConstraint *)edges { return [self addConstraintWithAttributes:MASAttributeTop | MASAttributeLeft | MASAttributeRight | MASAttributeBottom]; } - (MASConstraint *)size { return [self addConstraintWithAttributes:MASAttributeWidth | MASAttributeHeight]; } - (MASConstraint *)center { return [self addConstraintWithAttributes:MASAttributeCenterX | MASAttributeCenterY]; } #pragma mark - grouping - (MASConstraint *(^)(dispatch_block_t group))group { return ^id(dispatch_block_t group) { NSInteger previousCount = self.constraints.count; group(); NSArray *children = [self.constraints subarrayWithRange:NSMakeRange(previousCount, self.constraints.count - previousCount)]; MASCompositeConstraint *constraint = [[MASCompositeConstraint alloc] initWithChildren:children]; constraint.delegate = self; return constraint; }; } @end ================================================ FILE: Example/Pods/Masonry/Masonry/MASLayoutConstraint.h ================================================ // // MASLayoutConstraint.h // Masonry // // Created by Jonas Budelmann on 3/08/13. // Copyright (c) 2013 Jonas Budelmann. All rights reserved. // #import "MASUtilities.h" /** * When you are debugging or printing the constraints attached to a view this subclass * makes it easier to identify which constraints have been created via Masonry */ @interface MASLayoutConstraint : NSLayoutConstraint /** * a key to associate with this constraint */ @property (nonatomic, strong) id mas_key; @end ================================================ FILE: Example/Pods/Masonry/Masonry/MASLayoutConstraint.m ================================================ // // MASLayoutConstraint.m // Masonry // // Created by Jonas Budelmann on 3/08/13. // Copyright (c) 2013 Jonas Budelmann. All rights reserved. // #import "MASLayoutConstraint.h" @implementation MASLayoutConstraint @end ================================================ FILE: Example/Pods/Masonry/Masonry/MASUtilities.h ================================================ // // MASUtilities.h // Masonry // // Created by Jonas Budelmann on 19/08/13. // Copyright (c) 2013 Jonas Budelmann. All rights reserved. // #import #if TARGET_OS_IPHONE || TARGET_OS_TV #import #define MAS_VIEW UIView #define MAS_VIEW_CONTROLLER UIViewController #define MASEdgeInsets UIEdgeInsets typedef UILayoutPriority MASLayoutPriority; static const MASLayoutPriority MASLayoutPriorityRequired = UILayoutPriorityRequired; static const MASLayoutPriority MASLayoutPriorityDefaultHigh = UILayoutPriorityDefaultHigh; static const MASLayoutPriority MASLayoutPriorityDefaultMedium = 500; static const MASLayoutPriority MASLayoutPriorityDefaultLow = UILayoutPriorityDefaultLow; static const MASLayoutPriority MASLayoutPriorityFittingSizeLevel = UILayoutPriorityFittingSizeLevel; #elif TARGET_OS_MAC #import #define MAS_VIEW NSView #define MASEdgeInsets NSEdgeInsets typedef NSLayoutPriority MASLayoutPriority; static const MASLayoutPriority MASLayoutPriorityRequired = NSLayoutPriorityRequired; static const MASLayoutPriority MASLayoutPriorityDefaultHigh = NSLayoutPriorityDefaultHigh; static const MASLayoutPriority MASLayoutPriorityDragThatCanResizeWindow = NSLayoutPriorityDragThatCanResizeWindow; static const MASLayoutPriority MASLayoutPriorityDefaultMedium = 501; static const MASLayoutPriority MASLayoutPriorityWindowSizeStayPut = NSLayoutPriorityWindowSizeStayPut; static const MASLayoutPriority MASLayoutPriorityDragThatCannotResizeWindow = NSLayoutPriorityDragThatCannotResizeWindow; static const MASLayoutPriority MASLayoutPriorityDefaultLow = NSLayoutPriorityDefaultLow; static const MASLayoutPriority MASLayoutPriorityFittingSizeCompression = NSLayoutPriorityFittingSizeCompression; #endif /** * Allows you to attach keys to objects matching the variable names passed. * * view1.mas_key = @"view1", view2.mas_key = @"view2"; * * is equivalent to: * * MASAttachKeys(view1, view2); */ #define MASAttachKeys(...) \ { \ NSDictionary *keyPairs = NSDictionaryOfVariableBindings(__VA_ARGS__); \ for (id key in keyPairs.allKeys) { \ id obj = keyPairs[key]; \ NSAssert([obj respondsToSelector:@selector(setMas_key:)], \ @"Cannot attach mas_key to %@", obj); \ [obj setMas_key:key]; \ } \ } /** * Used to create object hashes * Based on http://www.mikeash.com/pyblog/friday-qa-2010-06-18-implementing-equality-and-hashing.html */ #define MAS_NSUINT_BIT (CHAR_BIT * sizeof(NSUInteger)) #define MAS_NSUINTROTATE(val, howmuch) ((((NSUInteger)val) << howmuch) | (((NSUInteger)val) >> (MAS_NSUINT_BIT - howmuch))) /** * Given a scalar or struct value, wraps it in NSValue * Based on EXPObjectify: https://github.com/specta/expecta */ static inline id _MASBoxValue(const char *type, ...) { va_list v; va_start(v, type); id obj = nil; if (strcmp(type, @encode(id)) == 0) { id actual = va_arg(v, id); obj = actual; } else if (strcmp(type, @encode(CGPoint)) == 0) { CGPoint actual = (CGPoint)va_arg(v, CGPoint); obj = [NSValue value:&actual withObjCType:type]; } else if (strcmp(type, @encode(CGSize)) == 0) { CGSize actual = (CGSize)va_arg(v, CGSize); obj = [NSValue value:&actual withObjCType:type]; } else if (strcmp(type, @encode(MASEdgeInsets)) == 0) { MASEdgeInsets actual = (MASEdgeInsets)va_arg(v, MASEdgeInsets); obj = [NSValue value:&actual withObjCType:type]; } else if (strcmp(type, @encode(double)) == 0) { double actual = (double)va_arg(v, double); obj = [NSNumber numberWithDouble:actual]; } else if (strcmp(type, @encode(float)) == 0) { float actual = (float)va_arg(v, double); obj = [NSNumber numberWithFloat:actual]; } else if (strcmp(type, @encode(int)) == 0) { int actual = (int)va_arg(v, int); obj = [NSNumber numberWithInt:actual]; } else if (strcmp(type, @encode(long)) == 0) { long actual = (long)va_arg(v, long); obj = [NSNumber numberWithLong:actual]; } else if (strcmp(type, @encode(long long)) == 0) { long long actual = (long long)va_arg(v, long long); obj = [NSNumber numberWithLongLong:actual]; } else if (strcmp(type, @encode(short)) == 0) { short actual = (short)va_arg(v, int); obj = [NSNumber numberWithShort:actual]; } else if (strcmp(type, @encode(char)) == 0) { char actual = (char)va_arg(v, int); obj = [NSNumber numberWithChar:actual]; } else if (strcmp(type, @encode(bool)) == 0) { bool actual = (bool)va_arg(v, int); obj = [NSNumber numberWithBool:actual]; } else if (strcmp(type, @encode(unsigned char)) == 0) { unsigned char actual = (unsigned char)va_arg(v, unsigned int); obj = [NSNumber numberWithUnsignedChar:actual]; } else if (strcmp(type, @encode(unsigned int)) == 0) { unsigned int actual = (unsigned int)va_arg(v, unsigned int); obj = [NSNumber numberWithUnsignedInt:actual]; } else if (strcmp(type, @encode(unsigned long)) == 0) { unsigned long actual = (unsigned long)va_arg(v, unsigned long); obj = [NSNumber numberWithUnsignedLong:actual]; } else if (strcmp(type, @encode(unsigned long long)) == 0) { unsigned long long actual = (unsigned long long)va_arg(v, unsigned long long); obj = [NSNumber numberWithUnsignedLongLong:actual]; } else if (strcmp(type, @encode(unsigned short)) == 0) { unsigned short actual = (unsigned short)va_arg(v, unsigned int); obj = [NSNumber numberWithUnsignedShort:actual]; } va_end(v); return obj; } #define MASBoxValue(value) _MASBoxValue(@encode(__typeof__((value))), (value)) ================================================ FILE: Example/Pods/Masonry/Masonry/MASViewAttribute.h ================================================ // // MASViewAttribute.h // Masonry // // Created by Jonas Budelmann on 21/07/13. // Copyright (c) 2013 cloudling. All rights reserved. // #import "MASUtilities.h" /** * An immutable tuple which stores the view and the related NSLayoutAttribute. * Describes part of either the left or right hand side of a constraint equation */ @interface MASViewAttribute : NSObject /** * The view which the reciever relates to. Can be nil if item is not a view. */ @property (nonatomic, weak, readonly) MAS_VIEW *view; /** * The item which the reciever relates to. */ @property (nonatomic, weak, readonly) id item; /** * The attribute which the reciever relates to */ @property (nonatomic, assign, readonly) NSLayoutAttribute layoutAttribute; /** * Convenience initializer. */ - (id)initWithView:(MAS_VIEW *)view layoutAttribute:(NSLayoutAttribute)layoutAttribute; /** * The designated initializer. */ - (id)initWithView:(MAS_VIEW *)view item:(id)item layoutAttribute:(NSLayoutAttribute)layoutAttribute; /** * Determine whether the layoutAttribute is a size attribute * * @return YES if layoutAttribute is equal to NSLayoutAttributeWidth or NSLayoutAttributeHeight */ - (BOOL)isSizeAttribute; @end ================================================ FILE: Example/Pods/Masonry/Masonry/MASViewAttribute.m ================================================ // // MASViewAttribute.m // Masonry // // Created by Jonas Budelmann on 21/07/13. // Copyright (c) 2013 cloudling. All rights reserved. // #import "MASViewAttribute.h" @implementation MASViewAttribute - (id)initWithView:(MAS_VIEW *)view layoutAttribute:(NSLayoutAttribute)layoutAttribute { self = [self initWithView:view item:view layoutAttribute:layoutAttribute]; return self; } - (id)initWithView:(MAS_VIEW *)view item:(id)item layoutAttribute:(NSLayoutAttribute)layoutAttribute { self = [super init]; if (!self) return nil; _view = view; _item = item; _layoutAttribute = layoutAttribute; return self; } - (BOOL)isSizeAttribute { return self.layoutAttribute == NSLayoutAttributeWidth || self.layoutAttribute == NSLayoutAttributeHeight; } - (BOOL)isEqual:(MASViewAttribute *)viewAttribute { if ([viewAttribute isKindOfClass:self.class]) { return self.view == viewAttribute.view && self.layoutAttribute == viewAttribute.layoutAttribute; } return [super isEqual:viewAttribute]; } - (NSUInteger)hash { return MAS_NSUINTROTATE([self.view hash], MAS_NSUINT_BIT / 2) ^ self.layoutAttribute; } @end ================================================ FILE: Example/Pods/Masonry/Masonry/MASViewConstraint.h ================================================ // // MASViewConstraint.h // Masonry // // Created by Jonas Budelmann on 20/07/13. // Copyright (c) 2013 cloudling. All rights reserved. // #import "MASViewAttribute.h" #import "MASConstraint.h" #import "MASLayoutConstraint.h" #import "MASUtilities.h" /** * A single constraint. * Contains the attributes neccessary for creating a NSLayoutConstraint and adding it to the appropriate view */ @interface MASViewConstraint : MASConstraint /** * First item/view and first attribute of the NSLayoutConstraint */ @property (nonatomic, strong, readonly) MASViewAttribute *firstViewAttribute; /** * Second item/view and second attribute of the NSLayoutConstraint */ @property (nonatomic, strong, readonly) MASViewAttribute *secondViewAttribute; /** * initialises the MASViewConstraint with the first part of the equation * * @param firstViewAttribute view.mas_left, view.mas_width etc. * * @return a new view constraint */ - (id)initWithFirstViewAttribute:(MASViewAttribute *)firstViewAttribute; /** * Returns all MASViewConstraints installed with this view as a first item. * * @param view A view to retrieve constraints for. * * @return An array of MASViewConstraints. */ + (NSArray *)installedConstraintsForView:(MAS_VIEW *)view; @end ================================================ FILE: Example/Pods/Masonry/Masonry/MASViewConstraint.m ================================================ // // MASViewConstraint.m // Masonry // // Created by Jonas Budelmann on 20/07/13. // Copyright (c) 2013 cloudling. All rights reserved. // #import "MASViewConstraint.h" #import "MASConstraint+Private.h" #import "MASCompositeConstraint.h" #import "MASLayoutConstraint.h" #import "View+MASAdditions.h" #import @interface MAS_VIEW (MASConstraints) @property (nonatomic, readonly) NSMutableSet *mas_installedConstraints; @end @implementation MAS_VIEW (MASConstraints) static char kInstalledConstraintsKey; - (NSMutableSet *)mas_installedConstraints { NSMutableSet *constraints = objc_getAssociatedObject(self, &kInstalledConstraintsKey); if (!constraints) { constraints = [NSMutableSet set]; objc_setAssociatedObject(self, &kInstalledConstraintsKey, constraints, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } return constraints; } @end @interface MASViewConstraint () @property (nonatomic, strong, readwrite) MASViewAttribute *secondViewAttribute; @property (nonatomic, weak) MAS_VIEW *installedView; @property (nonatomic, weak) MASLayoutConstraint *layoutConstraint; @property (nonatomic, assign) NSLayoutRelation layoutRelation; @property (nonatomic, assign) MASLayoutPriority layoutPriority; @property (nonatomic, assign) CGFloat layoutMultiplier; @property (nonatomic, assign) CGFloat layoutConstant; @property (nonatomic, assign) BOOL hasLayoutRelation; @property (nonatomic, strong) id mas_key; @property (nonatomic, assign) BOOL useAnimator; @end @implementation MASViewConstraint - (id)initWithFirstViewAttribute:(MASViewAttribute *)firstViewAttribute { self = [super init]; if (!self) return nil; _firstViewAttribute = firstViewAttribute; self.layoutPriority = MASLayoutPriorityRequired; self.layoutMultiplier = 1; return self; } #pragma mark - NSCoping - (id)copyWithZone:(NSZone __unused *)zone { MASViewConstraint *constraint = [[MASViewConstraint alloc] initWithFirstViewAttribute:self.firstViewAttribute]; constraint.layoutConstant = self.layoutConstant; constraint.layoutRelation = self.layoutRelation; constraint.layoutPriority = self.layoutPriority; constraint.layoutMultiplier = self.layoutMultiplier; constraint.delegate = self.delegate; return constraint; } #pragma mark - Public + (NSArray *)installedConstraintsForView:(MAS_VIEW *)view { return [view.mas_installedConstraints allObjects]; } #pragma mark - Private - (void)setLayoutConstant:(CGFloat)layoutConstant { _layoutConstant = layoutConstant; #if TARGET_OS_MAC && !(TARGET_OS_IPHONE || TARGET_OS_TV) if (self.useAnimator) { [self.layoutConstraint.animator setConstant:layoutConstant]; } else { self.layoutConstraint.constant = layoutConstant; } #else self.layoutConstraint.constant = layoutConstant; #endif } - (void)setLayoutRelation:(NSLayoutRelation)layoutRelation { _layoutRelation = layoutRelation; self.hasLayoutRelation = YES; } - (BOOL)supportsActiveProperty { return [self.layoutConstraint respondsToSelector:@selector(isActive)]; } - (BOOL)isActive { BOOL active = YES; if ([self supportsActiveProperty]) { active = [self.layoutConstraint isActive]; } return active; } - (BOOL)hasBeenInstalled { return (self.layoutConstraint != nil) && [self isActive]; } - (void)setSecondViewAttribute:(id)secondViewAttribute { if ([secondViewAttribute isKindOfClass:NSValue.class]) { [self setLayoutConstantWithValue:secondViewAttribute]; } else if ([secondViewAttribute isKindOfClass:MAS_VIEW.class]) { _secondViewAttribute = [[MASViewAttribute alloc] initWithView:secondViewAttribute layoutAttribute:self.firstViewAttribute.layoutAttribute]; } else if ([secondViewAttribute isKindOfClass:MASViewAttribute.class]) { _secondViewAttribute = secondViewAttribute; } else { NSAssert(NO, @"attempting to add unsupported attribute: %@", secondViewAttribute); } } #pragma mark - NSLayoutConstraint multiplier proxies - (MASConstraint * (^)(CGFloat))multipliedBy { return ^id(CGFloat multiplier) { NSAssert(!self.hasBeenInstalled, @"Cannot modify constraint multiplier after it has been installed"); self.layoutMultiplier = multiplier; return self; }; } - (MASConstraint * (^)(CGFloat))dividedBy { return ^id(CGFloat divider) { NSAssert(!self.hasBeenInstalled, @"Cannot modify constraint multiplier after it has been installed"); self.layoutMultiplier = 1.0/divider; return self; }; } #pragma mark - MASLayoutPriority proxy - (MASConstraint * (^)(MASLayoutPriority))priority { return ^id(MASLayoutPriority priority) { NSAssert(!self.hasBeenInstalled, @"Cannot modify constraint priority after it has been installed"); self.layoutPriority = priority; return self; }; } #pragma mark - NSLayoutRelation proxy - (MASConstraint * (^)(id, NSLayoutRelation))equalToWithRelation { return ^id(id attribute, NSLayoutRelation relation) { if ([attribute isKindOfClass:NSArray.class]) { NSAssert(!self.hasLayoutRelation, @"Redefinition of constraint relation"); NSMutableArray *children = NSMutableArray.new; for (id attr in attribute) { MASViewConstraint *viewConstraint = [self copy]; viewConstraint.layoutRelation = relation; viewConstraint.secondViewAttribute = attr; [children addObject:viewConstraint]; } MASCompositeConstraint *compositeConstraint = [[MASCompositeConstraint alloc] initWithChildren:children]; compositeConstraint.delegate = self.delegate; [self.delegate constraint:self shouldBeReplacedWithConstraint:compositeConstraint]; return compositeConstraint; } else { NSAssert(!self.hasLayoutRelation || self.layoutRelation == relation && [attribute isKindOfClass:NSValue.class], @"Redefinition of constraint relation"); self.layoutRelation = relation; self.secondViewAttribute = attribute; return self; } }; } #pragma mark - Semantic properties - (MASConstraint *)with { return self; } - (MASConstraint *)and { return self; } #pragma mark - attribute chaining - (MASConstraint *)addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute { NSAssert(!self.hasLayoutRelation, @"Attributes should be chained before defining the constraint relation"); return [self.delegate constraint:self addConstraintWithLayoutAttribute:layoutAttribute]; } #pragma mark - Animator proxy #if TARGET_OS_MAC && !(TARGET_OS_IPHONE || TARGET_OS_TV) - (MASConstraint *)animator { self.useAnimator = YES; return self; } #endif #pragma mark - debug helpers - (MASConstraint * (^)(id))key { return ^id(id key) { self.mas_key = key; return self; }; } #pragma mark - NSLayoutConstraint constant setters - (void)setInsets:(MASEdgeInsets)insets { NSLayoutAttribute layoutAttribute = self.firstViewAttribute.layoutAttribute; switch (layoutAttribute) { case NSLayoutAttributeLeft: case NSLayoutAttributeLeading: self.layoutConstant = insets.left; break; case NSLayoutAttributeTop: self.layoutConstant = insets.top; break; case NSLayoutAttributeBottom: self.layoutConstant = -insets.bottom; break; case NSLayoutAttributeRight: case NSLayoutAttributeTrailing: self.layoutConstant = -insets.right; break; default: break; } } - (void)setInset:(CGFloat)inset { [self setInsets:(MASEdgeInsets){.top = inset, .left = inset, .bottom = inset, .right = inset}]; } - (void)setOffset:(CGFloat)offset { self.layoutConstant = offset; } - (void)setSizeOffset:(CGSize)sizeOffset { NSLayoutAttribute layoutAttribute = self.firstViewAttribute.layoutAttribute; switch (layoutAttribute) { case NSLayoutAttributeWidth: self.layoutConstant = sizeOffset.width; break; case NSLayoutAttributeHeight: self.layoutConstant = sizeOffset.height; break; default: break; } } - (void)setCenterOffset:(CGPoint)centerOffset { NSLayoutAttribute layoutAttribute = self.firstViewAttribute.layoutAttribute; switch (layoutAttribute) { case NSLayoutAttributeCenterX: self.layoutConstant = centerOffset.x; break; case NSLayoutAttributeCenterY: self.layoutConstant = centerOffset.y; break; default: break; } } #pragma mark - MASConstraint - (void)activate { [self install]; } - (void)deactivate { [self uninstall]; } - (void)install { if (self.hasBeenInstalled) { return; } if ([self supportsActiveProperty] && self.layoutConstraint) { self.layoutConstraint.active = YES; [self.firstViewAttribute.view.mas_installedConstraints addObject:self]; return; } MAS_VIEW *firstLayoutItem = self.firstViewAttribute.item; NSLayoutAttribute firstLayoutAttribute = self.firstViewAttribute.layoutAttribute; MAS_VIEW *secondLayoutItem = self.secondViewAttribute.item; NSLayoutAttribute secondLayoutAttribute = self.secondViewAttribute.layoutAttribute; // alignment attributes must have a secondViewAttribute // therefore we assume that is refering to superview // eg make.left.equalTo(@10) if (!self.firstViewAttribute.isSizeAttribute && !self.secondViewAttribute) { secondLayoutItem = self.firstViewAttribute.view.superview; secondLayoutAttribute = firstLayoutAttribute; } MASLayoutConstraint *layoutConstraint = [MASLayoutConstraint constraintWithItem:firstLayoutItem attribute:firstLayoutAttribute relatedBy:self.layoutRelation toItem:secondLayoutItem attribute:secondLayoutAttribute multiplier:self.layoutMultiplier constant:self.layoutConstant]; layoutConstraint.priority = self.layoutPriority; layoutConstraint.mas_key = self.mas_key; if (self.secondViewAttribute.view) { MAS_VIEW *closestCommonSuperview = [self.firstViewAttribute.view mas_closestCommonSuperview:self.secondViewAttribute.view]; NSAssert(closestCommonSuperview, @"couldn't find a common superview for %@ and %@", self.firstViewAttribute.view, self.secondViewAttribute.view); self.installedView = closestCommonSuperview; } else if (self.firstViewAttribute.isSizeAttribute) { self.installedView = self.firstViewAttribute.view; } else { self.installedView = self.firstViewAttribute.view.superview; } MASLayoutConstraint *existingConstraint = nil; if (self.updateExisting) { existingConstraint = [self layoutConstraintSimilarTo:layoutConstraint]; } if (existingConstraint) { // just update the constant existingConstraint.constant = layoutConstraint.constant; self.layoutConstraint = existingConstraint; } else { [self.installedView addConstraint:layoutConstraint]; self.layoutConstraint = layoutConstraint; [firstLayoutItem.mas_installedConstraints addObject:self]; } } - (MASLayoutConstraint *)layoutConstraintSimilarTo:(MASLayoutConstraint *)layoutConstraint { // check if any constraints are the same apart from the only mutable property constant // go through constraints in reverse as we do not want to match auto-resizing or interface builder constraints // and they are likely to be added first. for (NSLayoutConstraint *existingConstraint in self.installedView.constraints.reverseObjectEnumerator) { if (![existingConstraint isKindOfClass:MASLayoutConstraint.class]) continue; if (existingConstraint.firstItem != layoutConstraint.firstItem) continue; if (existingConstraint.secondItem != layoutConstraint.secondItem) continue; if (existingConstraint.firstAttribute != layoutConstraint.firstAttribute) continue; if (existingConstraint.secondAttribute != layoutConstraint.secondAttribute) continue; if (existingConstraint.relation != layoutConstraint.relation) continue; if (existingConstraint.multiplier != layoutConstraint.multiplier) continue; if (existingConstraint.priority != layoutConstraint.priority) continue; return (id)existingConstraint; } return nil; } - (void)uninstall { if ([self supportsActiveProperty]) { self.layoutConstraint.active = NO; [self.firstViewAttribute.view.mas_installedConstraints removeObject:self]; return; } [self.installedView removeConstraint:self.layoutConstraint]; self.layoutConstraint = nil; self.installedView = nil; [self.firstViewAttribute.view.mas_installedConstraints removeObject:self]; } @end ================================================ FILE: Example/Pods/Masonry/Masonry/Masonry.h ================================================ // // Masonry.h // Masonry // // Created by Jonas Budelmann on 20/07/13. // Copyright (c) 2013 cloudling. All rights reserved. // #import //! Project version number for Masonry. FOUNDATION_EXPORT double MasonryVersionNumber; //! Project version string for Masonry. FOUNDATION_EXPORT const unsigned char MasonryVersionString[]; #import "MASUtilities.h" #import "View+MASAdditions.h" #import "View+MASShorthandAdditions.h" #import "ViewController+MASAdditions.h" #import "NSArray+MASAdditions.h" #import "NSArray+MASShorthandAdditions.h" #import "MASConstraint.h" #import "MASCompositeConstraint.h" #import "MASViewAttribute.h" #import "MASViewConstraint.h" #import "MASConstraintMaker.h" #import "MASLayoutConstraint.h" #import "NSLayoutConstraint+MASDebugAdditions.h" ================================================ FILE: Example/Pods/Masonry/Masonry/NSArray+MASAdditions.h ================================================ // // NSArray+MASAdditions.h // // // Created by Daniel Hammond on 11/26/13. // // #import "MASUtilities.h" #import "MASConstraintMaker.h" #import "MASViewAttribute.h" typedef NS_ENUM(NSUInteger, MASAxisType) { MASAxisTypeHorizontal, MASAxisTypeVertical }; @interface NSArray (MASAdditions) /** * Creates a MASConstraintMaker with each view in the callee. * Any constraints defined are added to the view or the appropriate superview once the block has finished executing on each view * * @param block scope within which you can build up the constraints which you wish to apply to each view. * * @return Array of created MASConstraints */ - (NSArray *)mas_makeConstraints:(void (NS_NOESCAPE ^)(MASConstraintMaker *make))block; /** * Creates a MASConstraintMaker with each view in the callee. * Any constraints defined are added to each view or the appropriate superview once the block has finished executing on each view. * If an existing constraint exists then it will be updated instead. * * @param block scope within which you can build up the constraints which you wish to apply to each view. * * @return Array of created/updated MASConstraints */ - (NSArray *)mas_updateConstraints:(void (NS_NOESCAPE ^)(MASConstraintMaker *make))block; /** * Creates a MASConstraintMaker with each view in the callee. * Any constraints defined are added to each view or the appropriate superview once the block has finished executing on each view. * All constraints previously installed for the views will be removed. * * @param block scope within which you can build up the constraints which you wish to apply to each view. * * @return Array of created/updated MASConstraints */ - (NSArray *)mas_remakeConstraints:(void (NS_NOESCAPE ^)(MASConstraintMaker *make))block; /** * distribute with fixed spacing * * @param axisType which axis to distribute items along * @param fixedSpacing the spacing between each item * @param leadSpacing the spacing before the first item and the container * @param tailSpacing the spacing after the last item and the container */ - (void)mas_distributeViewsAlongAxis:(MASAxisType)axisType withFixedSpacing:(CGFloat)fixedSpacing leadSpacing:(CGFloat)leadSpacing tailSpacing:(CGFloat)tailSpacing; /** * distribute with fixed item size * * @param axisType which axis to distribute items along * @param fixedItemLength the fixed length of each item * @param leadSpacing the spacing before the first item and the container * @param tailSpacing the spacing after the last item and the container */ - (void)mas_distributeViewsAlongAxis:(MASAxisType)axisType withFixedItemLength:(CGFloat)fixedItemLength leadSpacing:(CGFloat)leadSpacing tailSpacing:(CGFloat)tailSpacing; @end ================================================ FILE: Example/Pods/Masonry/Masonry/NSArray+MASAdditions.m ================================================ // // NSArray+MASAdditions.m // // // Created by Daniel Hammond on 11/26/13. // // #import "NSArray+MASAdditions.h" #import "View+MASAdditions.h" @implementation NSArray (MASAdditions) - (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *make))block { NSMutableArray *constraints = [NSMutableArray array]; for (MAS_VIEW *view in self) { NSAssert([view isKindOfClass:[MAS_VIEW class]], @"All objects in the array must be views"); [constraints addObjectsFromArray:[view mas_makeConstraints:block]]; } return constraints; } - (NSArray *)mas_updateConstraints:(void(^)(MASConstraintMaker *make))block { NSMutableArray *constraints = [NSMutableArray array]; for (MAS_VIEW *view in self) { NSAssert([view isKindOfClass:[MAS_VIEW class]], @"All objects in the array must be views"); [constraints addObjectsFromArray:[view mas_updateConstraints:block]]; } return constraints; } - (NSArray *)mas_remakeConstraints:(void(^)(MASConstraintMaker *make))block { NSMutableArray *constraints = [NSMutableArray array]; for (MAS_VIEW *view in self) { NSAssert([view isKindOfClass:[MAS_VIEW class]], @"All objects in the array must be views"); [constraints addObjectsFromArray:[view mas_remakeConstraints:block]]; } return constraints; } - (void)mas_distributeViewsAlongAxis:(MASAxisType)axisType withFixedSpacing:(CGFloat)fixedSpacing leadSpacing:(CGFloat)leadSpacing tailSpacing:(CGFloat)tailSpacing { if (self.count < 2) { NSAssert(self.count>1,@"views to distribute need to bigger than one"); return; } MAS_VIEW *tempSuperView = [self mas_commonSuperviewOfViews]; if (axisType == MASAxisTypeHorizontal) { MAS_VIEW *prev; for (int i = 0; i < self.count; i++) { MAS_VIEW *v = self[i]; [v mas_makeConstraints:^(MASConstraintMaker *make) { if (prev) { make.width.equalTo(prev); make.left.equalTo(prev.mas_right).offset(fixedSpacing); if (i == self.count - 1) {//last one make.right.equalTo(tempSuperView).offset(-tailSpacing); } } else {//first one make.left.equalTo(tempSuperView).offset(leadSpacing); } }]; prev = v; } } else { MAS_VIEW *prev; for (int i = 0; i < self.count; i++) { MAS_VIEW *v = self[i]; [v mas_makeConstraints:^(MASConstraintMaker *make) { if (prev) { make.height.equalTo(prev); make.top.equalTo(prev.mas_bottom).offset(fixedSpacing); if (i == self.count - 1) {//last one make.bottom.equalTo(tempSuperView).offset(-tailSpacing); } } else {//first one make.top.equalTo(tempSuperView).offset(leadSpacing); } }]; prev = v; } } } - (void)mas_distributeViewsAlongAxis:(MASAxisType)axisType withFixedItemLength:(CGFloat)fixedItemLength leadSpacing:(CGFloat)leadSpacing tailSpacing:(CGFloat)tailSpacing { if (self.count < 2) { NSAssert(self.count>1,@"views to distribute need to bigger than one"); return; } MAS_VIEW *tempSuperView = [self mas_commonSuperviewOfViews]; if (axisType == MASAxisTypeHorizontal) { MAS_VIEW *prev; for (int i = 0; i < self.count; i++) { MAS_VIEW *v = self[i]; [v mas_makeConstraints:^(MASConstraintMaker *make) { make.width.equalTo(@(fixedItemLength)); if (prev) { if (i == self.count - 1) {//last one make.right.equalTo(tempSuperView).offset(-tailSpacing); } else { CGFloat offset = (1-(i/((CGFloat)self.count-1)))*(fixedItemLength+leadSpacing)-i*tailSpacing/(((CGFloat)self.count-1)); make.right.equalTo(tempSuperView).multipliedBy(i/((CGFloat)self.count-1)).with.offset(offset); } } else {//first one make.left.equalTo(tempSuperView).offset(leadSpacing); } }]; prev = v; } } else { MAS_VIEW *prev; for (int i = 0; i < self.count; i++) { MAS_VIEW *v = self[i]; [v mas_makeConstraints:^(MASConstraintMaker *make) { make.height.equalTo(@(fixedItemLength)); if (prev) { if (i == self.count - 1) {//last one make.bottom.equalTo(tempSuperView).offset(-tailSpacing); } else { CGFloat offset = (1-(i/((CGFloat)self.count-1)))*(fixedItemLength+leadSpacing)-i*tailSpacing/(((CGFloat)self.count-1)); make.bottom.equalTo(tempSuperView).multipliedBy(i/((CGFloat)self.count-1)).with.offset(offset); } } else {//first one make.top.equalTo(tempSuperView).offset(leadSpacing); } }]; prev = v; } } } - (MAS_VIEW *)mas_commonSuperviewOfViews { MAS_VIEW *commonSuperview = nil; MAS_VIEW *previousView = nil; for (id object in self) { if ([object isKindOfClass:[MAS_VIEW class]]) { MAS_VIEW *view = (MAS_VIEW *)object; if (previousView) { commonSuperview = [view mas_closestCommonSuperview:commonSuperview]; } else { commonSuperview = view; } previousView = view; } } NSAssert(commonSuperview, @"Can't constrain views that do not share a common superview. Make sure that all the views in this array have been added into the same view hierarchy."); return commonSuperview; } @end ================================================ FILE: Example/Pods/Masonry/Masonry/NSArray+MASShorthandAdditions.h ================================================ // // NSArray+MASShorthandAdditions.h // Masonry // // Created by Jonas Budelmann on 22/07/13. // Copyright (c) 2013 Jonas Budelmann. All rights reserved. // #import "NSArray+MASAdditions.h" #ifdef MAS_SHORTHAND /** * Shorthand array additions without the 'mas_' prefixes, * only enabled if MAS_SHORTHAND is defined */ @interface NSArray (MASShorthandAdditions) - (NSArray *)makeConstraints:(void(^)(MASConstraintMaker *make))block; - (NSArray *)updateConstraints:(void(^)(MASConstraintMaker *make))block; - (NSArray *)remakeConstraints:(void(^)(MASConstraintMaker *make))block; @end @implementation NSArray (MASShorthandAdditions) - (NSArray *)makeConstraints:(void(^)(MASConstraintMaker *))block { return [self mas_makeConstraints:block]; } - (NSArray *)updateConstraints:(void(^)(MASConstraintMaker *))block { return [self mas_updateConstraints:block]; } - (NSArray *)remakeConstraints:(void(^)(MASConstraintMaker *))block { return [self mas_remakeConstraints:block]; } @end #endif ================================================ FILE: Example/Pods/Masonry/Masonry/NSLayoutConstraint+MASDebugAdditions.h ================================================ // // NSLayoutConstraint+MASDebugAdditions.h // Masonry // // Created by Jonas Budelmann on 3/08/13. // Copyright (c) 2013 Jonas Budelmann. All rights reserved. // #import "MASUtilities.h" /** * makes debug and log output of NSLayoutConstraints more readable */ @interface NSLayoutConstraint (MASDebugAdditions) @end ================================================ FILE: Example/Pods/Masonry/Masonry/NSLayoutConstraint+MASDebugAdditions.m ================================================ // // NSLayoutConstraint+MASDebugAdditions.m // Masonry // // Created by Jonas Budelmann on 3/08/13. // Copyright (c) 2013 Jonas Budelmann. All rights reserved. // #import "NSLayoutConstraint+MASDebugAdditions.h" #import "MASConstraint.h" #import "MASLayoutConstraint.h" @implementation NSLayoutConstraint (MASDebugAdditions) #pragma mark - description maps + (NSDictionary *)layoutRelationDescriptionsByValue { static dispatch_once_t once; static NSDictionary *descriptionMap; dispatch_once(&once, ^{ descriptionMap = @{ @(NSLayoutRelationEqual) : @"==", @(NSLayoutRelationGreaterThanOrEqual) : @">=", @(NSLayoutRelationLessThanOrEqual) : @"<=", }; }); return descriptionMap; } + (NSDictionary *)layoutAttributeDescriptionsByValue { static dispatch_once_t once; static NSDictionary *descriptionMap; dispatch_once(&once, ^{ descriptionMap = @{ @(NSLayoutAttributeTop) : @"top", @(NSLayoutAttributeLeft) : @"left", @(NSLayoutAttributeBottom) : @"bottom", @(NSLayoutAttributeRight) : @"right", @(NSLayoutAttributeLeading) : @"leading", @(NSLayoutAttributeTrailing) : @"trailing", @(NSLayoutAttributeWidth) : @"width", @(NSLayoutAttributeHeight) : @"height", @(NSLayoutAttributeCenterX) : @"centerX", @(NSLayoutAttributeCenterY) : @"centerY", @(NSLayoutAttributeBaseline) : @"baseline", #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) @(NSLayoutAttributeFirstBaseline) : @"firstBaseline", @(NSLayoutAttributeLastBaseline) : @"lastBaseline", #endif #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) @(NSLayoutAttributeLeftMargin) : @"leftMargin", @(NSLayoutAttributeRightMargin) : @"rightMargin", @(NSLayoutAttributeTopMargin) : @"topMargin", @(NSLayoutAttributeBottomMargin) : @"bottomMargin", @(NSLayoutAttributeLeadingMargin) : @"leadingMargin", @(NSLayoutAttributeTrailingMargin) : @"trailingMargin", @(NSLayoutAttributeCenterXWithinMargins) : @"centerXWithinMargins", @(NSLayoutAttributeCenterYWithinMargins) : @"centerYWithinMargins", #endif }; }); return descriptionMap; } + (NSDictionary *)layoutPriorityDescriptionsByValue { static dispatch_once_t once; static NSDictionary *descriptionMap; dispatch_once(&once, ^{ #if TARGET_OS_IPHONE || TARGET_OS_TV descriptionMap = @{ @(MASLayoutPriorityDefaultHigh) : @"high", @(MASLayoutPriorityDefaultLow) : @"low", @(MASLayoutPriorityDefaultMedium) : @"medium", @(MASLayoutPriorityRequired) : @"required", @(MASLayoutPriorityFittingSizeLevel) : @"fitting size", }; #elif TARGET_OS_MAC descriptionMap = @{ @(MASLayoutPriorityDefaultHigh) : @"high", @(MASLayoutPriorityDragThatCanResizeWindow) : @"drag can resize window", @(MASLayoutPriorityDefaultMedium) : @"medium", @(MASLayoutPriorityWindowSizeStayPut) : @"window size stay put", @(MASLayoutPriorityDragThatCannotResizeWindow) : @"drag cannot resize window", @(MASLayoutPriorityDefaultLow) : @"low", @(MASLayoutPriorityFittingSizeCompression) : @"fitting size", @(MASLayoutPriorityRequired) : @"required", }; #endif }); return descriptionMap; } #pragma mark - description override + (NSString *)descriptionForObject:(id)obj { if ([obj respondsToSelector:@selector(mas_key)] && [obj mas_key]) { return [NSString stringWithFormat:@"%@:%@", [obj class], [obj mas_key]]; } return [NSString stringWithFormat:@"%@:%p", [obj class], obj]; } - (NSString *)description { NSMutableString *description = [[NSMutableString alloc] initWithString:@"<"]; [description appendString:[self.class descriptionForObject:self]]; [description appendFormat:@" %@", [self.class descriptionForObject:self.firstItem]]; if (self.firstAttribute != NSLayoutAttributeNotAnAttribute) { [description appendFormat:@".%@", self.class.layoutAttributeDescriptionsByValue[@(self.firstAttribute)]]; } [description appendFormat:@" %@", self.class.layoutRelationDescriptionsByValue[@(self.relation)]]; if (self.secondItem) { [description appendFormat:@" %@", [self.class descriptionForObject:self.secondItem]]; } if (self.secondAttribute != NSLayoutAttributeNotAnAttribute) { [description appendFormat:@".%@", self.class.layoutAttributeDescriptionsByValue[@(self.secondAttribute)]]; } if (self.multiplier != 1) { [description appendFormat:@" * %g", self.multiplier]; } if (self.secondAttribute == NSLayoutAttributeNotAnAttribute) { [description appendFormat:@" %g", self.constant]; } else { if (self.constant) { [description appendFormat:@" %@ %g", (self.constant < 0 ? @"-" : @"+"), ABS(self.constant)]; } } if (self.priority != MASLayoutPriorityRequired) { [description appendFormat:@" ^%@", self.class.layoutPriorityDescriptionsByValue[@(self.priority)] ?: [NSNumber numberWithDouble:self.priority]]; } [description appendString:@">"]; return description; } @end ================================================ FILE: Example/Pods/Masonry/Masonry/View+MASAdditions.h ================================================ // // UIView+MASAdditions.h // Masonry // // Created by Jonas Budelmann on 20/07/13. // Copyright (c) 2013 cloudling. All rights reserved. // #import "MASUtilities.h" #import "MASConstraintMaker.h" #import "MASViewAttribute.h" /** * Provides constraint maker block * and convience methods for creating MASViewAttribute which are view + NSLayoutAttribute pairs */ @interface MAS_VIEW (MASAdditions) /** * following properties return a new MASViewAttribute with current view and appropriate NSLayoutAttribute */ @property (nonatomic, strong, readonly) MASViewAttribute *mas_left; @property (nonatomic, strong, readonly) MASViewAttribute *mas_top; @property (nonatomic, strong, readonly) MASViewAttribute *mas_right; @property (nonatomic, strong, readonly) MASViewAttribute *mas_bottom; @property (nonatomic, strong, readonly) MASViewAttribute *mas_leading; @property (nonatomic, strong, readonly) MASViewAttribute *mas_trailing; @property (nonatomic, strong, readonly) MASViewAttribute *mas_width; @property (nonatomic, strong, readonly) MASViewAttribute *mas_height; @property (nonatomic, strong, readonly) MASViewAttribute *mas_centerX; @property (nonatomic, strong, readonly) MASViewAttribute *mas_centerY; @property (nonatomic, strong, readonly) MASViewAttribute *mas_baseline; @property (nonatomic, strong, readonly) MASViewAttribute *(^mas_attribute)(NSLayoutAttribute attr); #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) @property (nonatomic, strong, readonly) MASViewAttribute *mas_firstBaseline; @property (nonatomic, strong, readonly) MASViewAttribute *mas_lastBaseline; #endif #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) @property (nonatomic, strong, readonly) MASViewAttribute *mas_leftMargin; @property (nonatomic, strong, readonly) MASViewAttribute *mas_rightMargin; @property (nonatomic, strong, readonly) MASViewAttribute *mas_topMargin; @property (nonatomic, strong, readonly) MASViewAttribute *mas_bottomMargin; @property (nonatomic, strong, readonly) MASViewAttribute *mas_leadingMargin; @property (nonatomic, strong, readonly) MASViewAttribute *mas_trailingMargin; @property (nonatomic, strong, readonly) MASViewAttribute *mas_centerXWithinMargins; @property (nonatomic, strong, readonly) MASViewAttribute *mas_centerYWithinMargins; #endif #if (__IPHONE_OS_VERSION_MAX_ALLOWED >= 110000) || (__TV_OS_VERSION_MAX_ALLOWED >= 110000) @property (nonatomic, strong, readonly) MASViewAttribute *mas_safeAreaLayoutGuide API_AVAILABLE(ios(11.0),tvos(11.0)); @property (nonatomic, strong, readonly) MASViewAttribute *mas_safeAreaLayoutGuideTop API_AVAILABLE(ios(11.0),tvos(11.0)); @property (nonatomic, strong, readonly) MASViewAttribute *mas_safeAreaLayoutGuideBottom API_AVAILABLE(ios(11.0),tvos(11.0)); @property (nonatomic, strong, readonly) MASViewAttribute *mas_safeAreaLayoutGuideLeft API_AVAILABLE(ios(11.0),tvos(11.0)); @property (nonatomic, strong, readonly) MASViewAttribute *mas_safeAreaLayoutGuideRight API_AVAILABLE(ios(11.0),tvos(11.0)); #endif /** * a key to associate with this view */ @property (nonatomic, strong) id mas_key; /** * Finds the closest common superview between this view and another view * * @param view other view * * @return returns nil if common superview could not be found */ - (instancetype)mas_closestCommonSuperview:(MAS_VIEW *)view; /** * Creates a MASConstraintMaker with the callee view. * Any constraints defined are added to the view or the appropriate superview once the block has finished executing * * @param block scope within which you can build up the constraints which you wish to apply to the view. * * @return Array of created MASConstraints */ - (NSArray *)mas_makeConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *make))block; /** * Creates a MASConstraintMaker with the callee view. * Any constraints defined are added to the view or the appropriate superview once the block has finished executing. * If an existing constraint exists then it will be updated instead. * * @param block scope within which you can build up the constraints which you wish to apply to the view. * * @return Array of created/updated MASConstraints */ - (NSArray *)mas_updateConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *make))block; /** * Creates a MASConstraintMaker with the callee view. * Any constraints defined are added to the view or the appropriate superview once the block has finished executing. * All constraints previously installed for the view will be removed. * * @param block scope within which you can build up the constraints which you wish to apply to the view. * * @return Array of created/updated MASConstraints */ - (NSArray *)mas_remakeConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *make))block; @end ================================================ FILE: Example/Pods/Masonry/Masonry/View+MASAdditions.m ================================================ // // UIView+MASAdditions.m // Masonry // // Created by Jonas Budelmann on 20/07/13. // Copyright (c) 2013 cloudling. All rights reserved. // #import "View+MASAdditions.h" #import @implementation MAS_VIEW (MASAdditions) - (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *))block { self.translatesAutoresizingMaskIntoConstraints = NO; MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self]; block(constraintMaker); return [constraintMaker install]; } - (NSArray *)mas_updateConstraints:(void(^)(MASConstraintMaker *))block { self.translatesAutoresizingMaskIntoConstraints = NO; MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self]; constraintMaker.updateExisting = YES; block(constraintMaker); return [constraintMaker install]; } - (NSArray *)mas_remakeConstraints:(void(^)(MASConstraintMaker *make))block { self.translatesAutoresizingMaskIntoConstraints = NO; MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self]; constraintMaker.removeExisting = YES; block(constraintMaker); return [constraintMaker install]; } #pragma mark - NSLayoutAttribute properties - (MASViewAttribute *)mas_left { return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeLeft]; } - (MASViewAttribute *)mas_top { return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeTop]; } - (MASViewAttribute *)mas_right { return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeRight]; } - (MASViewAttribute *)mas_bottom { return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeBottom]; } - (MASViewAttribute *)mas_leading { return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeLeading]; } - (MASViewAttribute *)mas_trailing { return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeTrailing]; } - (MASViewAttribute *)mas_width { return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeWidth]; } - (MASViewAttribute *)mas_height { return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeHeight]; } - (MASViewAttribute *)mas_centerX { return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeCenterX]; } - (MASViewAttribute *)mas_centerY { return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeCenterY]; } - (MASViewAttribute *)mas_baseline { return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeBaseline]; } - (MASViewAttribute *(^)(NSLayoutAttribute))mas_attribute { return ^(NSLayoutAttribute attr) { return [[MASViewAttribute alloc] initWithView:self layoutAttribute:attr]; }; } #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) - (MASViewAttribute *)mas_firstBaseline { return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeFirstBaseline]; } - (MASViewAttribute *)mas_lastBaseline { return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeLastBaseline]; } #endif #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) - (MASViewAttribute *)mas_leftMargin { return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeLeftMargin]; } - (MASViewAttribute *)mas_rightMargin { return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeRightMargin]; } - (MASViewAttribute *)mas_topMargin { return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeTopMargin]; } - (MASViewAttribute *)mas_bottomMargin { return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeBottomMargin]; } - (MASViewAttribute *)mas_leadingMargin { return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeLeadingMargin]; } - (MASViewAttribute *)mas_trailingMargin { return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeTrailingMargin]; } - (MASViewAttribute *)mas_centerXWithinMargins { return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeCenterXWithinMargins]; } - (MASViewAttribute *)mas_centerYWithinMargins { return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeCenterYWithinMargins]; } #endif #if (__IPHONE_OS_VERSION_MAX_ALLOWED >= 110000) || (__TV_OS_VERSION_MAX_ALLOWED >= 110000) - (MASViewAttribute *)mas_safeAreaLayoutGuide { return [[MASViewAttribute alloc] initWithView:self item:self.safeAreaLayoutGuide layoutAttribute:NSLayoutAttributeBottom]; } - (MASViewAttribute *)mas_safeAreaLayoutGuideTop { return [[MASViewAttribute alloc] initWithView:self item:self.safeAreaLayoutGuide layoutAttribute:NSLayoutAttributeTop]; } - (MASViewAttribute *)mas_safeAreaLayoutGuideBottom { return [[MASViewAttribute alloc] initWithView:self item:self.safeAreaLayoutGuide layoutAttribute:NSLayoutAttributeBottom]; } - (MASViewAttribute *)mas_safeAreaLayoutGuideLeft { return [[MASViewAttribute alloc] initWithView:self item:self.safeAreaLayoutGuide layoutAttribute:NSLayoutAttributeLeft]; } - (MASViewAttribute *)mas_safeAreaLayoutGuideRight { return [[MASViewAttribute alloc] initWithView:self item:self.safeAreaLayoutGuide layoutAttribute:NSLayoutAttributeRight]; } #endif #pragma mark - associated properties - (id)mas_key { return objc_getAssociatedObject(self, @selector(mas_key)); } - (void)setMas_key:(id)key { objc_setAssociatedObject(self, @selector(mas_key), key, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } #pragma mark - heirachy - (instancetype)mas_closestCommonSuperview:(MAS_VIEW *)view { MAS_VIEW *closestCommonSuperview = nil; MAS_VIEW *secondViewSuperview = view; while (!closestCommonSuperview && secondViewSuperview) { MAS_VIEW *firstViewSuperview = self; while (!closestCommonSuperview && firstViewSuperview) { if (secondViewSuperview == firstViewSuperview) { closestCommonSuperview = secondViewSuperview; } firstViewSuperview = firstViewSuperview.superview; } secondViewSuperview = secondViewSuperview.superview; } return closestCommonSuperview; } @end ================================================ FILE: Example/Pods/Masonry/Masonry/View+MASShorthandAdditions.h ================================================ // // UIView+MASShorthandAdditions.h // Masonry // // Created by Jonas Budelmann on 22/07/13. // Copyright (c) 2013 Jonas Budelmann. All rights reserved. // #import "View+MASAdditions.h" #ifdef MAS_SHORTHAND /** * Shorthand view additions without the 'mas_' prefixes, * only enabled if MAS_SHORTHAND is defined */ @interface MAS_VIEW (MASShorthandAdditions) @property (nonatomic, strong, readonly) MASViewAttribute *left; @property (nonatomic, strong, readonly) MASViewAttribute *top; @property (nonatomic, strong, readonly) MASViewAttribute *right; @property (nonatomic, strong, readonly) MASViewAttribute *bottom; @property (nonatomic, strong, readonly) MASViewAttribute *leading; @property (nonatomic, strong, readonly) MASViewAttribute *trailing; @property (nonatomic, strong, readonly) MASViewAttribute *width; @property (nonatomic, strong, readonly) MASViewAttribute *height; @property (nonatomic, strong, readonly) MASViewAttribute *centerX; @property (nonatomic, strong, readonly) MASViewAttribute *centerY; @property (nonatomic, strong, readonly) MASViewAttribute *baseline; @property (nonatomic, strong, readonly) MASViewAttribute *(^attribute)(NSLayoutAttribute attr); #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) @property (nonatomic, strong, readonly) MASViewAttribute *firstBaseline; @property (nonatomic, strong, readonly) MASViewAttribute *lastBaseline; #endif #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) @property (nonatomic, strong, readonly) MASViewAttribute *leftMargin; @property (nonatomic, strong, readonly) MASViewAttribute *rightMargin; @property (nonatomic, strong, readonly) MASViewAttribute *topMargin; @property (nonatomic, strong, readonly) MASViewAttribute *bottomMargin; @property (nonatomic, strong, readonly) MASViewAttribute *leadingMargin; @property (nonatomic, strong, readonly) MASViewAttribute *trailingMargin; @property (nonatomic, strong, readonly) MASViewAttribute *centerXWithinMargins; @property (nonatomic, strong, readonly) MASViewAttribute *centerYWithinMargins; #endif #if (__IPHONE_OS_VERSION_MAX_ALLOWED >= 110000) || (__TV_OS_VERSION_MAX_ALLOWED >= 110000) @property (nonatomic, strong, readonly) MASViewAttribute *safeAreaLayoutGuideTop API_AVAILABLE(ios(11.0),tvos(11.0)); @property (nonatomic, strong, readonly) MASViewAttribute *safeAreaLayoutGuideBottom API_AVAILABLE(ios(11.0),tvos(11.0)); @property (nonatomic, strong, readonly) MASViewAttribute *safeAreaLayoutGuideLeft API_AVAILABLE(ios(11.0),tvos(11.0)); @property (nonatomic, strong, readonly) MASViewAttribute *safeAreaLayoutGuideRight API_AVAILABLE(ios(11.0),tvos(11.0)); #endif - (NSArray *)makeConstraints:(void(^)(MASConstraintMaker *make))block; - (NSArray *)updateConstraints:(void(^)(MASConstraintMaker *make))block; - (NSArray *)remakeConstraints:(void(^)(MASConstraintMaker *make))block; @end #define MAS_ATTR_FORWARD(attr) \ - (MASViewAttribute *)attr { \ return [self mas_##attr]; \ } @implementation MAS_VIEW (MASShorthandAdditions) MAS_ATTR_FORWARD(top); MAS_ATTR_FORWARD(left); MAS_ATTR_FORWARD(bottom); MAS_ATTR_FORWARD(right); MAS_ATTR_FORWARD(leading); MAS_ATTR_FORWARD(trailing); MAS_ATTR_FORWARD(width); MAS_ATTR_FORWARD(height); MAS_ATTR_FORWARD(centerX); MAS_ATTR_FORWARD(centerY); MAS_ATTR_FORWARD(baseline); #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) MAS_ATTR_FORWARD(firstBaseline); MAS_ATTR_FORWARD(lastBaseline); #endif #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) MAS_ATTR_FORWARD(leftMargin); MAS_ATTR_FORWARD(rightMargin); MAS_ATTR_FORWARD(topMargin); MAS_ATTR_FORWARD(bottomMargin); MAS_ATTR_FORWARD(leadingMargin); MAS_ATTR_FORWARD(trailingMargin); MAS_ATTR_FORWARD(centerXWithinMargins); MAS_ATTR_FORWARD(centerYWithinMargins); #endif #if (__IPHONE_OS_VERSION_MAX_ALLOWED >= 110000) || (__TV_OS_VERSION_MAX_ALLOWED >= 110000) MAS_ATTR_FORWARD(safeAreaLayoutGuideTop); MAS_ATTR_FORWARD(safeAreaLayoutGuideBottom); MAS_ATTR_FORWARD(safeAreaLayoutGuideLeft); MAS_ATTR_FORWARD(safeAreaLayoutGuideRight); #endif - (MASViewAttribute *(^)(NSLayoutAttribute))attribute { return [self mas_attribute]; } - (NSArray *)makeConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *))block { return [self mas_makeConstraints:block]; } - (NSArray *)updateConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *))block { return [self mas_updateConstraints:block]; } - (NSArray *)remakeConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *))block { return [self mas_remakeConstraints:block]; } @end #endif ================================================ FILE: Example/Pods/Masonry/Masonry/ViewController+MASAdditions.h ================================================ // // UIViewController+MASAdditions.h // Masonry // // Created by Craig Siemens on 2015-06-23. // // #import "MASUtilities.h" #import "MASConstraintMaker.h" #import "MASViewAttribute.h" #ifdef MAS_VIEW_CONTROLLER @interface MAS_VIEW_CONTROLLER (MASAdditions) /** * following properties return a new MASViewAttribute with appropriate UILayoutGuide and NSLayoutAttribute */ @property (nonatomic, strong, readonly) MASViewAttribute *mas_topLayoutGuide; @property (nonatomic, strong, readonly) MASViewAttribute *mas_bottomLayoutGuide; @property (nonatomic, strong, readonly) MASViewAttribute *mas_topLayoutGuideTop; @property (nonatomic, strong, readonly) MASViewAttribute *mas_topLayoutGuideBottom; @property (nonatomic, strong, readonly) MASViewAttribute *mas_bottomLayoutGuideTop; @property (nonatomic, strong, readonly) MASViewAttribute *mas_bottomLayoutGuideBottom; @end #endif ================================================ FILE: Example/Pods/Masonry/Masonry/ViewController+MASAdditions.m ================================================ // // UIViewController+MASAdditions.m // Masonry // // Created by Craig Siemens on 2015-06-23. // // #import "ViewController+MASAdditions.h" #ifdef MAS_VIEW_CONTROLLER @implementation MAS_VIEW_CONTROLLER (MASAdditions) - (MASViewAttribute *)mas_topLayoutGuide { return [[MASViewAttribute alloc] initWithView:self.view item:self.topLayoutGuide layoutAttribute:NSLayoutAttributeBottom]; } - (MASViewAttribute *)mas_topLayoutGuideTop { return [[MASViewAttribute alloc] initWithView:self.view item:self.topLayoutGuide layoutAttribute:NSLayoutAttributeTop]; } - (MASViewAttribute *)mas_topLayoutGuideBottom { return [[MASViewAttribute alloc] initWithView:self.view item:self.topLayoutGuide layoutAttribute:NSLayoutAttributeBottom]; } - (MASViewAttribute *)mas_bottomLayoutGuide { return [[MASViewAttribute alloc] initWithView:self.view item:self.bottomLayoutGuide layoutAttribute:NSLayoutAttributeTop]; } - (MASViewAttribute *)mas_bottomLayoutGuideTop { return [[MASViewAttribute alloc] initWithView:self.view item:self.bottomLayoutGuide layoutAttribute:NSLayoutAttributeTop]; } - (MASViewAttribute *)mas_bottomLayoutGuideBottom { return [[MASViewAttribute alloc] initWithView:self.view item:self.bottomLayoutGuide layoutAttribute:NSLayoutAttributeBottom]; } @end #endif ================================================ FILE: Example/Pods/Masonry/README.md ================================================ # Masonry [![Build Status](https://travis-ci.org/SnapKit/Masonry.svg?branch=master)](https://travis-ci.org/SnapKit/Masonry) [![Coverage Status](https://img.shields.io/coveralls/SnapKit/Masonry.svg?style=flat-square)](https://coveralls.io/r/SnapKit/Masonry) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) ![Pod Version](https://img.shields.io/cocoapods/v/Masonry.svg?style=flat) **Masonry is still actively maintained, we are committed to fixing bugs and merging good quality PRs from the wider community. However if you're using Swift in your project, we recommend using [SnapKit](https://github.com/SnapKit/SnapKit) as it provides better type safety with a simpler API.** Masonry is a light-weight layout framework which wraps AutoLayout with a nicer syntax. Masonry has its own layout DSL which provides a chainable way of describing your NSLayoutConstraints which results in layout code that is more concise and readable. Masonry supports iOS and Mac OS X. For examples take a look at the **Masonry iOS Examples** project in the Masonry workspace. You will need to run `pod install` after downloading. ## What's wrong with NSLayoutConstraints? Under the hood Auto Layout is a powerful and flexible way of organising and laying out your views. However creating constraints from code is verbose and not very descriptive. Imagine a simple example in which you want to have a view fill its superview but inset by 10 pixels on every side ```obj-c UIView *superview = self.view; UIView *view1 = [[UIView alloc] init]; view1.translatesAutoresizingMaskIntoConstraints = NO; view1.backgroundColor = [UIColor greenColor]; [superview addSubview:view1]; UIEdgeInsets padding = UIEdgeInsetsMake(10, 10, 10, 10); [superview addConstraints:@[ //view1 constraints [NSLayoutConstraint constraintWithItem:view1 attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeTop multiplier:1.0 constant:padding.top], [NSLayoutConstraint constraintWithItem:view1 attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeLeft multiplier:1.0 constant:padding.left], [NSLayoutConstraint constraintWithItem:view1 attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-padding.bottom], [NSLayoutConstraint constraintWithItem:view1 attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeRight multiplier:1 constant:-padding.right], ]]; ``` Even with such a simple example the code needed is quite verbose and quickly becomes unreadable when you have more than 2 or 3 views. Another option is to use Visual Format Language (VFL), which is a bit less long winded. However the ASCII type syntax has its own pitfalls and its also a bit harder to animate as `NSLayoutConstraint constraintsWithVisualFormat:` returns an array. ## Prepare to meet your Maker! Heres the same constraints created using MASConstraintMaker ```obj-c UIEdgeInsets padding = UIEdgeInsetsMake(10, 10, 10, 10); [view1 mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(superview.mas_top).with.offset(padding.top); //with is an optional semantic filler make.left.equalTo(superview.mas_left).with.offset(padding.left); make.bottom.equalTo(superview.mas_bottom).with.offset(-padding.bottom); make.right.equalTo(superview.mas_right).with.offset(-padding.right); }]; ``` Or even shorter ```obj-c [view1 mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.equalTo(superview).with.insets(padding); }]; ``` Also note in the first example we had to add the constraints to the superview `[superview addConstraints:...`. Masonry however will automagically add constraints to the appropriate view. Masonry will also call `view1.translatesAutoresizingMaskIntoConstraints = NO;` for you. ## Not all things are created equal > `.equalTo` equivalent to **NSLayoutRelationEqual** > `.lessThanOrEqualTo` equivalent to **NSLayoutRelationLessThanOrEqual** > `.greaterThanOrEqualTo` equivalent to **NSLayoutRelationGreaterThanOrEqual** These three equality constraints accept one argument which can be any of the following: #### 1. MASViewAttribute ```obj-c make.centerX.lessThanOrEqualTo(view2.mas_left); ``` MASViewAttribute | NSLayoutAttribute ------------------------- | -------------------------- view.mas_left | NSLayoutAttributeLeft view.mas_right | NSLayoutAttributeRight view.mas_top | NSLayoutAttributeTop view.mas_bottom | NSLayoutAttributeBottom view.mas_leading | NSLayoutAttributeLeading view.mas_trailing | NSLayoutAttributeTrailing view.mas_width | NSLayoutAttributeWidth view.mas_height | NSLayoutAttributeHeight view.mas_centerX | NSLayoutAttributeCenterX view.mas_centerY | NSLayoutAttributeCenterY view.mas_baseline | NSLayoutAttributeBaseline #### 2. UIView/NSView if you want view.left to be greater than or equal to label.left : ```obj-c //these two constraints are exactly the same make.left.greaterThanOrEqualTo(label); make.left.greaterThanOrEqualTo(label.mas_left); ``` #### 3. NSNumber Auto Layout allows width and height to be set to constant values. if you want to set view to have a minimum and maximum width you could pass a number to the equality blocks: ```obj-c //width >= 200 && width <= 400 make.width.greaterThanOrEqualTo(@200); make.width.lessThanOrEqualTo(@400) ``` However Auto Layout does not allow alignment attributes such as left, right, centerY etc to be set to constant values. So if you pass a NSNumber for these attributes Masonry will turn these into constraints relative to the view’s superview ie: ```obj-c //creates view.left = view.superview.left + 10 make.left.lessThanOrEqualTo(@10) ``` Instead of using NSNumber, you can use primitives and structs to build your constraints, like so: ```obj-c make.top.mas_equalTo(42); make.height.mas_equalTo(20); make.size.mas_equalTo(CGSizeMake(50, 100)); make.edges.mas_equalTo(UIEdgeInsetsMake(10, 0, 10, 0)); make.left.mas_equalTo(view).mas_offset(UIEdgeInsetsMake(10, 0, 10, 0)); ``` By default, macros which support [autoboxing](https://en.wikipedia.org/wiki/Autoboxing#Autoboxing) are prefixed with `mas_`. Unprefixed versions are available by defining `MAS_SHORTHAND_GLOBALS` before importing Masonry. #### 4. NSArray An array of a mixture of any of the previous types ```obj-c make.height.equalTo(@[view1.mas_height, view2.mas_height]); make.height.equalTo(@[view1, view2]); make.left.equalTo(@[view1, @100, view3.right]); ```` ## Learn to prioritize > `.priority` allows you to specify an exact priority > `.priorityHigh` equivalent to **UILayoutPriorityDefaultHigh** > `.priorityMedium` is half way between high and low > `.priorityLow` equivalent to **UILayoutPriorityDefaultLow** Priorities are can be tacked on to the end of a constraint chain like so: ```obj-c make.left.greaterThanOrEqualTo(label.mas_left).with.priorityLow(); make.top.equalTo(label.mas_top).with.priority(600); ``` ## Composition, composition, composition Masonry also gives you a few convenience methods which create multiple constraints at the same time. These are called MASCompositeConstraints #### edges ```obj-c // make top, left, bottom, right equal view2 make.edges.equalTo(view2); // make top = superview.top + 5, left = superview.left + 10, // bottom = superview.bottom - 15, right = superview.right - 20 make.edges.equalTo(superview).insets(UIEdgeInsetsMake(5, 10, 15, 20)) ``` #### size ```obj-c // make width and height greater than or equal to titleLabel make.size.greaterThanOrEqualTo(titleLabel) // make width = superview.width + 100, height = superview.height - 50 make.size.equalTo(superview).sizeOffset(CGSizeMake(100, -50)) ``` #### center ```obj-c // make centerX and centerY = button1 make.center.equalTo(button1) // make centerX = superview.centerX - 5, centerY = superview.centerY + 10 make.center.equalTo(superview).centerOffset(CGPointMake(-5, 10)) ``` You can chain view attributes for increased readability: ```obj-c // All edges but the top should equal those of the superview make.left.right.and.bottom.equalTo(superview); make.top.equalTo(otherView); ``` ## Hold on for dear life Sometimes you need modify existing constraints in order to animate or remove/replace constraints. In Masonry there are a few different approaches to updating constraints. #### 1. References You can hold on to a reference of a particular constraint by assigning the result of a constraint make expression to a local variable or a class property. You could also reference multiple constraints by storing them away in an array. ```obj-c // in public/private interface @property (nonatomic, strong) MASConstraint *topConstraint; ... // when making constraints [view1 mas_makeConstraints:^(MASConstraintMaker *make) { self.topConstraint = make.top.equalTo(superview.mas_top).with.offset(padding.top); make.left.equalTo(superview.mas_left).with.offset(padding.left); }]; ... // then later you can call [self.topConstraint uninstall]; ``` #### 2. mas_updateConstraints Alternatively if you are only updating the constant value of the constraint you can use the convience method `mas_updateConstraints` instead of `mas_makeConstraints` ```obj-c // this is Apple's recommended place for adding/updating constraints // this method can get called multiple times in response to setNeedsUpdateConstraints // which can be called by UIKit internally or in your code if you need to trigger an update to your constraints - (void)updateConstraints { [self.growingButton mas_updateConstraints:^(MASConstraintMaker *make) { make.center.equalTo(self); make.width.equalTo(@(self.buttonSize.width)).priorityLow(); make.height.equalTo(@(self.buttonSize.height)).priorityLow(); make.width.lessThanOrEqualTo(self); make.height.lessThanOrEqualTo(self); }]; //according to apple super should be called at end of method [super updateConstraints]; } ``` ### 3. mas_remakeConstraints `mas_updateConstraints` is useful for updating a set of constraints, but doing anything beyond updating constant values can get exhausting. That's where `mas_remakeConstraints` comes in. `mas_remakeConstraints` is similar to `mas_updateConstraints`, but instead of updating constant values, it will remove all of its constraints before installing them again. This lets you provide different constraints without having to keep around references to ones which you want to remove. ```obj-c - (void)changeButtonPosition { [self.button mas_remakeConstraints:^(MASConstraintMaker *make) { make.size.equalTo(self.buttonSize); if (topLeft) { make.top.and.left.offset(10); } else { make.bottom.and.right.offset(-10); } }]; } ``` You can find more detailed examples of all three approaches in the **Masonry iOS Examples** project. ## When the ^&*!@ hits the fan! Laying out your views doesn't always goto plan. So when things literally go pear shaped, you don't want to be looking at console output like this: ```obj-c Unable to simultaneously satisfy constraints.....blah blah blah.... ( "=5000)]>", "", "", "" ) Will attempt to recover by breaking constraint =5000)]> ``` Masonry adds a category to NSLayoutConstraint which overrides the default implementation of `- (NSString *)description`. Now you can give meaningful names to views and constraints, and also easily pick out the constraints created by Masonry. which means your console output can now look like this: ```obj-c Unable to simultaneously satisfy constraints......blah blah blah.... ( "", "= 5000>", "", "" ) Will attempt to recover by breaking constraint = 5000> ``` For an example of how to set this up take a look at the **Masonry iOS Examples** project in the Masonry workspace. ## Where should I create my constraints? ```objc @implementation DIYCustomView - (id)init { self = [super init]; if (!self) return nil; // --- Create your views here --- self.button = [[UIButton alloc] init]; return self; } // tell UIKit that you are using AutoLayout + (BOOL)requiresConstraintBasedLayout { return YES; } // this is Apple's recommended place for adding/updating constraints - (void)updateConstraints { // --- remake/update constraints here [self.button remakeConstraints:^(MASConstraintMaker *make) { make.width.equalTo(@(self.buttonSize.width)); make.height.equalTo(@(self.buttonSize.height)); }]; //according to apple super should be called at end of method [super updateConstraints]; } - (void)didTapButton:(UIButton *)button { // --- Do your changes ie change variables that affect your layout etc --- self.buttonSize = CGSize(200, 200); // tell constraints they need updating [self setNeedsUpdateConstraints]; } @end ``` ## Installation Use the [orsome](http://www.youtube.com/watch?v=YaIZF8uUTtk) [CocoaPods](http://github.com/CocoaPods/CocoaPods). In your Podfile >`pod 'Masonry'` If you want to use masonry without all those pesky 'mas_' prefixes. Add #define MAS_SHORTHAND to your prefix.pch before importing Masonry >`#define MAS_SHORTHAND` Get busy Masoning >`#import "Masonry.h"` ## Code Snippets Copy the included code snippets to ``~/Library/Developer/Xcode/UserData/CodeSnippets`` to write your masonry blocks at lightning speed! `mas_make` -> ` [<#view#> mas_makeConstraints:^(MASConstraintMaker *make) { <#code#> }];` `mas_update` -> ` [<#view#> mas_updateConstraints:^(MASConstraintMaker *make) { <#code#> }];` `mas_remake` -> ` [<#view#> mas_remakeConstraints:^(MASConstraintMaker *make) { <#code#> }];` ## Features * Not limited to subset of Auto Layout. Anything NSLayoutConstraint can do, Masonry can do too! * Great debug support, give your views and constraints meaningful names. * Constraints read like sentences. * No crazy macro magic. Masonry won't pollute the global namespace with macros. * Not string or dictionary based and hence you get compile time checking. ## TODO * Eye candy * Mac example project * More tests and examples ================================================ FILE: Example/Pods/Pods.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 0036C8E1BBB2FF8C9EC7B0B1AAFD23DF /* FMSupplementary.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A6BACBBBAF66F4EAF255239F54D56EA /* FMSupplementary.h */; settings = {ATTRIBUTES = (Public, ); }; }; 03480CAA966B43707E614B04EF182226 /* FMLayoutFillSection.h in Headers */ = {isa = PBXBuildFile; fileRef = F7950A8B63A4F538F53B4D0165DAAAAE /* FMLayoutFillSection.h */; settings = {ATTRIBUTES = (Public, ); }; }; 05A040F35BF1C88F869404E1A940B493 /* NSArray+MASShorthandAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 27E12E3D2779B5C7A8301A94F715DB4C /* NSArray+MASShorthandAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; 05EA1447EEA0EB669F8DEE73964A7C60 /* NSArray+MASAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 30EC6C5D191587619B42076546EDC448 /* NSArray+MASAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; 0967598607D521318F69D7D39D517B20 /* ViewController+MASAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 342C4D9B5E1E36390E7AF01E35444998 /* ViewController+MASAdditions.m */; }; 098630ECDB64ED7B89F5F687C82B4AC3 /* NSArray+MASAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 8AEEBD88282BA13360CAA867D8465C75 /* NSArray+MASAdditions.m */; }; 0AF1AD35706D90B1A91F291B899EF8C0 /* NSLayoutConstraint+MASDebugAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = E7851906D7976272A721C8C4E0CE9092 /* NSLayoutConstraint+MASDebugAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; 1022317B997FE907CDCD25317B4A071F /* FMLayoutFixedSection.m in Sources */ = {isa = PBXBuildFile; fileRef = AB29189261D660E85FDE41FE16816ECD /* FMLayoutFixedSection.m */; }; 17B1B66CD4133C22EB8356A617AC6D6B /* FMLayoutBackground.h in Headers */ = {isa = PBXBuildFile; fileRef = E57ABA024D08EDE3371F3F3C62400CAE /* FMLayoutBackground.h */; settings = {ATTRIBUTES = (Public, ); }; }; 1972E85F0FCD0F3EAF28ED7CD036286E /* Masonry-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = A85AE9E36F67A1B513CB8DA940771B4F /* Masonry-dummy.m */; }; 1D02BDC76EBE6C218E5DCF6DE7312674 /* FMLayoutDynamicSection.h in Headers */ = {isa = PBXBuildFile; fileRef = 695762AF41ACC2A7AFD29B9B1E1C6862 /* FMLayoutDynamicSection.h */; settings = {ATTRIBUTES = (Public, ); }; }; 280D36330BAC5715615FF4A8B42D60D6 /* MASUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 607937A372913475EE7EAE532760ACD4 /* MASUtilities.h */; settings = {ATTRIBUTES = (Public, ); }; }; 297A3627CF2F032CBFDC61D1A3786E63 /* MASViewAttribute.m in Sources */ = {isa = PBXBuildFile; fileRef = A8BCCE8C6C17F326AFEDF4357C62ADAF /* MASViewAttribute.m */; }; 2BF16135E62ABD244F9394C280B06EE8 /* FMLayoutFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B03A6B14FC8CDE4DE74F867FC4F7F65 /* FMLayoutFooter.m */; }; 346080C0D1CA23399ADD739D722D7CEF /* Masonry.h in Headers */ = {isa = PBXBuildFile; fileRef = EDA8A3885BC33F25CB32442EB2449111 /* Masonry.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3DA5F1D8E51CDD102A871C2F37770C7B /* MASViewAttribute.h in Headers */ = {isa = PBXBuildFile; fileRef = A78D3443F105E00FC21FE5A357C8F716 /* MASViewAttribute.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3E6BAAA0B701F41E9E589822F97BF3AF /* FMLayoutHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = F1BA5D5862C57CC3644C9D0385D221AC /* FMLayoutHeader.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3EABA5C42467DAD253F1AF5ADA7EB3F3 /* FMLayoutAbsoluteSection.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CBE4990B360257A8AA8BAED6177471B /* FMLayoutAbsoluteSection.m */; }; 4920CEABC4082E37F8B2BBB9D930C02E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 436BAA54A31999B53B3CC7115C55FE50 /* Foundation.framework */; }; 4B0981F9AC628CF5100C50FF4A163A4A /* View+MASAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 047EE388CF208BD5F57049BD98558C94 /* View+MASAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4F5212C040672D2776544CAA39A4FCCE /* FMKVOArrayObject.m in Sources */ = {isa = PBXBuildFile; fileRef = AAF19FCABA3E0F39CA988DE97736C2C3 /* FMKVOArrayObject.m */; }; 5E69AAA6E15FDFECAA93CBAEC53577BC /* FMLayoutView.m in Sources */ = {isa = PBXBuildFile; fileRef = 27F4B838AAA41DA3AFC042162BE57A14 /* FMLayoutView.m */; }; 6A6AD3A5BBDBFD0B4AF936BD518EC0B1 /* Masonry-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 6CF8069504999FB8BF5FA1529175AA74 /* Masonry-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 6ED2198EBA016B6DA6627F67D251986C /* FMLayoutLabelSection.m in Sources */ = {isa = PBXBuildFile; fileRef = CBBED27DA45B26B520D460A4665F4D78 /* FMLayoutLabelSection.m */; }; 71C79BAA01DF9FE5DAA86B75A507F253 /* FMLayoutKit-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = DEAA326C1902A3E21C96E1592CA9E5F8 /* FMLayoutKit-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 72B72B650AF3C690635A54BE8356662C /* FMTeslaSuspensionHeightChangeDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = CA6102B5FF7D583B8C2C690205DE20A4 /* FMTeslaSuspensionHeightChangeDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; 78B2727EE5D693F58D019DB098005101 /* MASConstraintMaker.m in Sources */ = {isa = PBXBuildFile; fileRef = 470C5CD1265270E95A8A89443C727427 /* MASConstraintMaker.m */; }; 7AC2FC49B351E793717BFC9DA6B333C5 /* Pods-FMLayoutKit_Example-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = B263B7AE65E097574862F32234C5F0A8 /* Pods-FMLayoutKit_Example-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 7BFF65958F014760B6AC4742824892EB /* MASCompositeConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = EB7CC7527FD599A1064055C060E14B43 /* MASCompositeConstraint.m */; }; 82F24F7CB465BA0393889419603DE536 /* FMLayoutFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = BE6875EFE2C29C824642C4EBEF334C30 /* FMLayoutFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; 8475566499CB6BE91D3D16D549E3EB2D /* FMTeslaLayoutView.h in Headers */ = {isa = PBXBuildFile; fileRef = B176EB4D307EA30B2F3A1980CAD83A70 /* FMTeslaLayoutView.h */; settings = {ATTRIBUTES = (Public, ); }; }; 8539B851E01A58467BE49CA3FA77223C /* MASLayoutConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = 6E17443EA85E103F4DD0553AB6BB942A /* MASLayoutConstraint.m */; }; 8B86204F0349A782F91323459449CD0B /* FMCollectionLayoutAttributes.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B4ADEDC659AD492EE7CC526FDF7DD8 /* FMCollectionLayoutAttributes.m */; }; 8B92011C9373001132C8148BFC8F50B3 /* ViewController+MASAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 55960467D1B758EC688A18A171012E78 /* ViewController+MASAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; 8D4D1F6E4709EBB13974E95DC1059DDC /* MASLayoutConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = 6FF4AF21902029EC43C354AC0978CE49 /* MASLayoutConstraint.h */; settings = {ATTRIBUTES = (Public, ); }; }; 8D65CE579E516BDD5FB36CAA21D693F6 /* MASCompositeConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = 4AD89987EC7EAE20D7034EEF9935E7CC /* MASCompositeConstraint.h */; settings = {ATTRIBUTES = (Public, ); }; }; 92DA6DE8550689C4F76DBFB01A460124 /* FMLayoutLabelSection.h in Headers */ = {isa = PBXBuildFile; fileRef = B76709D281AC0B27965A319D31A49399 /* FMLayoutLabelSection.h */; settings = {ATTRIBUTES = (Public, ); }; }; 940A8C4C1195ACC5EB26CF6DB55B4D02 /* Pods-FMLayoutKit_Example-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 8F8ADAA65E2E1F0E9F75CE99DD2523EA /* Pods-FMLayoutKit_Example-dummy.m */; }; 941955A19C40899D275604E6E9C21A6D /* MASConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = 02CA69FDFD4D7BB11F8E3E2E7A0B9879 /* MASConstraint.h */; settings = {ATTRIBUTES = (Public, ); }; }; 98313EE28994F7745E8E60C1FC4EBB7A /* FMLayoutView.h in Headers */ = {isa = PBXBuildFile; fileRef = FC09401D363564893FFA81BCD727C206 /* FMLayoutView.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9D546E1168C04B0B2EAE005D9275D18B /* MASConstraint+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 837834476F3329FA118B081516D4FC28 /* MASConstraint+Private.h */; settings = {ATTRIBUTES = (Public, ); }; }; A35FBEEC7D088AEC05297E8292A32C77 /* View+MASAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = AF4497913DB548AE2E03103D3A97F34F /* View+MASAdditions.m */; }; A65EAC754DF091EB22BCC40FFF0F1D35 /* FMLayoutFixedSection.h in Headers */ = {isa = PBXBuildFile; fileRef = FEB8048D4BBD68AB8C55867A00652E22 /* FMLayoutFixedSection.h */; settings = {ATTRIBUTES = (Public, ); }; }; B08C380708F0F4816D1E2BE5D199B9C7 /* FMLayoutElement.m in Sources */ = {isa = PBXBuildFile; fileRef = 27EDA7901C9F630F428E06BD9DDE8D2A /* FMLayoutElement.m */; }; B67FA646712B7183A3742DE39A61BE2C /* FMKVOArrayObject.h in Headers */ = {isa = PBXBuildFile; fileRef = C0E86FA9D29C2710D6F80866B0E2EA75 /* FMKVOArrayObject.h */; settings = {ATTRIBUTES = (Public, ); }; }; B7D645EC004610E8A581E532D28771EC /* MASViewConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = 72A95F8027E3EB86CB9AE2D7539201FE /* MASViewConstraint.m */; }; B915FCFC0E255F43F5A4049082E68D95 /* FMLayoutHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D4503ED6C470BF67C1AB6E9BFE8560C /* FMLayoutHeader.m */; }; B9EB397E56BC70BDD925430719BC6329 /* FMLayoutElement.h in Headers */ = {isa = PBXBuildFile; fileRef = F9E17FEA74C0D603C0DEE059C5833D59 /* FMLayoutElement.h */; settings = {ATTRIBUTES = (Public, ); }; }; BA16C547F6B3F33429F514A9C7C998F0 /* FMTeslaLayoutView.m in Sources */ = {isa = PBXBuildFile; fileRef = 6F3D0D5CF65ED9C7476ADC49BD08B176 /* FMTeslaLayoutView.m */; }; BD55ECDBBFF5476F382CFEAF1DDE9146 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 436BAA54A31999B53B3CC7115C55FE50 /* Foundation.framework */; }; BF5C569DA64FD9C3EEEF8E536A7A806C /* FMLayoutFillSection.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CA553886878BC7E10C1FFEEA3C1E2E3 /* FMLayoutFillSection.m */; }; C0861ADB4C5FA30F4F9E051F7638A264 /* NSLayoutConstraint+MASDebugAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 071EEE0A3CE36E163E09EA7F7915F1DE /* NSLayoutConstraint+MASDebugAdditions.m */; }; C306258324986E6A000243D4 /* FMLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = C306258124986E6A000243D4 /* FMLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; C306258424986E6A000243D4 /* FMLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = C306258224986E6A000243D4 /* FMLayout.m */; }; C30625872498CABA000243D4 /* FMLayoutCrossCell.h in Headers */ = {isa = PBXBuildFile; fileRef = C30625852498CABA000243D4 /* FMLayoutCrossCell.h */; }; C30625882498CABA000243D4 /* FMLayoutCrossCell.m in Sources */ = {isa = PBXBuildFile; fileRef = C30625862498CABA000243D4 /* FMLayoutCrossCell.m */; }; C306258B2498CC06000243D4 /* FMLayoutCrossSection.h in Headers */ = {isa = PBXBuildFile; fileRef = C30625892498CC06000243D4 /* FMLayoutCrossSection.h */; settings = {ATTRIBUTES = (Public, ); }; }; C306258C2498CC06000243D4 /* FMLayoutCrossSection.m in Sources */ = {isa = PBXBuildFile; fileRef = C306258A2498CC06000243D4 /* FMLayoutCrossSection.m */; }; C3808B74261F4FD10013501C /* _FMLayoutSussEmptyView.h in Headers */ = {isa = PBXBuildFile; fileRef = C3808B72261F4FD10013501C /* _FMLayoutSussEmptyView.h */; }; C3808B75261F4FD10013501C /* _FMLayoutSussEmptyView.m in Sources */ = {isa = PBXBuildFile; fileRef = C3808B73261F4FD10013501C /* _FMLayoutSussEmptyView.m */; }; C38CB4B2260EC0B500E1C3AA /* FMCollectionViewDelegateDataSourceProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = C38CB4B0260EC0B500E1C3AA /* FMCollectionViewDelegateDataSourceProvider.h */; settings = {ATTRIBUTES = (Public, ); }; }; C38CB4B3260EC0B500E1C3AA /* FMCollectionViewDelegateDataSourceProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = C38CB4B1260EC0B500E1C3AA /* FMCollectionViewDelegateDataSourceProvider.m */; }; C38CB4BA260EC4B800E1C3AA /* UIView+FMLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = C38CB4B8260EC4B800E1C3AA /* UIView+FMLayout.h */; }; C38CB4BB260EC4B800E1C3AA /* UIView+FMLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = C38CB4B9260EC4B800E1C3AA /* UIView+FMLayout.m */; }; C38CD57124C528CA00D89C9E /* FMLayoutScaleSection.h in Headers */ = {isa = PBXBuildFile; fileRef = C38CD56F24C528CA00D89C9E /* FMLayoutScaleSection.h */; settings = {ATTRIBUTES = (Public, ); }; }; C38CD57224C528CA00D89C9E /* FMLayoutScaleSection.m in Sources */ = {isa = PBXBuildFile; fileRef = C38CD57024C528CA00D89C9E /* FMLayoutScaleSection.m */; }; C3973880248F716E00A7A2C2 /* FMLayoutKit.h in Headers */ = {isa = PBXBuildFile; fileRef = C397387F248F716E00A7A2C2 /* FMLayoutKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; C399ACAD24BECF8500DD02EE /* FMLayoutCrossTransformSection.h in Headers */ = {isa = PBXBuildFile; fileRef = C399ACAB24BECF8500DD02EE /* FMLayoutCrossTransformSection.h */; settings = {ATTRIBUTES = (Public, ); }; }; C399ACAE24BECF8500DD02EE /* FMLayoutCrossTransformSection.m in Sources */ = {isa = PBXBuildFile; fileRef = C399ACAC24BECF8500DD02EE /* FMLayoutCrossTransformSection.m */; }; C3A262922499EC06000A269D /* FMLayoutDebugLog.h in Headers */ = {isa = PBXBuildFile; fileRef = C3A262902499EC06000A269D /* FMLayoutDebugLog.h */; settings = {ATTRIBUTES = (Public, ); }; }; C3A262932499EC06000A269D /* FMLayoutDebugLog.m in Sources */ = {isa = PBXBuildFile; fileRef = C3A262912499EC06000A269D /* FMLayoutDebugLog.m */; }; C3C47B9B24BAB5B00020C071 /* FMLayoutCombineSection.h in Headers */ = {isa = PBXBuildFile; fileRef = C3C47B9924BAB5B00020C071 /* FMLayoutCombineSection.h */; settings = {ATTRIBUTES = (Public, ); }; }; C3C47B9C24BAB5B00020C071 /* FMLayoutCombineSection.m in Sources */ = {isa = PBXBuildFile; fileRef = C3C47B9A24BAB5B00020C071 /* FMLayoutCombineSection.m */; }; CA9FF2872811CDA655E6C77C620BCD05 /* Pods-FMLayoutKit_Tests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 96A04BFBA339CDD9A004F61900B12E32 /* Pods-FMLayoutKit_Tests-dummy.m */; }; CE93C54413259B4AC3683B6EB874D466 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 312B988EF117AE4DE76A268D970131FE /* UIKit.framework */; }; D240D2B05DDD6EABBFDF67F8E42921A4 /* FMLayoutAbsoluteSection.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B1FF779F9051E7EBED1D90B22E54DBE /* FMLayoutAbsoluteSection.h */; settings = {ATTRIBUTES = (Public, ); }; }; DE71BF9E8478FF8DA2C96CD2B630C39E /* FMCollectionLayoutAttributes.h in Headers */ = {isa = PBXBuildFile; fileRef = F306E024590AF9CC027DBBAB232B73E3 /* FMCollectionLayoutAttributes.h */; settings = {ATTRIBUTES = (Public, ); }; }; E2B9E1E80E80F624D4FF15D038655677 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 436BAA54A31999B53B3CC7115C55FE50 /* Foundation.framework */; }; E51F496BDC6ACADE04FDA059C6CB2342 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 436BAA54A31999B53B3CC7115C55FE50 /* Foundation.framework */; }; E7CA20228B3583F41927813EE904CAD3 /* View+MASShorthandAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 86765B456E483806C4E13D2DD50E40A4 /* View+MASShorthandAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; E8DD5D1D406150E1C80AD015271B6848 /* MASConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = 9073C3B74BC30C55B4EB5B2A596EAD72 /* MASConstraint.m */; }; EAE8B0895956885A752B173683A0D889 /* MASViewConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = D12E9F350C1C8076BE92719B89951AD8 /* MASViewConstraint.h */; settings = {ATTRIBUTES = (Public, ); }; }; EAEF0BFE8D36DCB4694B7D396DD97AAE /* FMLayoutBackground.m in Sources */ = {isa = PBXBuildFile; fileRef = C88C69EDAC1D1808A8CBEADA2477ABC8 /* FMLayoutBackground.m */; }; ECC24C178FF280A0D8F0C329AC7D59A7 /* FMLayoutBaseSection.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C82D5BFA0B27E8632239CAA6181284C /* FMLayoutBaseSection.m */; }; F19C07B7E88762246953AF01071B2E24 /* FMLayoutBaseSection.h in Headers */ = {isa = PBXBuildFile; fileRef = 04571F5B56E0EDD2CBD13357E25B5C46 /* FMLayoutBaseSection.h */; settings = {ATTRIBUTES = (Public, ); }; }; F4C5DC6114CB65244093D6A8DA36B005 /* FMLayoutKit-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 80509D0C69E6817F6D85CDF9582F413F /* FMLayoutKit-dummy.m */; }; F7F785200308DA7B9636000E2D47F4A8 /* FMLayoutDynamicSection.m in Sources */ = {isa = PBXBuildFile; fileRef = 96DF14938E1694B50EC1788FF7CC6B31 /* FMLayoutDynamicSection.m */; }; F977A8588FE03966589260ECDE5CCEC5 /* FMSupplementary.m in Sources */ = {isa = PBXBuildFile; fileRef = 757A4B6AAA8326254A2E25CCE4363522 /* FMSupplementary.m */; }; FAFBFA90F7BC3E7CF50F8A5CF0A8B264 /* MASConstraintMaker.h in Headers */ = {isa = PBXBuildFile; fileRef = B28EC2F4C626ED77509645BE3805CB29 /* MASConstraintMaker.h */; settings = {ATTRIBUTES = (Public, ); }; }; FCCB987C9E8C8D7CC4D2C42DD86BAABF /* Pods-FMLayoutKit_Tests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = F1F3F17D6738600847CCB29087356C28 /* Pods-FMLayoutKit_Tests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ 533CAF9A4A9C7831C1D4CCB6A5125581 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; remoteGlobalIDString = 55AF53E6C77A10ED4985E04D74A8878E; remoteInfo = Masonry; }; 5A308C6B23658D4BCECD24DEBBF83C5E /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; remoteGlobalIDString = B2FC59B39F266A918806E8EA1301C377; remoteInfo = FMLayoutKit; }; 99FF2E4998226FB31D16609CDE458316 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; remoteGlobalIDString = DA993AD93696E1200894CB71CBC71FA9; remoteInfo = "Pods-FMLayoutKit_Example"; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ 02CA69FDFD4D7BB11F8E3E2E7A0B9879 /* MASConstraint.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASConstraint.h; path = Masonry/MASConstraint.h; sourceTree = ""; }; 04571F5B56E0EDD2CBD13357E25B5C46 /* FMLayoutBaseSection.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = FMLayoutBaseSection.h; sourceTree = ""; }; 047EE388CF208BD5F57049BD98558C94 /* View+MASAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "View+MASAdditions.h"; path = "Masonry/View+MASAdditions.h"; sourceTree = ""; }; 071EEE0A3CE36E163E09EA7F7915F1DE /* NSLayoutConstraint+MASDebugAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSLayoutConstraint+MASDebugAdditions.m"; path = "Masonry/NSLayoutConstraint+MASDebugAdditions.m"; sourceTree = ""; }; 0C3D35D65006895D8FEC2D259FACD724 /* Pods-FMLayoutKit_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-FMLayoutKit_Example.debug.xcconfig"; sourceTree = ""; }; 0CA553886878BC7E10C1FFEEA3C1E2E3 /* FMLayoutFillSection.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = FMLayoutFillSection.m; sourceTree = ""; }; 15A006ECDF5E6A5D581F64FB6602E2BC /* Pods-FMLayoutKit_Example-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-FMLayoutKit_Example-acknowledgements.markdown"; sourceTree = ""; }; 178BBA299FABFEDDD5906B36A1B9467F /* FMLayoutKit-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "FMLayoutKit-Info.plist"; sourceTree = ""; }; 1B04B626DB0A83721A64BE176C6E082E /* Pods-FMLayoutKit_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-FMLayoutKit_Tests.debug.xcconfig"; sourceTree = ""; }; 1FFED36A657123030ABB700256D73F15 /* Masonry.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Masonry.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 25E681D1FE06AC1C1D118CF19E26866A /* FMLayoutKit.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FMLayoutKit.release.xcconfig; sourceTree = ""; }; 27C923CEC19AD2AE1D49E900B465DE2E /* Pods-FMLayoutKit_Example-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-FMLayoutKit_Example-Info.plist"; sourceTree = ""; }; 27E12E3D2779B5C7A8301A94F715DB4C /* NSArray+MASShorthandAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSArray+MASShorthandAdditions.h"; path = "Masonry/NSArray+MASShorthandAdditions.h"; sourceTree = ""; }; 27EDA7901C9F630F428E06BD9DDE8D2A /* FMLayoutElement.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = FMLayoutElement.m; sourceTree = ""; }; 27F4B838AAA41DA3AFC042162BE57A14 /* FMLayoutView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FMLayoutView.m; path = FMLayoutKit/Classes/FMLayoutView.m; sourceTree = ""; }; 29B4ADEDC659AD492EE7CC526FDF7DD8 /* FMCollectionLayoutAttributes.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FMCollectionLayoutAttributes.m; path = FMLayoutKit/Classes/FMCollectionLayoutAttributes.m; sourceTree = ""; }; 2CBE4990B360257A8AA8BAED6177471B /* FMLayoutAbsoluteSection.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = FMLayoutAbsoluteSection.m; sourceTree = ""; }; 2DB747C7C5D095FAD7DC101195534913 /* Pods-FMLayoutKit_Example.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-FMLayoutKit_Example.modulemap"; sourceTree = ""; }; 30EC6C5D191587619B42076546EDC448 /* NSArray+MASAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSArray+MASAdditions.h"; path = "Masonry/NSArray+MASAdditions.h"; sourceTree = ""; }; 312B988EF117AE4DE76A268D970131FE /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; 342C4D9B5E1E36390E7AF01E35444998 /* ViewController+MASAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "ViewController+MASAdditions.m"; path = "Masonry/ViewController+MASAdditions.m"; sourceTree = ""; }; 3E537C1F47DA8B06DA4A71E3D14F4DE4 /* Masonry.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = Masonry.modulemap; sourceTree = ""; }; 3ED09B7CD1A7327639D889668502ABC9 /* FMLayoutKit.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; path = FMLayoutKit.podspec; sourceTree = ""; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 3F1CDE96B8DD819AFBC893527CD2D540 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; 40648A88F893A5F24BF147514CBEF448 /* Pods_FMLayoutKit_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_FMLayoutKit_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 419A961AD957E23BAB6A998ED7623134 /* Masonry.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Masonry.release.xcconfig; sourceTree = ""; }; 436BAA54A31999B53B3CC7115C55FE50 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; 45B08C70A4CDCFF6F7EAAB4ADBD47049 /* Pods-FMLayoutKit_Tests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-FMLayoutKit_Tests.modulemap"; sourceTree = ""; }; 470C5CD1265270E95A8A89443C727427 /* MASConstraintMaker.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASConstraintMaker.m; path = Masonry/MASConstraintMaker.m; sourceTree = ""; }; 4AD89987EC7EAE20D7034EEF9935E7CC /* MASCompositeConstraint.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASCompositeConstraint.h; path = Masonry/MASCompositeConstraint.h; sourceTree = ""; }; 55960467D1B758EC688A18A171012E78 /* ViewController+MASAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "ViewController+MASAdditions.h"; path = "Masonry/ViewController+MASAdditions.h"; sourceTree = ""; }; 5C82D5BFA0B27E8632239CAA6181284C /* FMLayoutBaseSection.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = FMLayoutBaseSection.m; sourceTree = ""; }; 607937A372913475EE7EAE532760ACD4 /* MASUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASUtilities.h; path = Masonry/MASUtilities.h; sourceTree = ""; }; 695762AF41ACC2A7AFD29B9B1E1C6862 /* FMLayoutDynamicSection.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = FMLayoutDynamicSection.h; sourceTree = ""; }; 6C45DA37873F2F0BD195A76D9F212950 /* Pods-FMLayoutKit_Tests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-FMLayoutKit_Tests-acknowledgements.markdown"; sourceTree = ""; }; 6CF8069504999FB8BF5FA1529175AA74 /* Masonry-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Masonry-umbrella.h"; sourceTree = ""; }; 6E17443EA85E103F4DD0553AB6BB942A /* MASLayoutConstraint.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASLayoutConstraint.m; path = Masonry/MASLayoutConstraint.m; sourceTree = ""; }; 6E278E08B8933498E6D2169E80346C46 /* Pods_FMLayoutKit_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_FMLayoutKit_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 6F3D0D5CF65ED9C7476ADC49BD08B176 /* FMTeslaLayoutView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FMTeslaLayoutView.m; path = FMLayoutKit/Classes/FMTeslaLayoutView.m; sourceTree = ""; }; 6FF4AF21902029EC43C354AC0978CE49 /* MASLayoutConstraint.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASLayoutConstraint.h; path = Masonry/MASLayoutConstraint.h; sourceTree = ""; }; 70EF59D03E8E18F7F4A4759C9D883F45 /* Pods-FMLayoutKit_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-FMLayoutKit_Example.release.xcconfig"; sourceTree = ""; }; 72A95F8027E3EB86CB9AE2D7539201FE /* MASViewConstraint.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASViewConstraint.m; path = Masonry/MASViewConstraint.m; sourceTree = ""; }; 73AF606D61C49DC01DC5C905A43E81D1 /* FMLayoutKit.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = FMLayoutKit.modulemap; sourceTree = ""; }; 757A4B6AAA8326254A2E25CCE4363522 /* FMSupplementary.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = FMSupplementary.m; sourceTree = ""; }; 7A6BACBBBAF66F4EAF255239F54D56EA /* FMSupplementary.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = FMSupplementary.h; sourceTree = ""; }; 7B1FF779F9051E7EBED1D90B22E54DBE /* FMLayoutAbsoluteSection.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = FMLayoutAbsoluteSection.h; sourceTree = ""; }; 80509D0C69E6817F6D85CDF9582F413F /* FMLayoutKit-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "FMLayoutKit-dummy.m"; sourceTree = ""; }; 837834476F3329FA118B081516D4FC28 /* MASConstraint+Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "MASConstraint+Private.h"; path = "Masonry/MASConstraint+Private.h"; sourceTree = ""; }; 86765B456E483806C4E13D2DD50E40A4 /* View+MASShorthandAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "View+MASShorthandAdditions.h"; path = "Masonry/View+MASShorthandAdditions.h"; sourceTree = ""; }; 8AEEBD88282BA13360CAA867D8465C75 /* NSArray+MASAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSArray+MASAdditions.m"; path = "Masonry/NSArray+MASAdditions.m"; sourceTree = ""; }; 8B03A6B14FC8CDE4DE74F867FC4F7F65 /* FMLayoutFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = FMLayoutFooter.m; sourceTree = ""; }; 8D4503ED6C470BF67C1AB6E9BFE8560C /* FMLayoutHeader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = FMLayoutHeader.m; sourceTree = ""; }; 8F8ADAA65E2E1F0E9F75CE99DD2523EA /* Pods-FMLayoutKit_Example-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-FMLayoutKit_Example-dummy.m"; sourceTree = ""; }; 9073C3B74BC30C55B4EB5B2A596EAD72 /* MASConstraint.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASConstraint.m; path = Masonry/MASConstraint.m; sourceTree = ""; }; 9330DB95734C61A9B50053A900E605AD /* FMLayoutKit-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FMLayoutKit-prefix.pch"; sourceTree = ""; }; 96A04BFBA339CDD9A004F61900B12E32 /* Pods-FMLayoutKit_Tests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-FMLayoutKit_Tests-dummy.m"; sourceTree = ""; }; 96AFA767C03E7AC6D309F8621C7A8CE7 /* Pods-FMLayoutKit_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-FMLayoutKit_Tests.release.xcconfig"; sourceTree = ""; }; 96B17227B74ED7BCB99AA0FD25EE6C40 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 96DF14938E1694B50EC1788FF7CC6B31 /* FMLayoutDynamicSection.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = FMLayoutDynamicSection.m; sourceTree = ""; }; 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; A78D3443F105E00FC21FE5A357C8F716 /* MASViewAttribute.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASViewAttribute.h; path = Masonry/MASViewAttribute.h; sourceTree = ""; }; A85AE9E36F67A1B513CB8DA940771B4F /* Masonry-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Masonry-dummy.m"; sourceTree = ""; }; A8BCCE8C6C17F326AFEDF4357C62ADAF /* MASViewAttribute.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASViewAttribute.m; path = Masonry/MASViewAttribute.m; sourceTree = ""; }; AAF19FCABA3E0F39CA988DE97736C2C3 /* FMKVOArrayObject.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FMKVOArrayObject.m; path = FMLayoutKit/Classes/FMKVOArrayObject.m; sourceTree = ""; }; AB29189261D660E85FDE41FE16816ECD /* FMLayoutFixedSection.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = FMLayoutFixedSection.m; sourceTree = ""; }; AD9AB32AE99D9D9B67F4E426138CC214 /* Pods-FMLayoutKit_Tests-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-FMLayoutKit_Tests-Info.plist"; sourceTree = ""; }; AF4497913DB548AE2E03103D3A97F34F /* View+MASAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "View+MASAdditions.m"; path = "Masonry/View+MASAdditions.m"; sourceTree = ""; }; B176EB4D307EA30B2F3A1980CAD83A70 /* FMTeslaLayoutView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FMTeslaLayoutView.h; path = FMLayoutKit/Classes/FMTeslaLayoutView.h; sourceTree = ""; }; B263B7AE65E097574862F32234C5F0A8 /* Pods-FMLayoutKit_Example-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-FMLayoutKit_Example-umbrella.h"; sourceTree = ""; }; B28EC2F4C626ED77509645BE3805CB29 /* MASConstraintMaker.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASConstraintMaker.h; path = Masonry/MASConstraintMaker.h; sourceTree = ""; }; B76709D281AC0B27965A319D31A49399 /* FMLayoutLabelSection.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = FMLayoutLabelSection.h; sourceTree = ""; }; BDB676D9D5D3AFD89D8DDCE3369D4BAC /* Masonry-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Masonry-prefix.pch"; sourceTree = ""; }; BE6875EFE2C29C824642C4EBEF334C30 /* FMLayoutFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = FMLayoutFooter.h; sourceTree = ""; }; C0E86FA9D29C2710D6F80866B0E2EA75 /* FMKVOArrayObject.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FMKVOArrayObject.h; path = FMLayoutKit/Classes/FMKVOArrayObject.h; sourceTree = ""; }; C306258124986E6A000243D4 /* FMLayout.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FMLayout.h; path = FMLayoutKit/Classes/FMLayout.h; sourceTree = ""; }; C306258224986E6A000243D4 /* FMLayout.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = FMLayout.m; path = FMLayoutKit/Classes/FMLayout.m; sourceTree = ""; }; C30625852498CABA000243D4 /* FMLayoutCrossCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FMLayoutCrossCell.h; sourceTree = ""; }; C30625862498CABA000243D4 /* FMLayoutCrossCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FMLayoutCrossCell.m; sourceTree = ""; }; C30625892498CC06000243D4 /* FMLayoutCrossSection.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FMLayoutCrossSection.h; sourceTree = ""; }; C306258A2498CC06000243D4 /* FMLayoutCrossSection.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FMLayoutCrossSection.m; sourceTree = ""; }; C3808B72261F4FD10013501C /* _FMLayoutSussEmptyView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = _FMLayoutSussEmptyView.h; path = FMLayoutKit/Classes/_FMLayoutSussEmptyView.h; sourceTree = ""; }; C3808B73261F4FD10013501C /* _FMLayoutSussEmptyView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = _FMLayoutSussEmptyView.m; path = FMLayoutKit/Classes/_FMLayoutSussEmptyView.m; sourceTree = ""; }; C38CB4B0260EC0B500E1C3AA /* FMCollectionViewDelegateDataSourceProvider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FMCollectionViewDelegateDataSourceProvider.h; path = FMLayoutKit/Classes/FMCollectionViewDelegateDataSourceProvider.h; sourceTree = ""; }; C38CB4B1260EC0B500E1C3AA /* FMCollectionViewDelegateDataSourceProvider.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = FMCollectionViewDelegateDataSourceProvider.m; path = FMLayoutKit/Classes/FMCollectionViewDelegateDataSourceProvider.m; sourceTree = ""; }; C38CB4B8260EC4B800E1C3AA /* UIView+FMLayout.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "UIView+FMLayout.h"; path = "FMLayoutKit/Classes/UIView+FMLayout.h"; sourceTree = ""; }; C38CB4B9260EC4B800E1C3AA /* UIView+FMLayout.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = "UIView+FMLayout.m"; path = "FMLayoutKit/Classes/UIView+FMLayout.m"; sourceTree = ""; }; C38CD56F24C528CA00D89C9E /* FMLayoutScaleSection.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FMLayoutScaleSection.h; sourceTree = ""; }; C38CD57024C528CA00D89C9E /* FMLayoutScaleSection.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FMLayoutScaleSection.m; sourceTree = ""; }; C397387F248F716E00A7A2C2 /* FMLayoutKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FMLayoutKit.h; path = FMLayoutKit/Classes/FMLayoutKit.h; sourceTree = ""; }; C399ACAB24BECF8500DD02EE /* FMLayoutCrossTransformSection.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FMLayoutCrossTransformSection.h; sourceTree = ""; }; C399ACAC24BECF8500DD02EE /* FMLayoutCrossTransformSection.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FMLayoutCrossTransformSection.m; sourceTree = ""; }; C3A262902499EC06000A269D /* FMLayoutDebugLog.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FMLayoutDebugLog.h; path = FMLayoutKit/Classes/FMLayoutDebugLog.h; sourceTree = ""; }; C3A262912499EC06000A269D /* FMLayoutDebugLog.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = FMLayoutDebugLog.m; path = FMLayoutKit/Classes/FMLayoutDebugLog.m; sourceTree = ""; }; C3C47B9924BAB5B00020C071 /* FMLayoutCombineSection.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FMLayoutCombineSection.h; sourceTree = ""; }; C3C47B9A24BAB5B00020C071 /* FMLayoutCombineSection.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FMLayoutCombineSection.m; sourceTree = ""; }; C88C69EDAC1D1808A8CBEADA2477ABC8 /* FMLayoutBackground.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = FMLayoutBackground.m; sourceTree = ""; }; CA6102B5FF7D583B8C2C690205DE20A4 /* FMTeslaSuspensionHeightChangeDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FMTeslaSuspensionHeightChangeDelegate.h; path = FMLayoutKit/Classes/FMTeslaSuspensionHeightChangeDelegate.h; sourceTree = ""; }; CBBED27DA45B26B520D460A4665F4D78 /* FMLayoutLabelSection.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = FMLayoutLabelSection.m; sourceTree = ""; }; CD5237ED21769F367AD59FEA53E56403 /* FMLayoutKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = FMLayoutKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D12E9F350C1C8076BE92719B89951AD8 /* MASViewConstraint.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASViewConstraint.h; path = Masonry/MASViewConstraint.h; sourceTree = ""; }; DEAA326C1902A3E21C96E1592CA9E5F8 /* FMLayoutKit-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FMLayoutKit-umbrella.h"; sourceTree = ""; }; DFA1012B6A8BD076CD9F09831AE37A01 /* Masonry-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Masonry-Info.plist"; sourceTree = ""; }; E1C00F6DE5FCEE0DA9B533ADB640314A /* Pods-FMLayoutKit_Example-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-FMLayoutKit_Example-acknowledgements.plist"; sourceTree = ""; }; E57ABA024D08EDE3371F3F3C62400CAE /* FMLayoutBackground.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = FMLayoutBackground.h; sourceTree = ""; }; E7851906D7976272A721C8C4E0CE9092 /* NSLayoutConstraint+MASDebugAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSLayoutConstraint+MASDebugAdditions.h"; path = "Masonry/NSLayoutConstraint+MASDebugAdditions.h"; sourceTree = ""; }; EB7CC7527FD599A1064055C060E14B43 /* MASCompositeConstraint.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASCompositeConstraint.m; path = Masonry/MASCompositeConstraint.m; sourceTree = ""; }; EDA8A3885BC33F25CB32442EB2449111 /* Masonry.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Masonry.h; path = Masonry/Masonry.h; sourceTree = ""; }; EFB557E32229FE28558ECD4165517E19 /* Pods-FMLayoutKit_Tests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-FMLayoutKit_Tests-acknowledgements.plist"; sourceTree = ""; }; F1BA5D5862C57CC3644C9D0385D221AC /* FMLayoutHeader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = FMLayoutHeader.h; sourceTree = ""; }; F1F3F17D6738600847CCB29087356C28 /* Pods-FMLayoutKit_Tests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-FMLayoutKit_Tests-umbrella.h"; sourceTree = ""; }; F2293961BF15DE3D3E5DE9FBAADCAFA2 /* Pods-FMLayoutKit_Example-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-FMLayoutKit_Example-frameworks.sh"; sourceTree = ""; }; F287598D192FA586BD4AECCD85B988A4 /* Masonry.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Masonry.debug.xcconfig; sourceTree = ""; }; F306E024590AF9CC027DBBAB232B73E3 /* FMCollectionLayoutAttributes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FMCollectionLayoutAttributes.h; path = FMLayoutKit/Classes/FMCollectionLayoutAttributes.h; sourceTree = ""; }; F7950A8B63A4F538F53B4D0165DAAAAE /* FMLayoutFillSection.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = FMLayoutFillSection.h; sourceTree = ""; }; F86E146544D85F28DCC4F98C9C817B3E /* FMLayoutKit.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FMLayoutKit.debug.xcconfig; sourceTree = ""; }; F9E17FEA74C0D603C0DEE059C5833D59 /* FMLayoutElement.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = FMLayoutElement.h; sourceTree = ""; }; FC09401D363564893FFA81BCD727C206 /* FMLayoutView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FMLayoutView.h; path = FMLayoutKit/Classes/FMLayoutView.h; sourceTree = ""; }; FEB8048D4BBD68AB8C55867A00652E22 /* FMLayoutFixedSection.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = FMLayoutFixedSection.h; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 34491089D9993E01EB0F5DD7FFB1F651 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( E2B9E1E80E80F624D4FF15D038655677 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 5E047F76604659BF1B2099B2C412AC93 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( E51F496BDC6ACADE04FDA059C6CB2342 /* Foundation.framework in Frameworks */, CE93C54413259B4AC3683B6EB874D466 /* UIKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; C3DF58F3D2435E31C755240BC1445BF6 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( BD55ECDBBFF5476F382CFEAF1DDE9146 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; CF309522E666ABB1561A51BD4788BA50 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 4920CEABC4082E37F8B2BBB9D930C02E /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 0CCC0CD98AB951949302B433AFE762AD /* Masonry */ = { isa = PBXGroup; children = ( 4AD89987EC7EAE20D7034EEF9935E7CC /* MASCompositeConstraint.h */, EB7CC7527FD599A1064055C060E14B43 /* MASCompositeConstraint.m */, 02CA69FDFD4D7BB11F8E3E2E7A0B9879 /* MASConstraint.h */, 9073C3B74BC30C55B4EB5B2A596EAD72 /* MASConstraint.m */, 837834476F3329FA118B081516D4FC28 /* MASConstraint+Private.h */, B28EC2F4C626ED77509645BE3805CB29 /* MASConstraintMaker.h */, 470C5CD1265270E95A8A89443C727427 /* MASConstraintMaker.m */, 6FF4AF21902029EC43C354AC0978CE49 /* MASLayoutConstraint.h */, 6E17443EA85E103F4DD0553AB6BB942A /* MASLayoutConstraint.m */, EDA8A3885BC33F25CB32442EB2449111 /* Masonry.h */, 607937A372913475EE7EAE532760ACD4 /* MASUtilities.h */, A78D3443F105E00FC21FE5A357C8F716 /* MASViewAttribute.h */, A8BCCE8C6C17F326AFEDF4357C62ADAF /* MASViewAttribute.m */, D12E9F350C1C8076BE92719B89951AD8 /* MASViewConstraint.h */, 72A95F8027E3EB86CB9AE2D7539201FE /* MASViewConstraint.m */, 30EC6C5D191587619B42076546EDC448 /* NSArray+MASAdditions.h */, 8AEEBD88282BA13360CAA867D8465C75 /* NSArray+MASAdditions.m */, 27E12E3D2779B5C7A8301A94F715DB4C /* NSArray+MASShorthandAdditions.h */, E7851906D7976272A721C8C4E0CE9092 /* NSLayoutConstraint+MASDebugAdditions.h */, 071EEE0A3CE36E163E09EA7F7915F1DE /* NSLayoutConstraint+MASDebugAdditions.m */, 047EE388CF208BD5F57049BD98558C94 /* View+MASAdditions.h */, AF4497913DB548AE2E03103D3A97F34F /* View+MASAdditions.m */, 86765B456E483806C4E13D2DD50E40A4 /* View+MASShorthandAdditions.h */, 55960467D1B758EC688A18A171012E78 /* ViewController+MASAdditions.h */, 342C4D9B5E1E36390E7AF01E35444998 /* ViewController+MASAdditions.m */, C84A449C2DE4F91F0620A5147DD42E0F /* Support Files */, ); path = Masonry; sourceTree = ""; }; 1628BF05B4CAFDCC3549A101F5A10A17 /* Frameworks */ = { isa = PBXGroup; children = ( E2983683FD097A93297E2F5D4E382B36 /* iOS */, ); name = Frameworks; sourceTree = ""; }; 1C467F762175597F044EF6829CDF04C4 /* Support Files */ = { isa = PBXGroup; children = ( 73AF606D61C49DC01DC5C905A43E81D1 /* FMLayoutKit.modulemap */, 80509D0C69E6817F6D85CDF9582F413F /* FMLayoutKit-dummy.m */, 178BBA299FABFEDDD5906B36A1B9467F /* FMLayoutKit-Info.plist */, 9330DB95734C61A9B50053A900E605AD /* FMLayoutKit-prefix.pch */, DEAA326C1902A3E21C96E1592CA9E5F8 /* FMLayoutKit-umbrella.h */, F86E146544D85F28DCC4F98C9C817B3E /* FMLayoutKit.debug.xcconfig */, 25E681D1FE06AC1C1D118CF19E26866A /* FMLayoutKit.release.xcconfig */, ); name = "Support Files"; path = "Example/Pods/Target Support Files/FMLayoutKit"; sourceTree = ""; }; 371CC500889E351021FEAC1E07D282C4 /* Products */ = { isa = PBXGroup; children = ( CD5237ED21769F367AD59FEA53E56403 /* FMLayoutKit.framework */, 1FFED36A657123030ABB700256D73F15 /* Masonry.framework */, 40648A88F893A5F24BF147514CBEF448 /* Pods_FMLayoutKit_Example.framework */, 6E278E08B8933498E6D2169E80346C46 /* Pods_FMLayoutKit_Tests.framework */, ); name = Products; sourceTree = ""; }; 38D5BB81E45E4804D850ED0E4CE55BC0 /* Targets Support Files */ = { isa = PBXGroup; children = ( F00177F0A67E6545F98CB19B124C1C77 /* Pods-FMLayoutKit_Example */, 7AD1B600A784EEF6EB0D1C4DA890842C /* Pods-FMLayoutKit_Tests */, ); name = "Targets Support Files"; sourceTree = ""; }; 521B128D0E16D2ED85B3CD0DC3C5815C /* Pod */ = { isa = PBXGroup; children = ( 3ED09B7CD1A7327639D889668502ABC9 /* FMLayoutKit.podspec */, 3F1CDE96B8DD819AFBC893527CD2D540 /* LICENSE */, 96B17227B74ED7BCB99AA0FD25EE6C40 /* README.md */, ); name = Pod; sourceTree = ""; }; 7529FD53BCE26816CCD46658378AAF1B /* Pods */ = { isa = PBXGroup; children = ( 0CCC0CD98AB951949302B433AFE762AD /* Masonry */, ); name = Pods; sourceTree = ""; }; 770554BE2FB438F7C5558E3AEDB7FC8C /* Sections */ = { isa = PBXGroup; children = ( 7B1FF779F9051E7EBED1D90B22E54DBE /* FMLayoutAbsoluteSection.h */, 2CBE4990B360257A8AA8BAED6177471B /* FMLayoutAbsoluteSection.m */, 04571F5B56E0EDD2CBD13357E25B5C46 /* FMLayoutBaseSection.h */, 5C82D5BFA0B27E8632239CAA6181284C /* FMLayoutBaseSection.m */, 695762AF41ACC2A7AFD29B9B1E1C6862 /* FMLayoutDynamicSection.h */, 96DF14938E1694B50EC1788FF7CC6B31 /* FMLayoutDynamicSection.m */, F7950A8B63A4F538F53B4D0165DAAAAE /* FMLayoutFillSection.h */, 0CA553886878BC7E10C1FFEEA3C1E2E3 /* FMLayoutFillSection.m */, FEB8048D4BBD68AB8C55867A00652E22 /* FMLayoutFixedSection.h */, AB29189261D660E85FDE41FE16816ECD /* FMLayoutFixedSection.m */, B76709D281AC0B27965A319D31A49399 /* FMLayoutLabelSection.h */, CBBED27DA45B26B520D460A4665F4D78 /* FMLayoutLabelSection.m */, C38CD56F24C528CA00D89C9E /* FMLayoutScaleSection.h */, C38CD57024C528CA00D89C9E /* FMLayoutScaleSection.m */, C3C47B9924BAB5B00020C071 /* FMLayoutCombineSection.h */, C3C47B9A24BAB5B00020C071 /* FMLayoutCombineSection.m */, ); name = Sections; path = FMLayoutKit/Classes/Sections; sourceTree = ""; }; 79DB7F77077E34FDB5226D9574592B2D /* Development Pods */ = { isa = PBXGroup; children = ( 815B8D70AFC95F45BD946ADDBC223F2F /* FMLayoutKit */, ); name = "Development Pods"; sourceTree = ""; }; 7AD1B600A784EEF6EB0D1C4DA890842C /* Pods-FMLayoutKit_Tests */ = { isa = PBXGroup; children = ( 45B08C70A4CDCFF6F7EAAB4ADBD47049 /* Pods-FMLayoutKit_Tests.modulemap */, 6C45DA37873F2F0BD195A76D9F212950 /* Pods-FMLayoutKit_Tests-acknowledgements.markdown */, EFB557E32229FE28558ECD4165517E19 /* Pods-FMLayoutKit_Tests-acknowledgements.plist */, 96A04BFBA339CDD9A004F61900B12E32 /* Pods-FMLayoutKit_Tests-dummy.m */, AD9AB32AE99D9D9B67F4E426138CC214 /* Pods-FMLayoutKit_Tests-Info.plist */, F1F3F17D6738600847CCB29087356C28 /* Pods-FMLayoutKit_Tests-umbrella.h */, 1B04B626DB0A83721A64BE176C6E082E /* Pods-FMLayoutKit_Tests.debug.xcconfig */, 96AFA767C03E7AC6D309F8621C7A8CE7 /* Pods-FMLayoutKit_Tests.release.xcconfig */, ); name = "Pods-FMLayoutKit_Tests"; path = "Target Support Files/Pods-FMLayoutKit_Tests"; sourceTree = ""; }; 815B8D70AFC95F45BD946ADDBC223F2F /* FMLayoutKit */ = { isa = PBXGroup; children = ( C397387F248F716E00A7A2C2 /* FMLayoutKit.h */, C3A262902499EC06000A269D /* FMLayoutDebugLog.h */, C3A262912499EC06000A269D /* FMLayoutDebugLog.m */, F306E024590AF9CC027DBBAB232B73E3 /* FMCollectionLayoutAttributes.h */, 29B4ADEDC659AD492EE7CC526FDF7DD8 /* FMCollectionLayoutAttributes.m */, C0E86FA9D29C2710D6F80866B0E2EA75 /* FMKVOArrayObject.h */, AAF19FCABA3E0F39CA988DE97736C2C3 /* FMKVOArrayObject.m */, C306258124986E6A000243D4 /* FMLayout.h */, C306258224986E6A000243D4 /* FMLayout.m */, FC09401D363564893FFA81BCD727C206 /* FMLayoutView.h */, 27F4B838AAA41DA3AFC042162BE57A14 /* FMLayoutView.m */, C3808B72261F4FD10013501C /* _FMLayoutSussEmptyView.h */, C3808B73261F4FD10013501C /* _FMLayoutSussEmptyView.m */, B176EB4D307EA30B2F3A1980CAD83A70 /* FMTeslaLayoutView.h */, 6F3D0D5CF65ED9C7476ADC49BD08B176 /* FMTeslaLayoutView.m */, CA6102B5FF7D583B8C2C690205DE20A4 /* FMTeslaSuspensionHeightChangeDelegate.h */, C38CB4B0260EC0B500E1C3AA /* FMCollectionViewDelegateDataSourceProvider.h */, C38CB4B1260EC0B500E1C3AA /* FMCollectionViewDelegateDataSourceProvider.m */, C38CB4B8260EC4B800E1C3AA /* UIView+FMLayout.h */, C38CB4B9260EC4B800E1C3AA /* UIView+FMLayout.m */, FDD5EA2B508FBDBE1A7E2C95FAB84874 /* Element */, F64D6E01665608365589F24F63B8FA36 /* Cross */, 521B128D0E16D2ED85B3CD0DC3C5815C /* Pod */, 770554BE2FB438F7C5558E3AEDB7FC8C /* Sections */, 1C467F762175597F044EF6829CDF04C4 /* Support Files */, ); name = FMLayoutKit; path = ../..; sourceTree = ""; }; C84A449C2DE4F91F0620A5147DD42E0F /* Support Files */ = { isa = PBXGroup; children = ( 3E537C1F47DA8B06DA4A71E3D14F4DE4 /* Masonry.modulemap */, A85AE9E36F67A1B513CB8DA940771B4F /* Masonry-dummy.m */, DFA1012B6A8BD076CD9F09831AE37A01 /* Masonry-Info.plist */, BDB676D9D5D3AFD89D8DDCE3369D4BAC /* Masonry-prefix.pch */, 6CF8069504999FB8BF5FA1529175AA74 /* Masonry-umbrella.h */, F287598D192FA586BD4AECCD85B988A4 /* Masonry.debug.xcconfig */, 419A961AD957E23BAB6A998ED7623134 /* Masonry.release.xcconfig */, ); name = "Support Files"; path = "../Target Support Files/Masonry"; sourceTree = ""; }; CF1408CF629C7361332E53B88F7BD30C = { isa = PBXGroup; children = ( 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */, 79DB7F77077E34FDB5226D9574592B2D /* Development Pods */, 1628BF05B4CAFDCC3549A101F5A10A17 /* Frameworks */, 7529FD53BCE26816CCD46658378AAF1B /* Pods */, 371CC500889E351021FEAC1E07D282C4 /* Products */, 38D5BB81E45E4804D850ED0E4CE55BC0 /* Targets Support Files */, ); sourceTree = ""; }; E2983683FD097A93297E2F5D4E382B36 /* iOS */ = { isa = PBXGroup; children = ( 436BAA54A31999B53B3CC7115C55FE50 /* Foundation.framework */, 312B988EF117AE4DE76A268D970131FE /* UIKit.framework */, ); name = iOS; sourceTree = ""; }; F00177F0A67E6545F98CB19B124C1C77 /* Pods-FMLayoutKit_Example */ = { isa = PBXGroup; children = ( 2DB747C7C5D095FAD7DC101195534913 /* Pods-FMLayoutKit_Example.modulemap */, 15A006ECDF5E6A5D581F64FB6602E2BC /* Pods-FMLayoutKit_Example-acknowledgements.markdown */, E1C00F6DE5FCEE0DA9B533ADB640314A /* Pods-FMLayoutKit_Example-acknowledgements.plist */, 8F8ADAA65E2E1F0E9F75CE99DD2523EA /* Pods-FMLayoutKit_Example-dummy.m */, F2293961BF15DE3D3E5DE9FBAADCAFA2 /* Pods-FMLayoutKit_Example-frameworks.sh */, 27C923CEC19AD2AE1D49E900B465DE2E /* Pods-FMLayoutKit_Example-Info.plist */, B263B7AE65E097574862F32234C5F0A8 /* Pods-FMLayoutKit_Example-umbrella.h */, 0C3D35D65006895D8FEC2D259FACD724 /* Pods-FMLayoutKit_Example.debug.xcconfig */, 70EF59D03E8E18F7F4A4759C9D883F45 /* Pods-FMLayoutKit_Example.release.xcconfig */, ); name = "Pods-FMLayoutKit_Example"; path = "Target Support Files/Pods-FMLayoutKit_Example"; sourceTree = ""; }; F64D6E01665608365589F24F63B8FA36 /* Cross */ = { isa = PBXGroup; children = ( C30625892498CC06000243D4 /* FMLayoutCrossSection.h */, C306258A2498CC06000243D4 /* FMLayoutCrossSection.m */, C399ACAB24BECF8500DD02EE /* FMLayoutCrossTransformSection.h */, C399ACAC24BECF8500DD02EE /* FMLayoutCrossTransformSection.m */, C30625852498CABA000243D4 /* FMLayoutCrossCell.h */, C30625862498CABA000243D4 /* FMLayoutCrossCell.m */, ); name = Cross; path = FMLayoutKit/Classes/Cross; sourceTree = ""; }; FDD5EA2B508FBDBE1A7E2C95FAB84874 /* Element */ = { isa = PBXGroup; children = ( E57ABA024D08EDE3371F3F3C62400CAE /* FMLayoutBackground.h */, C88C69EDAC1D1808A8CBEADA2477ABC8 /* FMLayoutBackground.m */, F9E17FEA74C0D603C0DEE059C5833D59 /* FMLayoutElement.h */, 27EDA7901C9F630F428E06BD9DDE8D2A /* FMLayoutElement.m */, BE6875EFE2C29C824642C4EBEF334C30 /* FMLayoutFooter.h */, 8B03A6B14FC8CDE4DE74F867FC4F7F65 /* FMLayoutFooter.m */, F1BA5D5862C57CC3644C9D0385D221AC /* FMLayoutHeader.h */, 8D4503ED6C470BF67C1AB6E9BFE8560C /* FMLayoutHeader.m */, 7A6BACBBBAF66F4EAF255239F54D56EA /* FMSupplementary.h */, 757A4B6AAA8326254A2E25CCE4363522 /* FMSupplementary.m */, ); name = Element; path = FMLayoutKit/Classes/Element; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ 7B04ACBA4522760CA66A5D4AFA498F81 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( 8D65CE579E516BDD5FB36CAA21D693F6 /* MASCompositeConstraint.h in Headers */, 9D546E1168C04B0B2EAE005D9275D18B /* MASConstraint+Private.h in Headers */, 941955A19C40899D275604E6E9C21A6D /* MASConstraint.h in Headers */, FAFBFA90F7BC3E7CF50F8A5CF0A8B264 /* MASConstraintMaker.h in Headers */, 8D4D1F6E4709EBB13974E95DC1059DDC /* MASLayoutConstraint.h in Headers */, 6A6AD3A5BBDBFD0B4AF936BD518EC0B1 /* Masonry-umbrella.h in Headers */, 346080C0D1CA23399ADD739D722D7CEF /* Masonry.h in Headers */, 280D36330BAC5715615FF4A8B42D60D6 /* MASUtilities.h in Headers */, 3DA5F1D8E51CDD102A871C2F37770C7B /* MASViewAttribute.h in Headers */, EAE8B0895956885A752B173683A0D889 /* MASViewConstraint.h in Headers */, 05EA1447EEA0EB669F8DEE73964A7C60 /* NSArray+MASAdditions.h in Headers */, 05A040F35BF1C88F869404E1A940B493 /* NSArray+MASShorthandAdditions.h in Headers */, 0AF1AD35706D90B1A91F291B899EF8C0 /* NSLayoutConstraint+MASDebugAdditions.h in Headers */, 4B0981F9AC628CF5100C50FF4A163A4A /* View+MASAdditions.h in Headers */, E7CA20228B3583F41927813EE904CAD3 /* View+MASShorthandAdditions.h in Headers */, 8B92011C9373001132C8148BFC8F50B3 /* ViewController+MASAdditions.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; AF3E507B4594F1F2D455490399DA6945 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( DE71BF9E8478FF8DA2C96CD2B630C39E /* FMCollectionLayoutAttributes.h in Headers */, B67FA646712B7183A3742DE39A61BE2C /* FMKVOArrayObject.h in Headers */, D240D2B05DDD6EABBFDF67F8E42921A4 /* FMLayoutAbsoluteSection.h in Headers */, 17B1B66CD4133C22EB8356A617AC6D6B /* FMLayoutBackground.h in Headers */, F19C07B7E88762246953AF01071B2E24 /* FMLayoutBaseSection.h in Headers */, 1D02BDC76EBE6C218E5DCF6DE7312674 /* FMLayoutDynamicSection.h in Headers */, C3808B74261F4FD10013501C /* _FMLayoutSussEmptyView.h in Headers */, B9EB397E56BC70BDD925430719BC6329 /* FMLayoutElement.h in Headers */, 03480CAA966B43707E614B04EF182226 /* FMLayoutFillSection.h in Headers */, C3C47B9B24BAB5B00020C071 /* FMLayoutCombineSection.h in Headers */, A65EAC754DF091EB22BCC40FFF0F1D35 /* FMLayoutFixedSection.h in Headers */, 82F24F7CB465BA0393889419603DE536 /* FMLayoutFooter.h in Headers */, 3E6BAAA0B701F41E9E589822F97BF3AF /* FMLayoutHeader.h in Headers */, C306258324986E6A000243D4 /* FMLayout.h in Headers */, C3A262922499EC06000A269D /* FMLayoutDebugLog.h in Headers */, 71C79BAA01DF9FE5DAA86B75A507F253 /* FMLayoutKit-umbrella.h in Headers */, 92DA6DE8550689C4F76DBFB01A460124 /* FMLayoutLabelSection.h in Headers */, C38CD57124C528CA00D89C9E /* FMLayoutScaleSection.h in Headers */, C3973880248F716E00A7A2C2 /* FMLayoutKit.h in Headers */, C306258B2498CC06000243D4 /* FMLayoutCrossSection.h in Headers */, 98313EE28994F7745E8E60C1FC4EBB7A /* FMLayoutView.h in Headers */, C399ACAD24BECF8500DD02EE /* FMLayoutCrossTransformSection.h in Headers */, C30625872498CABA000243D4 /* FMLayoutCrossCell.h in Headers */, 0036C8E1BBB2FF8C9EC7B0B1AAFD23DF /* FMSupplementary.h in Headers */, C38CB4BA260EC4B800E1C3AA /* UIView+FMLayout.h in Headers */, C38CB4B2260EC0B500E1C3AA /* FMCollectionViewDelegateDataSourceProvider.h in Headers */, 8475566499CB6BE91D3D16D549E3EB2D /* FMTeslaLayoutView.h in Headers */, 72B72B650AF3C690635A54BE8356662C /* FMTeslaSuspensionHeightChangeDelegate.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; BF2DE328125FA10F1B743B8AE594F125 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( FCCB987C9E8C8D7CC4D2C42DD86BAABF /* Pods-FMLayoutKit_Tests-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; D856990D5B161FAE88855E064DF8CB26 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( 7AC2FC49B351E793717BFC9DA6B333C5 /* Pods-FMLayoutKit_Example-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ 36F6AC16E4AD8E1A010DDD02352D58B1 /* Pods-FMLayoutKit_Tests */ = { isa = PBXNativeTarget; buildConfigurationList = F9CE1300BDF0147EB7E5882FE011F66B /* Build configuration list for PBXNativeTarget "Pods-FMLayoutKit_Tests" */; buildPhases = ( BF2DE328125FA10F1B743B8AE594F125 /* Headers */, 9F952A29AE3D4C491373827B49E6C3EC /* Sources */, C3DF58F3D2435E31C755240BC1445BF6 /* Frameworks */, DD013282352D4431C34E71EF4B7C0F09 /* Resources */, ); buildRules = ( ); dependencies = ( E9DDAAACCA7F20D436F63DFF1F367546 /* PBXTargetDependency */, ); name = "Pods-FMLayoutKit_Tests"; productName = "Pods-FMLayoutKit_Tests"; productReference = 6E278E08B8933498E6D2169E80346C46 /* Pods_FMLayoutKit_Tests.framework */; productType = "com.apple.product-type.framework"; }; 55AF53E6C77A10ED4985E04D74A8878E /* Masonry */ = { isa = PBXNativeTarget; buildConfigurationList = 87FD40BD683E3BD044AA4D1B5CA58652 /* Build configuration list for PBXNativeTarget "Masonry" */; buildPhases = ( 7B04ACBA4522760CA66A5D4AFA498F81 /* Headers */, 038B428AD06C5A47FAF2BEFE16C6DC16 /* Sources */, 5E047F76604659BF1B2099B2C412AC93 /* Frameworks */, 895ED1B8779C1D82DF681CBFF67AC570 /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Masonry; productName = Masonry; productReference = 1FFED36A657123030ABB700256D73F15 /* Masonry.framework */; productType = "com.apple.product-type.framework"; }; B2FC59B39F266A918806E8EA1301C377 /* FMLayoutKit */ = { isa = PBXNativeTarget; buildConfigurationList = 6A145D0DBF33ABE959D817689CD5996D /* Build configuration list for PBXNativeTarget "FMLayoutKit" */; buildPhases = ( AF3E507B4594F1F2D455490399DA6945 /* Headers */, DCA6E53AE9B631BF1708850006DA4F30 /* Sources */, CF309522E666ABB1561A51BD4788BA50 /* Frameworks */, 1F669A1356963AD7260892AE3AE4CD98 /* Resources */, ); buildRules = ( ); dependencies = ( ); name = FMLayoutKit; productName = FMLayoutKit; productReference = CD5237ED21769F367AD59FEA53E56403 /* FMLayoutKit.framework */; productType = "com.apple.product-type.framework"; }; DA993AD93696E1200894CB71CBC71FA9 /* Pods-FMLayoutKit_Example */ = { isa = PBXNativeTarget; buildConfigurationList = EC90C08AF5A25F039BCB00E55C8759F9 /* Build configuration list for PBXNativeTarget "Pods-FMLayoutKit_Example" */; buildPhases = ( D856990D5B161FAE88855E064DF8CB26 /* Headers */, E186AACF279867E6B8B545FA0E5333A7 /* Sources */, 34491089D9993E01EB0F5DD7FFB1F651 /* Frameworks */, 144725C5BB6287765BFF7FF082E00C64 /* Resources */, ); buildRules = ( ); dependencies = ( D7D87E083A850272A709E01F7A230835 /* PBXTargetDependency */, 6E778B6AB4A92700C4E9420C40F249D5 /* PBXTargetDependency */, ); name = "Pods-FMLayoutKit_Example"; productName = "Pods-FMLayoutKit_Example"; productReference = 40648A88F893A5F24BF147514CBEF448 /* Pods_FMLayoutKit_Example.framework */; productType = "com.apple.product-type.framework"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ BFDFE7DC352907FC980B868725387E98 /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 1100; LastUpgradeCheck = 1100; }; buildConfigurationList = 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = CF1408CF629C7361332E53B88F7BD30C; productRefGroup = 371CC500889E351021FEAC1E07D282C4 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( B2FC59B39F266A918806E8EA1301C377 /* FMLayoutKit */, 55AF53E6C77A10ED4985E04D74A8878E /* Masonry */, DA993AD93696E1200894CB71CBC71FA9 /* Pods-FMLayoutKit_Example */, 36F6AC16E4AD8E1A010DDD02352D58B1 /* Pods-FMLayoutKit_Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 144725C5BB6287765BFF7FF082E00C64 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; 1F669A1356963AD7260892AE3AE4CD98 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; 895ED1B8779C1D82DF681CBFF67AC570 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; DD013282352D4431C34E71EF4B7C0F09 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 038B428AD06C5A47FAF2BEFE16C6DC16 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 7BFF65958F014760B6AC4742824892EB /* MASCompositeConstraint.m in Sources */, E8DD5D1D406150E1C80AD015271B6848 /* MASConstraint.m in Sources */, 78B2727EE5D693F58D019DB098005101 /* MASConstraintMaker.m in Sources */, 8539B851E01A58467BE49CA3FA77223C /* MASLayoutConstraint.m in Sources */, 1972E85F0FCD0F3EAF28ED7CD036286E /* Masonry-dummy.m in Sources */, 297A3627CF2F032CBFDC61D1A3786E63 /* MASViewAttribute.m in Sources */, B7D645EC004610E8A581E532D28771EC /* MASViewConstraint.m in Sources */, 098630ECDB64ED7B89F5F687C82B4AC3 /* NSArray+MASAdditions.m in Sources */, C0861ADB4C5FA30F4F9E051F7638A264 /* NSLayoutConstraint+MASDebugAdditions.m in Sources */, A35FBEEC7D088AEC05297E8292A32C77 /* View+MASAdditions.m in Sources */, 0967598607D521318F69D7D39D517B20 /* ViewController+MASAdditions.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 9F952A29AE3D4C491373827B49E6C3EC /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( CA9FF2872811CDA655E6C77C620BCD05 /* Pods-FMLayoutKit_Tests-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; DCA6E53AE9B631BF1708850006DA4F30 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 8B86204F0349A782F91323459449CD0B /* FMCollectionLayoutAttributes.m in Sources */, C30625882498CABA000243D4 /* FMLayoutCrossCell.m in Sources */, C38CB4B3260EC0B500E1C3AA /* FMCollectionViewDelegateDataSourceProvider.m in Sources */, 4F5212C040672D2776544CAA39A4FCCE /* FMKVOArrayObject.m in Sources */, 3EABA5C42467DAD253F1AF5ADA7EB3F3 /* FMLayoutAbsoluteSection.m in Sources */, C3C47B9C24BAB5B00020C071 /* FMLayoutCombineSection.m in Sources */, EAEF0BFE8D36DCB4694B7D396DD97AAE /* FMLayoutBackground.m in Sources */, C306258424986E6A000243D4 /* FMLayout.m in Sources */, C3A262932499EC06000A269D /* FMLayoutDebugLog.m in Sources */, ECC24C178FF280A0D8F0C329AC7D59A7 /* FMLayoutBaseSection.m in Sources */, F7F785200308DA7B9636000E2D47F4A8 /* FMLayoutDynamicSection.m in Sources */, B08C380708F0F4816D1E2BE5D199B9C7 /* FMLayoutElement.m in Sources */, BF5C569DA64FD9C3EEEF8E536A7A806C /* FMLayoutFillSection.m in Sources */, 1022317B997FE907CDCD25317B4A071F /* FMLayoutFixedSection.m in Sources */, 2BF16135E62ABD244F9394C280B06EE8 /* FMLayoutFooter.m in Sources */, C399ACAE24BECF8500DD02EE /* FMLayoutCrossTransformSection.m in Sources */, B915FCFC0E255F43F5A4049082E68D95 /* FMLayoutHeader.m in Sources */, C38CB4BB260EC4B800E1C3AA /* UIView+FMLayout.m in Sources */, C306258C2498CC06000243D4 /* FMLayoutCrossSection.m in Sources */, F4C5DC6114CB65244093D6A8DA36B005 /* FMLayoutKit-dummy.m in Sources */, 6ED2198EBA016B6DA6627F67D251986C /* FMLayoutLabelSection.m in Sources */, C3808B75261F4FD10013501C /* _FMLayoutSussEmptyView.m in Sources */, 5E69AAA6E15FDFECAA93CBAEC53577BC /* FMLayoutView.m in Sources */, F977A8588FE03966589260ECDE5CCEC5 /* FMSupplementary.m in Sources */, BA16C547F6B3F33429F514A9C7C998F0 /* FMTeslaLayoutView.m in Sources */, C38CD57224C528CA00D89C9E /* FMLayoutScaleSection.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; E186AACF279867E6B8B545FA0E5333A7 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 940A8C4C1195ACC5EB26CF6DB55B4D02 /* Pods-FMLayoutKit_Example-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ 6E778B6AB4A92700C4E9420C40F249D5 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = Masonry; target = 55AF53E6C77A10ED4985E04D74A8878E /* Masonry */; targetProxy = 533CAF9A4A9C7831C1D4CCB6A5125581 /* PBXContainerItemProxy */; }; D7D87E083A850272A709E01F7A230835 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = FMLayoutKit; target = B2FC59B39F266A918806E8EA1301C377 /* FMLayoutKit */; targetProxy = 5A308C6B23658D4BCECD24DEBBF83C5E /* PBXContainerItemProxy */; }; E9DDAAACCA7F20D436F63DFF1F367546 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Pods-FMLayoutKit_Example"; target = DA993AD93696E1200894CB71CBC71FA9 /* Pods-FMLayoutKit_Example */; targetProxy = 99FF2E4998226FB31D16609CDE458316 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ 0B6225DA3EBEE01DDD79234D59236C14 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 0C3D35D65006895D8FEC2D259FACD724 /* Pods-FMLayoutKit_Example.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = "Target Support Files/Pods-FMLayoutKit_Example/Pods-FMLayoutKit_Example-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; MODULEMAP_FILE = "Target Support Files/Pods-FMLayoutKit_Example/Pods-FMLayoutKit_Example.modulemap"; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Debug; }; 34CBD7E6AAA07FBAFD01D1D6955D9B8A /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = F86E146544D85F28DCC4F98C9C817B3E /* FMLayoutKit.debug.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; GCC_PREFIX_HEADER = "Target Support Files/FMLayoutKit/FMLayoutKit-prefix.pch"; INFOPLIST_FILE = "Target Support Files/FMLayoutKit/FMLayoutKit-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MODULEMAP_FILE = "Target Support Files/FMLayoutKit/FMLayoutKit.modulemap"; PRODUCT_MODULE_NAME = FMLayoutKit; PRODUCT_NAME = FMLayoutKit; SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Debug; }; 4BE66A09A74FD25164AAB3C2645B9B93 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "POD_CONFIGURATION_RELEASE=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; STRIP_INSTALLED_PRODUCT = NO; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_VERSION = 5.0; SYMROOT = "${SRCROOT}/../build"; }; name = Release; }; 6937BDCA511479ACC614AF0793FFC06E /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 419A961AD957E23BAB6A998ED7623134 /* Masonry.release.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; GCC_PREFIX_HEADER = "Target Support Files/Masonry/Masonry-prefix.pch"; INFOPLIST_FILE = "Target Support Files/Masonry/Masonry-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MODULEMAP_FILE = "Target Support Files/Masonry/Masonry.modulemap"; PRODUCT_MODULE_NAME = Masonry; PRODUCT_NAME = Masonry; SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Release; }; 7EE6C529993B6A9390049C88518DD3DB /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 1B04B626DB0A83721A64BE176C6E082E /* Pods-FMLayoutKit_Tests.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = "Target Support Files/Pods-FMLayoutKit_Tests/Pods-FMLayoutKit_Tests-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; MODULEMAP_FILE = "Target Support Files/Pods-FMLayoutKit_Tests/Pods-FMLayoutKit_Tests.modulemap"; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Debug; }; 7EF7227D9B20A1D549000096ACCB23D7 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "POD_CONFIGURATION_DEBUG=1", "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; STRIP_INSTALLED_PRODUCT = NO; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; SYMROOT = "${SRCROOT}/../build"; }; name = Debug; }; C746FC4CB0A99DA239378D15BEEA700E /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 25E681D1FE06AC1C1D118CF19E26866A /* FMLayoutKit.release.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; GCC_PREFIX_HEADER = "Target Support Files/FMLayoutKit/FMLayoutKit-prefix.pch"; INFOPLIST_FILE = "Target Support Files/FMLayoutKit/FMLayoutKit-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MODULEMAP_FILE = "Target Support Files/FMLayoutKit/FMLayoutKit.modulemap"; PRODUCT_MODULE_NAME = FMLayoutKit; PRODUCT_NAME = FMLayoutKit; SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Release; }; D45B0094A457EE4A52D5D84A8A18BEA5 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = F287598D192FA586BD4AECCD85B988A4 /* Masonry.debug.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; GCC_PREFIX_HEADER = "Target Support Files/Masonry/Masonry-prefix.pch"; INFOPLIST_FILE = "Target Support Files/Masonry/Masonry-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MODULEMAP_FILE = "Target Support Files/Masonry/Masonry.modulemap"; PRODUCT_MODULE_NAME = Masonry; PRODUCT_NAME = Masonry; SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Debug; }; E1168A46214C44E7C5302E01299A52E9 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 70EF59D03E8E18F7F4A4759C9D883F45 /* Pods-FMLayoutKit_Example.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = "Target Support Files/Pods-FMLayoutKit_Example/Pods-FMLayoutKit_Example-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; MODULEMAP_FILE = "Target Support Files/Pods-FMLayoutKit_Example/Pods-FMLayoutKit_Example.modulemap"; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Release; }; F9F3ADC7D256F79C6152AA54E3396746 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 96AFA767C03E7AC6D309F8621C7A8CE7 /* Pods-FMLayoutKit_Tests.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = "Target Support Files/Pods-FMLayoutKit_Tests/Pods-FMLayoutKit_Tests-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; MODULEMAP_FILE = "Target Support Files/Pods-FMLayoutKit_Tests/Pods-FMLayoutKit_Tests.modulemap"; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { isa = XCConfigurationList; buildConfigurations = ( 7EF7227D9B20A1D549000096ACCB23D7 /* Debug */, 4BE66A09A74FD25164AAB3C2645B9B93 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 6A145D0DBF33ABE959D817689CD5996D /* Build configuration list for PBXNativeTarget "FMLayoutKit" */ = { isa = XCConfigurationList; buildConfigurations = ( 34CBD7E6AAA07FBAFD01D1D6955D9B8A /* Debug */, C746FC4CB0A99DA239378D15BEEA700E /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 87FD40BD683E3BD044AA4D1B5CA58652 /* Build configuration list for PBXNativeTarget "Masonry" */ = { isa = XCConfigurationList; buildConfigurations = ( D45B0094A457EE4A52D5D84A8A18BEA5 /* Debug */, 6937BDCA511479ACC614AF0793FFC06E /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; EC90C08AF5A25F039BCB00E55C8759F9 /* Build configuration list for PBXNativeTarget "Pods-FMLayoutKit_Example" */ = { isa = XCConfigurationList; buildConfigurations = ( 0B6225DA3EBEE01DDD79234D59236C14 /* Debug */, E1168A46214C44E7C5302E01299A52E9 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; F9CE1300BDF0147EB7E5882FE011F66B /* Build configuration list for PBXNativeTarget "Pods-FMLayoutKit_Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7EE6C529993B6A9390049C88518DD3DB /* Debug */, F9F3ADC7D256F79C6152AA54E3396746 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = BFDFE7DC352907FC980B868725387E98 /* Project object */; } ================================================ FILE: Example/Pods/Target Support Files/FMLayoutKit/FMLayoutKit-Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier ${PRODUCT_BUNDLE_IDENTIFIER} CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType FMWK CFBundleShortVersionString 1.0.0 CFBundleSignature ???? CFBundleVersion ${CURRENT_PROJECT_VERSION} NSPrincipalClass ================================================ FILE: Example/Pods/Target Support Files/FMLayoutKit/FMLayoutKit-dummy.m ================================================ #import @interface PodsDummy_FMLayoutKit : NSObject @end @implementation PodsDummy_FMLayoutKit @end ================================================ FILE: Example/Pods/Target Support Files/FMLayoutKit/FMLayoutKit-prefix.pch ================================================ #ifdef __OBJC__ #import #else #ifndef FOUNDATION_EXPORT #if defined(__cplusplus) #define FOUNDATION_EXPORT extern "C" #else #define FOUNDATION_EXPORT extern #endif #endif #endif ================================================ FILE: Example/Pods/Target Support Files/FMLayoutKit/FMLayoutKit-umbrella.h ================================================ #ifdef __OBJC__ #import #else #ifndef FOUNDATION_EXPORT #if defined(__cplusplus) #define FOUNDATION_EXPORT extern "C" #else #define FOUNDATION_EXPORT extern #endif #endif #endif #import "FMLayoutBackground.h" #import "FMLayoutElement.h" #import "FMLayoutFooter.h" #import "FMLayoutHeader.h" #import "FMSupplementary.h" #import "FMCollectionLayoutAttributes.h" #import "FMKVOArrayObject.h" #import "FMLayout.h" #import "FMLayoutView.h" #import "FMTeslaLayoutView.h" #import "FMTeslaSuspensionHeightChangeDelegate.h" #import "FMLayoutCrossSection.h" #import "FMLayoutAbsoluteSection.h" #import "FMLayoutBaseSection.h" #import "FMLayoutDynamicSection.h" #import "FMLayoutFillSection.h" #import "FMLayoutFixedSection.h" #import "FMLayoutLabelSection.h" FOUNDATION_EXPORT double FMLayoutKitVersionNumber; FOUNDATION_EXPORT const unsigned char FMLayoutKitVersionString[]; ================================================ FILE: Example/Pods/Target Support Files/FMLayoutKit/FMLayoutKit.debug.xcconfig ================================================ CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FMLayoutKit GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_ROOT = ${SRCROOT} PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} SKIP_INSTALL = YES USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES ================================================ FILE: Example/Pods/Target Support Files/FMLayoutKit/FMLayoutKit.modulemap ================================================ framework module FMLayoutKit { umbrella header "FMLayoutKit-umbrella.h" export * module * { export * } } ================================================ FILE: Example/Pods/Target Support Files/FMLayoutKit/FMLayoutKit.release.xcconfig ================================================ CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FMLayoutKit GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_ROOT = ${SRCROOT} PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} SKIP_INSTALL = YES USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES ================================================ FILE: Example/Pods/Target Support Files/Masonry/Masonry-Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier ${PRODUCT_BUNDLE_IDENTIFIER} CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType FMWK CFBundleShortVersionString 1.1.0 CFBundleSignature ???? CFBundleVersion ${CURRENT_PROJECT_VERSION} NSPrincipalClass ================================================ FILE: Example/Pods/Target Support Files/Masonry/Masonry-dummy.m ================================================ #import @interface PodsDummy_Masonry : NSObject @end @implementation PodsDummy_Masonry @end ================================================ FILE: Example/Pods/Target Support Files/Masonry/Masonry-prefix.pch ================================================ #ifdef __OBJC__ #import #else #ifndef FOUNDATION_EXPORT #if defined(__cplusplus) #define FOUNDATION_EXPORT extern "C" #else #define FOUNDATION_EXPORT extern #endif #endif #endif ================================================ FILE: Example/Pods/Target Support Files/Masonry/Masonry-umbrella.h ================================================ #ifdef __OBJC__ #import #else #ifndef FOUNDATION_EXPORT #if defined(__cplusplus) #define FOUNDATION_EXPORT extern "C" #else #define FOUNDATION_EXPORT extern #endif #endif #endif #import "MASCompositeConstraint.h" #import "MASConstraint+Private.h" #import "MASConstraint.h" #import "MASConstraintMaker.h" #import "MASLayoutConstraint.h" #import "Masonry.h" #import "MASUtilities.h" #import "MASViewAttribute.h" #import "MASViewConstraint.h" #import "NSArray+MASAdditions.h" #import "NSArray+MASShorthandAdditions.h" #import "NSLayoutConstraint+MASDebugAdditions.h" #import "View+MASAdditions.h" #import "View+MASShorthandAdditions.h" #import "ViewController+MASAdditions.h" FOUNDATION_EXPORT double MasonryVersionNumber; FOUNDATION_EXPORT const unsigned char MasonryVersionString[]; ================================================ FILE: Example/Pods/Target Support Files/Masonry/Masonry.debug.xcconfig ================================================ CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Masonry GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 OTHER_LDFLAGS = $(inherited) -framework "Foundation" -framework "UIKit" PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_ROOT = ${SRCROOT} PODS_TARGET_SRCROOT = ${PODS_ROOT}/Masonry PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} SKIP_INSTALL = YES USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES ================================================ FILE: Example/Pods/Target Support Files/Masonry/Masonry.modulemap ================================================ framework module Masonry { umbrella header "Masonry-umbrella.h" export * module * { export * } } ================================================ FILE: Example/Pods/Target Support Files/Masonry/Masonry.release.xcconfig ================================================ CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Masonry GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 OTHER_LDFLAGS = $(inherited) -framework "Foundation" -framework "UIKit" PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_ROOT = ${SRCROOT} PODS_TARGET_SRCROOT = ${PODS_ROOT}/Masonry PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} SKIP_INSTALL = YES USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES ================================================ FILE: Example/Pods/Target Support Files/Pods-FMLayoutKit_Example/Pods-FMLayoutKit_Example-Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier ${PRODUCT_BUNDLE_IDENTIFIER} CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType FMWK CFBundleShortVersionString 1.0.0 CFBundleSignature ???? CFBundleVersion ${CURRENT_PROJECT_VERSION} NSPrincipalClass ================================================ FILE: Example/Pods/Target Support Files/Pods-FMLayoutKit_Example/Pods-FMLayoutKit_Example-acknowledgements.markdown ================================================ # Acknowledgements This application makes use of the following third party libraries: ## FMLayoutKit Copyright (c) 2020 zhoufaming251@163.com Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ## Masonry Copyright (c) 2011-2012 Masonry Team - https://github.com/Masonry Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Generated by CocoaPods - https://cocoapods.org ================================================ FILE: Example/Pods/Target Support Files/Pods-FMLayoutKit_Example/Pods-FMLayoutKit_Example-acknowledgements.plist ================================================ PreferenceSpecifiers FooterText This application makes use of the following third party libraries: Title Acknowledgements Type PSGroupSpecifier FooterText Copyright (c) 2020 zhoufaming251@163.com <zhoufaming251@163.com> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. License MIT Title FMLayoutKit Type PSGroupSpecifier FooterText Copyright (c) 2011-2012 Masonry Team - https://github.com/Masonry Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. License MIT Title Masonry Type PSGroupSpecifier FooterText Generated by CocoaPods - https://cocoapods.org Title Type PSGroupSpecifier StringsTable Acknowledgements Title Acknowledgements ================================================ FILE: Example/Pods/Target Support Files/Pods-FMLayoutKit_Example/Pods-FMLayoutKit_Example-dummy.m ================================================ #import @interface PodsDummy_Pods_FMLayoutKit_Example : NSObject @end @implementation PodsDummy_Pods_FMLayoutKit_Example @end ================================================ FILE: Example/Pods/Target Support Files/Pods-FMLayoutKit_Example/Pods-FMLayoutKit_Example-frameworks.sh ================================================ #!/bin/sh set -e set -u set -o pipefail function on_error { echo "$(realpath -mq "${0}"):$1: error: Unexpected failure" } trap 'on_error $LINENO' ERR if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy # frameworks to, so exit 0 (signalling the script phase was successful). exit 0 fi echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" # Used as a return value for each invocation of `strip_invalid_archs` function. STRIP_BINARY_RETVAL=0 # This protects against multiple targets copying the same framework dependency at the same time. The solution # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") # Copies and strips a vendored framework install_framework() { if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then local source="${BUILT_PRODUCTS_DIR}/$1" elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" elif [ -r "$1" ]; then local source="$1" fi local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" if [ -L "${source}" ]; then echo "Symlinked..." source="$(readlink "${source}")" fi # Use filter instead of exclude so missing patterns don't throw errors. echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" local basename basename="$(basename -s .framework "$1")" binary="${destination}/${basename}.framework/${basename}" if ! [ -r "$binary" ]; then binary="${destination}/${basename}" elif [ -L "${binary}" ]; then echo "Destination binary is symlinked..." dirname="$(dirname "${binary}")" binary="${dirname}/$(readlink "${binary}")" fi # Strip invalid architectures so "fat" simulator / device frameworks work on device if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then strip_invalid_archs "$binary" fi # Resign the code if required by the build settings to avoid unstable apps code_sign_if_enabled "${destination}/$(basename "$1")" # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then local swift_runtime_libs swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u) for lib in $swift_runtime_libs; do echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" code_sign_if_enabled "${destination}/${lib}" done fi } # Copies and strips a vendored dSYM install_dsym() { local source="$1" warn_missing_arch=${2:-true} if [ -r "$source" ]; then # Copy the dSYM into the targets temp dir. echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" local basename basename="$(basename -s .dSYM "$source")" binary_name="$(ls "$source/Contents/Resources/DWARF")" binary="${DERIVED_FILES_DIR}/${basename}.dSYM/Contents/Resources/DWARF/${binary_name}" # Strip invalid architectures so "fat" simulator / device frameworks work on device if [[ "$(file "$binary")" == *"Mach-O "*"dSYM companion"* ]]; then strip_invalid_archs "$binary" "$warn_missing_arch" fi if [[ $STRIP_BINARY_RETVAL == 1 ]]; then # Move the stripped file into its final destination. echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.dSYM" "${DWARF_DSYM_FOLDER_PATH}" else # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.dSYM" fi fi } # Copies the bcsymbolmap files of a vendored framework install_bcsymbolmap() { local bcsymbolmap_path="$1" local destination="${BUILT_PRODUCTS_DIR}" echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}"" rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}" } # Signs a framework with the provided identity code_sign_if_enabled() { if [ -n "${EXPANDED_CODE_SIGN_IDENTITY:-}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then # Use the current code_sign_identity echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then code_sign_cmd="$code_sign_cmd &" fi echo "$code_sign_cmd" eval "$code_sign_cmd" fi } # Strip invalid architectures strip_invalid_archs() { binary="$1" warn_missing_arch=${2:-true} # Get architectures for current target binary binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" # Intersect them with the architectures we are building for intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" # If there are no archs supported by this binary then warn the user if [[ -z "$intersected_archs" ]]; then if [[ "$warn_missing_arch" == "true" ]]; then echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." fi STRIP_BINARY_RETVAL=0 return fi stripped="" for arch in $binary_archs; do if ! [[ "${ARCHS}" == *"$arch"* ]]; then # Strip non-valid architectures in-place lipo -remove "$arch" -output "$binary" "$binary" stripped="$stripped $arch" fi done if [[ "$stripped" ]]; then echo "Stripped $binary of architectures:$stripped" fi STRIP_BINARY_RETVAL=1 } install_artifact() { artifact="$1" base="$(basename "$artifact")" case $base in *.framework) install_framework "$artifact" ;; *.dSYM) # Suppress arch warnings since XCFrameworks will include many dSYM files install_dsym "$artifact" "false" ;; *.bcsymbolmap) install_bcsymbolmap "$artifact" ;; *) echo "error: Unrecognized artifact "$artifact"" ;; esac } copy_artifacts() { file_list="$1" while read artifact; do install_artifact "$artifact" done <$file_list } ARTIFACT_LIST_FILE="${BUILT_PRODUCTS_DIR}/cocoapods-artifacts-${CONFIGURATION}.txt" if [ -r "${ARTIFACT_LIST_FILE}" ]; then copy_artifacts "${ARTIFACT_LIST_FILE}" fi if [[ "$CONFIGURATION" == "Debug" ]]; then install_framework "${BUILT_PRODUCTS_DIR}/FMLayoutKit/FMLayoutKit.framework" install_framework "${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework" fi if [[ "$CONFIGURATION" == "Release" ]]; then install_framework "${BUILT_PRODUCTS_DIR}/FMLayoutKit/FMLayoutKit.framework" install_framework "${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework" fi if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then wait fi ================================================ FILE: Example/Pods/Target Support Files/Pods-FMLayoutKit_Example/Pods-FMLayoutKit_Example-umbrella.h ================================================ #ifdef __OBJC__ #import #else #ifndef FOUNDATION_EXPORT #if defined(__cplusplus) #define FOUNDATION_EXPORT extern "C" #else #define FOUNDATION_EXPORT extern #endif #endif #endif FOUNDATION_EXPORT double Pods_FMLayoutKit_ExampleVersionNumber; FOUNDATION_EXPORT const unsigned char Pods_FMLayoutKit_ExampleVersionString[]; ================================================ FILE: Example/Pods/Target Support Files/Pods-FMLayoutKit_Example/Pods-FMLayoutKit_Example.debug.xcconfig ================================================ FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FMLayoutKit" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FMLayoutKit/FMLayoutKit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry/Masonry.framework/Headers" LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' OTHER_LDFLAGS = $(inherited) -framework "FMLayoutKit" -framework "Foundation" -framework "Masonry" -framework "UIKit" PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_PODFILE_DIR_PATH = ${SRCROOT}/. PODS_ROOT = ${SRCROOT}/Pods USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES ================================================ FILE: Example/Pods/Target Support Files/Pods-FMLayoutKit_Example/Pods-FMLayoutKit_Example.modulemap ================================================ framework module Pods_FMLayoutKit_Example { umbrella header "Pods-FMLayoutKit_Example-umbrella.h" export * module * { export * } } ================================================ FILE: Example/Pods/Target Support Files/Pods-FMLayoutKit_Example/Pods-FMLayoutKit_Example.release.xcconfig ================================================ FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FMLayoutKit" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FMLayoutKit/FMLayoutKit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry/Masonry.framework/Headers" LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' OTHER_LDFLAGS = $(inherited) -framework "FMLayoutKit" -framework "Foundation" -framework "Masonry" -framework "UIKit" PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_PODFILE_DIR_PATH = ${SRCROOT}/. PODS_ROOT = ${SRCROOT}/Pods USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES ================================================ FILE: Example/Pods/Target Support Files/Pods-FMLayoutKit_Tests/Pods-FMLayoutKit_Tests-Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier ${PRODUCT_BUNDLE_IDENTIFIER} CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType FMWK CFBundleShortVersionString 1.0.0 CFBundleSignature ???? CFBundleVersion ${CURRENT_PROJECT_VERSION} NSPrincipalClass ================================================ FILE: Example/Pods/Target Support Files/Pods-FMLayoutKit_Tests/Pods-FMLayoutKit_Tests-acknowledgements.markdown ================================================ # Acknowledgements This application makes use of the following third party libraries: Generated by CocoaPods - https://cocoapods.org ================================================ FILE: Example/Pods/Target Support Files/Pods-FMLayoutKit_Tests/Pods-FMLayoutKit_Tests-acknowledgements.plist ================================================ PreferenceSpecifiers FooterText This application makes use of the following third party libraries: Title Acknowledgements Type PSGroupSpecifier FooterText Generated by CocoaPods - https://cocoapods.org Title Type PSGroupSpecifier StringsTable Acknowledgements Title Acknowledgements ================================================ FILE: Example/Pods/Target Support Files/Pods-FMLayoutKit_Tests/Pods-FMLayoutKit_Tests-dummy.m ================================================ #import @interface PodsDummy_Pods_FMLayoutKit_Tests : NSObject @end @implementation PodsDummy_Pods_FMLayoutKit_Tests @end ================================================ FILE: Example/Pods/Target Support Files/Pods-FMLayoutKit_Tests/Pods-FMLayoutKit_Tests-umbrella.h ================================================ #ifdef __OBJC__ #import #else #ifndef FOUNDATION_EXPORT #if defined(__cplusplus) #define FOUNDATION_EXPORT extern "C" #else #define FOUNDATION_EXPORT extern #endif #endif #endif FOUNDATION_EXPORT double Pods_FMLayoutKit_TestsVersionNumber; FOUNDATION_EXPORT const unsigned char Pods_FMLayoutKit_TestsVersionString[]; ================================================ FILE: Example/Pods/Target Support Files/Pods-FMLayoutKit_Tests/Pods-FMLayoutKit_Tests.debug.xcconfig ================================================ FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FMLayoutKit" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FMLayoutKit/FMLayoutKit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry/Masonry.framework/Headers" OTHER_LDFLAGS = $(inherited) -framework "FMLayoutKit" -framework "Foundation" -framework "Masonry" -framework "UIKit" PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_PODFILE_DIR_PATH = ${SRCROOT}/. PODS_ROOT = ${SRCROOT}/Pods USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES ================================================ FILE: Example/Pods/Target Support Files/Pods-FMLayoutKit_Tests/Pods-FMLayoutKit_Tests.modulemap ================================================ framework module Pods_FMLayoutKit_Tests { umbrella header "Pods-FMLayoutKit_Tests-umbrella.h" export * module * { export * } } ================================================ FILE: Example/Pods/Target Support Files/Pods-FMLayoutKit_Tests/Pods-FMLayoutKit_Tests.release.xcconfig ================================================ FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FMLayoutKit" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FMLayoutKit/FMLayoutKit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry/Masonry.framework/Headers" OTHER_LDFLAGS = $(inherited) -framework "FMLayoutKit" -framework "Foundation" -framework "Masonry" -framework "UIKit" PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_PODFILE_DIR_PATH = ${SRCROOT}/. PODS_ROOT = ${SRCROOT}/Pods USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES ================================================ FILE: Example/Tests/Tests-Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Example/Tests/Tests-Prefix.pch ================================================ // The contents of this file are implicitly included at the beginning of every test case source file. #ifdef __OBJC__ #endif ================================================ FILE: Example/Tests/Tests.m ================================================ // // FMLayoutKitTests.m // FMLayoutKitTests // // Created by zhoufaming251@163.com on 06/09/2020. // Copyright (c) 2020 zhoufaming251@163.com. All rights reserved. // @import XCTest; @interface Tests : XCTestCase @end @implementation Tests - (void)setUp { [super setUp]; // Put setup code here. This method is called before the invocation of each test method in the class. } - (void)tearDown { // Put teardown code here. This method is called after the invocation of each test method in the class. [super tearDown]; } - (void)testExample { XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); } @end ================================================ FILE: Example/Tests/en.lproj/InfoPlist.strings ================================================ /* Localized versions of Info.plist keys */ ================================================ FILE: Example/makeFramework.sh ================================================ #! /bin/bash #当前项目所在路径 current_path=`pwd` #项目 project_name='FMLayoutKit' # workspace_name=$project_name target_name=$project_name framework_config=Release #framework输出路径 FRAMEWORK_TARGET_DIR=$current_path/${workspace_name}"Framework" #临时文件夹路径 BUILD_DIR_TMP=$current_path/'FrameworkTmp' echo "当前项目所在路径:$current_path" echo "临时文件夹:$BUILD_DIR_TMP" echo "framework输出路径:${FRAMEWORK_TARGET_DIR}" archiveWorkSpace(){ #build之前清理文件 xcodebuild clean -workspace ${workspace_name}.xcworkspace -scheme ${target_name} #模拟器build xcodebuild build -workspace ${workspace_name}.xcworkspace -scheme ${target_name} -configuration framework_config -sdk iphonesimulator SYMROOT=${BUILD_DIR_TMP} #真机build xcodebuild build -workspace ${workspace_name}.xcworkspace -scheme ${target_name} -configuration framework_config -sdk iphoneos SYMROOT=${BUILD_DIR_TMP} #OBJROOT=${BUILD_DIR_TMP} SYMROOT=${BUILD_DIR_TMP} #将模拟器中的framework复制出来 cp -R ${BUILD_DIR_TMP}/${framework_config}-iphonesimulator/${workspace_name}/${workspace_name}.framework ${FRAMEWORK_TARGET_DIR} #从模拟器中移除arm64架构 lipo ${BUILD_DIR_TMP}/${framework_config}-iphonesimulator/${workspace_name}/${workspace_name}.framework/${workspace_name} -remove arm64 -output ${BUILD_DIR_TMP}/${framework_config}-iphonesimulator/${workspace_name}/${workspace_name}.framework/${workspace_name} #合并真机和模拟器文件并输出到构建的framework中 lipo -create ${BUILD_DIR_TMP}/${framework_config}-iphonesimulator/${workspace_name}/${workspace_name}.framework/${workspace_name} ${BUILD_DIR_TMP}/${framework_config}-iphoneos/${workspace_name}/${workspace_name}.framework/${workspace_name} -output ${FRAMEWORK_TARGET_DIR}/${workspace_name}.framework/${workspace_name} #删除无用的三方bundle find ${FRAMEWORK_TARGET_DIR}/${workspace_name}.framework -maxdepth 1 -name '*.bundle' -not -name "${workspace_name}*.bundle" | xargs rm -rf #自动打开文件夹 open $FRAMEWORK_TARGET_DIR } makeFramework(){ #判断临时文件夹是否存在,存在的话先删除 if [ -d $BUILD_DIR_TMP ];then rm -rf $BUILD_DIR_TMP fi # 判断输出文件夹是否存在,存在的话先删除 if [ -d ${FRAMEWORK_TARGET_DIR} ];then rm -rf ${FRAMEWORK_TARGET_DIR} fi #创建临时文件夹 mkdir -p ${BUILD_DIR_TMP} #创建输出文件夹 mkdir -p ${FRAMEWORK_TARGET_DIR} archiveWorkSpace rm -rf $BUILD_DIR_TMP } makeFramework ================================================ FILE: FMLayoutKit/Assets/.gitkeep ================================================ ================================================ FILE: FMLayoutKit/Classes/.gitkeep ================================================ ================================================ FILE: FMLayoutKit/Classes/Cross/FMLayoutCrossCell.h ================================================ // // FMLayoutCrossCell.h // FMLayoutKit // // Created by 周发明 on 2020/6/16. // #import NS_ASSUME_NONNULL_BEGIN @class FMLayoutCrossSection; @interface FMLayoutCrossCell : UICollectionViewCell @property(nonatomic, strong)FMLayoutCrossSection *crossSection; @end NS_ASSUME_NONNULL_END ================================================ FILE: FMLayoutKit/Classes/Cross/FMLayoutCrossCell.m ================================================ // // FMLayoutCrossCell.m // FMLayoutKit // // Created by 周发明 on 2020/6/16. // #import "FMLayoutCrossCell.h" #import "FMLayoutView.h" #import "FMLayoutCrossSection.h" @interface FMLayoutCrossCell() @property(nonatomic, weak)FMLayoutView *layoutView; @end @implementation FMLayoutCrossCell - (void)dealloc{ FMLayoutLog(@"FMHorizontalCell dealloc"); } - (FMLayoutView *)layoutView{ if (_layoutView == nil) { FMLayoutView *view = [[FMLayoutView alloc] init]; view.backgroundColor = [UIColor clearColor]; [self.contentView addSubview:view]; _layoutView = view; } return _layoutView; } - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.layoutView.translatesAutoresizingMaskIntoConstraints = NO; NSLayoutConstraint *left = [NSLayoutConstraint constraintWithItem:self.layoutView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeLeft multiplier:1 constant:0]; NSLayoutConstraint *right = [NSLayoutConstraint constraintWithItem:self.layoutView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeRight multiplier:1 constant:0]; NSLayoutConstraint *top = [NSLayoutConstraint constraintWithItem:self.layoutView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTop multiplier:1 constant:0]; NSLayoutConstraint *bottom = [NSLayoutConstraint constraintWithItem:self.layoutView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeBottom multiplier:1 constant:0]; [self.contentView addConstraints:@[left,right,top,bottom]]; } return self; } - (void)setCrossSection:(FMLayoutCrossSection *)crossSection{ _crossSection = crossSection; self.layoutView.layout.direction = crossSection.crossDirection; self.layoutView.layout.sections = crossSection.sections; self.layoutView.delegate = crossSection; [self.layoutView reloadData]; if (crossSection.configureCollectionView) { crossSection.configureCollectionView(self.layoutView, crossSection); } } @end ================================================ FILE: FMLayoutKit/Classes/Cross/FMLayoutCrossSection.h ================================================ // // FMLayoutCrossSection.h // FMLayoutKit // // Created by 周发明 on 2020/6/16. // #import "FMLayoutBaseSection.h" NS_ASSUME_NONNULL_BEGIN @interface FMLayoutCrossSection : FMLayoutBaseSection @property(nonatomic, assign, readonly)FMLayoutDirection crossDirection; /// 所有section计算获取最大的高度 @property(nonatomic, assign)BOOL autoMaxSize; /// 所有section计算获取最大的高度 @property(nonatomic, assign)CGFloat size; @property(nonatomic, assign)BOOL canReuseCell; @property(nonatomic, assign, readonly)CGFloat maxContentWidth; @property(nonatomic, strong)NSMutableArray *sections; @property(nonatomic, copy)void(^scrollDidScroll)(UICollectionView *collectionView, FMLayoutCrossSection *hSection); @property(nonatomic, copy)void(^configureCollectionView)(UICollectionView *collectionView, FMLayoutCrossSection *hSection); + (instancetype)sectionAutoWithSection:(FMLayoutBaseSection *)section; @end NS_ASSUME_NONNULL_END ================================================ FILE: FMLayoutKit/Classes/Cross/FMLayoutCrossSection.m ================================================ // // FMLayoutCrossSection.m // FMLayoutKit // // Created by 周发明 on 2020/6/16. // #import "FMLayoutCrossSection.h" #import "FMLayoutCrossCell.h" #import "FMLayoutElement.h" #import "FMCollectionLayoutAttributes.h" @interface FMLayoutCrossSection () @property(nonatomic, strong)FMLayoutElement *cellElement;///固定分组 @end @implementation FMLayoutCrossSection - (id)copyWithZone:(NSZone *)zone{ FMLayoutCrossSection *section = [super copyWithZone:zone]; section.cellElement = [self.cellElement copy]; section.configureCellData = self.configureCellData; section.autoMaxSize = self.autoMaxSize; section.size = self.size; section.canReuseCell = self.canReuseCell; NSMutableArray *sections = [NSMutableArray array]; for (FMLayoutBaseSection *s in self.sections) { [sections addObject:[s copy]]; } section.sections = sections; section.scrollDidScroll = [self.scrollDidScroll copy]; section.configureCollectionView = [self.configureCollectionView copy]; return section; } - (FMLayoutDirection)crossDirection{ return self.direction == FMLayoutDirectionVertical ? FMLayoutDirectionHorizontal : FMLayoutDirectionVertical; } - (CGFloat)maxContentWidth{ if (self.sections == nil || self.sections.count == 0) { return 0; } FMLayoutBaseSection *last = [self.sections lastObject]; return last.sectionOffset + last.sectionSize; } - (void)setCanReuseCell:(BOOL)canReuseCell{ _canReuseCell = canReuseCell; self.cellElement.reuseIdentifier = canReuseCell ? NSStringFromClass(self.cellElement.viewClass) : [NSString stringWithFormat:@"%@%@", self, NSStringFromClass(self.cellElement.viewClass)]; } + (instancetype)sectionAutoWithSection:(FMLayoutBaseSection *)section{ FMLayoutCrossSection *hor = [[self alloc] init]; hor.autoMaxSize = YES; hor.sections = [@[section] mutableCopy]; return hor; } - (instancetype)init { self = [super init]; if (self) { self.cellElement = [FMLayoutElement elementWithViewClass:[FMLayoutCrossCell class]]; self.canReuseCell = NO; [self setConfigureCellData:^(FMLayoutBaseSection * _Nonnull section, UICollectionViewCell * _Nonnull cell, NSInteger item) { FMLayoutCrossCell *hCell = (FMLayoutCrossCell *)cell; hCell.crossSection = (FMLayoutCrossSection *)section; }]; self.sections = [NSMutableArray array]; } return self; } - (NSInteger)itemCount{ return 1; } - (void)prepareItems{ if ([self prepareLayoutItemsIsOlnyChangeOffset]) return; [self resetcolumnSizes]; FMCollectionLayoutAttributes *itemAttr = [FMCollectionLayoutAttributes layoutAttributesForCellWithIndexPath:[NSIndexPath indexPathForItem:0 inSection:self.indexPath.section]]; CGSize itemSize; if (self.autoMaxSize) { CGFloat maxSize = 0; for (FMLayoutBaseSection *section in self.sections) { section.direction = self.crossDirection; CGFloat size = [section crossSingleSectionSize]; if (maxSize < size) { maxSize = size; } } if (self.direction == FMLayoutDirectionVertical) { itemSize = CGSizeMake(self.collectionView.frame.size.width - self.sectionInset.left - self.sectionInset.right, maxSize); } else { itemSize = CGSizeMake(maxSize, self.collectionView.frame.size.height - self.sectionInset.top - self.sectionInset.bottom); } } else { if (self.direction == FMLayoutDirectionVertical) { itemSize = CGSizeMake(self.collectionView.frame.size.width - self.sectionInset.left - self.sectionInset.right, self.size); } else { itemSize = CGSizeMake(self.size, self.collectionView.frame.size.height - self.sectionInset.top - self.sectionInset.bottom); } } CGFloat x = self.firstItemStartX; CGFloat y = self.firstItemStartY; itemAttr.frame = CGRectMake(x, y, itemSize.width, itemSize.height); self.itemsAttribute = @[itemAttr]; self.columnSizes[@(0)] = self.direction == FMLayoutDirectionVertical ? @(itemSize.height) : @(itemSize.width); } - (UICollectionViewCell *)dequeueReusableCellForIndexPath:(NSIndexPath *)indexPath collectionView:(nonnull UICollectionView *)collectionView{ return [collectionView dequeueReusableCellWithReuseIdentifier:self.cellElement.reuseIdentifier forIndexPath:indexPath]; } - (void)registerCellsWithCollectionView:(UICollectionView *)collectionView{ [self.cellElement registerElementWithCollection:collectionView]; } #pragma mark ----- UICollectionViewDelegate - (void)scrollViewDidScroll:(UIScrollView *)scrollView{ if (self.scrollDidScroll) { self.scrollDidScroll((UICollectionView *)scrollView, self); } } @end ================================================ FILE: FMLayoutKit/Classes/Cross/FMLayoutCrossTransformSection.h ================================================ // // FMLayoutCrossTransformSection.h // FMLayoutKit // // Created by 郑桂华 on 2020/7/15. // #import "FMLayoutCrossSection.h" NS_ASSUME_NONNULL_BEGIN typedef NS_ENUM(NSUInteger, FMLayoutCrossTransformType) { ///什么都不做 FMLayoutCrossTransformNone, ///缩小0.9 + 0.1*进度 FMLayoutCrossTransformScale, ///简拼App首页样式 M_PI_4 * 0.5 * 进度 FMLayoutCrossTransformCrooked, ///折叠效果 FMLayoutCrossTransformFold, }; ///Cell是需要做处理的cell, progress是指cell中心点到屏幕边缘移动的进度 -1 ~ 1 0为在最中间 -1在左边 1在右边 typedef void(^FMLayoutCrossTransformBlock)(UICollectionViewCell *cell, CGFloat progress); ///当前仅针对横向做适配 更多的动画 @interface FMLayoutCrossTransformSection : FMLayoutCrossSection ///形变类型 @property(nonatomic, assign)FMLayoutCrossTransformType transformType; ///如果有该Block 则优先执行此block @property(nonatomic, copy)FMLayoutCrossTransformBlock __nullable transformBlock; @end NS_ASSUME_NONNULL_END ================================================ FILE: FMLayoutKit/Classes/Cross/FMLayoutCrossTransformSection.m ================================================ // // FMLayoutCrossTransformSection.m // FMLayoutKit // // Created by 郑桂华 on 2020/7/15. // #import "FMLayoutCrossTransformSection.h" @implementation FMLayoutCrossTransformSection - (instancetype)init { self = [super init]; if (self) { [self setConfigureCollectionView:^(UICollectionView * _Nonnull collectionView, FMLayoutCrossSection * _Nonnull hSection) { collectionView.decelerationRate = UIScrollViewDecelerationRateFast; collectionView.alwaysBounceHorizontal = YES; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [collectionView layoutIfNeeded]; [collectionView.delegate scrollViewDidScroll:collectionView]; }); }]; } return self; } - (void)setTransformType:(FMLayoutCrossTransformType)transformType{ _transformType = transformType; switch (transformType) { case FMLayoutCrossTransformScale: { [self setTransformBlock:^(UICollectionViewCell * _Nonnull cell, CGFloat progress) { cell.layer.affineTransform = CGAffineTransformMakeScale(0.9 + (1 - (fabs(progress))) * 0.1, 0.9 + (1 - (fabs(progress))) * 0.1); }]; } break; case FMLayoutCrossTransformCrooked: { [self setTransformBlock:^(UICollectionViewCell * _Nonnull cell, CGFloat progress) { CATransform3D transform; if (progress < 0) { transform = CATransform3DMakeRotation(M_PI_4 * 0.5 * (fabs(progress)), 1, 1, 0); } else if (progress > 0) { transform = CATransform3DMakeRotation(M_PI_4 * 0.5 * (fabs(progress)), -1, 1, 0); } else { transform = CATransform3DIdentity; } transform.m34 = 1/500.0; cell.layer.allowsEdgeAntialiasing = YES; cell.layer.transform = transform; }]; } break; case FMLayoutCrossTransformFold: { [self setTransformBlock:^(UICollectionViewCell * _Nonnull cell, CGFloat progress) { CATransform3D transform; if (progress < 0) { cell.layer.anchorPoint = CGPointMake(0 + 0.5 * (1 - fabs(progress)), 0.5); transform = CATransform3DMakeTranslation(-cell.bounds.size.width * 0.5 * fabs(progress), 0, 0); cell.layer.transform = transform; transform.m34 = 1.0/500; transform = CATransform3DRotate(transform, M_PI_4 * fabs(progress), 0, -1, 0); } else { cell.layer.anchorPoint = CGPointMake(1 - 0.5 * (1 - fabs(progress)), 0.5); transform = CATransform3DMakeTranslation(cell.bounds.size.width * 0.5 * fabs(progress), 0, 0); cell.layer.transform = transform; transform.m34 = 1.0/500; transform = CATransform3DRotate(transform, M_PI_4 * fabs(progress), 0, 1, 0); } if (@available(iOS 13.0, *)) { cell.transform3D = transform; } else { cell.layer.transform = transform; } }]; } break; default: self.transformBlock = nil; break; } } - (void)scrollViewDidScroll:(UIScrollView *)scrollView{ [super scrollViewDidScroll:scrollView]; if (self.transformBlock == nil) { return; } FMLayoutCrossTransformBlock block = self.transformBlock; if (block) { NSArray *cells = [(UICollectionView *)scrollView visibleCells]; for (UICollectionViewCell *cell in cells) { block(cell, [self progressCell:cell scrollView:scrollView]); } } } - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{ if (!decelerate) { [self scrollToCenter:scrollView]; } else { dispatch_async(dispatch_get_main_queue(), ^{ [scrollView setContentOffset:scrollView.contentOffset animated:NO]; [self scrollToCenter:scrollView]; }); } } - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{ [self scrollToCenter:scrollView]; } - (void)scrollToCenter:(UIScrollView *)scrollView{ UICollectionViewCell *lastCell = nil; CGFloat minProgress = 1.01; NSArray *cells = [(UICollectionView *)scrollView visibleCells]; for (UICollectionViewCell *cell in cells) { if (lastCell == nil) { lastCell = cell; } CGFloat progress = [self progressCell:cell scrollView:scrollView]; if (fabs(progress) < minProgress) { minProgress = fabs(progress); lastCell = cell; } } NSIndexPath *indexPath = [(UICollectionView *)scrollView indexPathForCell:lastCell]; if (indexPath) { [(UICollectionView *)scrollView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:YES]; } } - (CGFloat)progressCell:(UICollectionViewCell *)cell scrollView:(UIScrollView *)scrollView{ CGPoint globalCenter = scrollView.center; CGPoint cellGlobalCenter = cell.center; CGFloat progress = (cellGlobalCenter.x - scrollView.contentOffset.x - globalCenter.x) / globalCenter.x; if (progress < -1) { progress = -1; } if (progress > 1) { progress = 1; } return progress; } @end ================================================ FILE: FMLayoutKit/Classes/Element/FMLayoutBackground.h ================================================ // // FMLayoutBackground.h // FMLayoutKit // // Created by 周发明 on 2020/3/27. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import "FMSupplementary.h" NS_ASSUME_NONNULL_BEGIN static NSString *const UICollectionElementKindSectionBackground = @"UICollectionElementKindSectionBackground"; @interface FMLayoutBackground : FMSupplementary + (instancetype)bgWithViewClass:(Class)viewClass; @end NS_ASSUME_NONNULL_END ================================================ FILE: FMLayoutKit/Classes/Element/FMLayoutBackground.m ================================================ // // FMLayoutBackground.m // FMLayoutKit // // Created by 周发明 on 2020/3/27. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import "FMLayoutBackground.h" @implementation FMLayoutBackground - (NSString *)elementKind{ return UICollectionElementKindSectionBackground; } + (instancetype)bgWithViewClass:(Class)viewClass{ FMLayoutBackground *bg = [super elementWithViewClass:viewClass]; bg.zIndex = FMLayoutZIndexBg; return bg; } @end ================================================ FILE: FMLayoutKit/Classes/Element/FMLayoutElement.h ================================================ // // FMLayoutElement.h // FMLayoutKit // // Created by 周发明 on 2020/4/1. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import #import NS_ASSUME_NONNULL_BEGIN @interface FMLayoutElement : NSObject @property(nonatomic, copy)NSString *reuseIdentifier; @property(nonatomic, assign)BOOL isNib; @property(nonatomic, weak)Class viewClass;///视图的类 + (instancetype)elementWithViewClass:(Class)vCalss; + (instancetype)elementWithViewClass:(Class)vCalss isNib:(BOOL)isNib; + (instancetype)elementWithViewClass:(Class)vCalss isNib:(BOOL)isNib reuseIdentifier:(NSString *)reuseIdentifier; - (void)registerElementWithCollection:(UICollectionView *)collectionView; @end NS_ASSUME_NONNULL_END ================================================ FILE: FMLayoutKit/Classes/Element/FMLayoutElement.m ================================================ // // FMLayoutElement.m // FMLayoutKit // // Created by 周发明 on 2020/4/1. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import "FMLayoutElement.h" @interface FMLayoutElement () @end @implementation FMLayoutElement - (id)copyWithZone:(NSZone *)zone{ FMLayoutElement *element = [[[self class] allocWithZone:zone] init]; element.reuseIdentifier = self.reuseIdentifier; element.isNib = self.isNib; element.viewClass = self.viewClass; return element; } + (instancetype)elementWithViewClass:(Class)vCalss{ return [self elementWithViewClass:vCalss isNib:NO]; } + (instancetype)elementWithViewClass:(Class)vCalss isNib:(BOOL)isNib{ return [self elementWithViewClass:vCalss isNib:isNib reuseIdentifier:NSStringFromClass(vCalss)]; } + (instancetype)elementWithViewClass:(Class)vCalss isNib:(BOOL)isNib reuseIdentifier:(NSString *)reuseIdentifier{ FMLayoutElement *element = [[self alloc] init]; element.viewClass = vCalss; element.isNib = isNib; element.reuseIdentifier = reuseIdentifier; return element; } - (void)registerElementWithCollection:(UICollectionView *)collectionView{ if (self.isNib) { [collectionView registerNib:[UINib nibWithNibName:NSStringFromClass(self.viewClass) bundle:[NSBundle mainBundle]] forCellWithReuseIdentifier:self.reuseIdentifier]; } else { [collectionView registerClass:self.viewClass forCellWithReuseIdentifier:self.reuseIdentifier]; } } @end ================================================ FILE: FMLayoutKit/Classes/Element/FMLayoutFooter.h ================================================ // // FMLayoutFooter.h // FMLayoutKit // // Created by 周发明 on 2020/3/20. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import "FMSupplementary.h" NS_ASSUME_NONNULL_BEGIN @interface FMLayoutFooter : FMSupplementary /// 距离最后Item的距离 纵向-上方 横向-左边 @property(nonatomic, assign)CGFloat topMargin; @end NS_ASSUME_NONNULL_END ================================================ FILE: FMLayoutKit/Classes/Element/FMLayoutFooter.m ================================================ // // FMLayoutFooter.m // FMLayoutKit // // Created by 周发明 on 2020/3/20. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import "FMLayoutFooter.h" @implementation FMLayoutFooter - (NSString *)elementKind{ return UICollectionElementKindSectionFooter; } - (id)copyWithZone:(NSZone *)zone{ FMLayoutFooter *footer = [super copyWithZone:zone]; footer.topMargin = self.topMargin; return footer; } @end ================================================ FILE: FMLayoutKit/Classes/Element/FMLayoutHeader.h ================================================ // // FMLayoutHeader.h // FMLayoutKit // // Created by 周发明 on 2020/3/20. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import "FMSupplementary.h" NS_ASSUME_NONNULL_BEGIN /// 悬浮方式 typedef NS_ENUM(NSInteger, FMLayoutHeaderType) { ///跟着滚动 FMLayoutHeaderTypeFixed, ///悬浮在顶部 跟着section动 FMLayoutHeaderTypeSuspension, ///悬浮在顶部 不跟随section动 如果出现多个可能会被覆盖 FMLayoutHeaderTypeSuspensionAlways, ///仅支持在第一个头部 下拉放大效果 FMLayoutHeaderTypeSuspensionBigger }; @interface FMLayoutHeader : FMSupplementary /// 显示方式 是悬浮 还是跟着滚动 默认跟着滚动 @property(nonatomic, assign)FMLayoutHeaderType type; /// 悬浮模式时距离顶部的高度 可以来设置两个悬浮的方式 多个顶部悬浮时 可以通过这个来达到层叠悬浮的模式 @property(nonatomic, assign)CGFloat suspensionTopMargin; /// 距离第一个Item的距离 纵向-下方 横向-右边 @property(nonatomic, assign)CGFloat lastMargin; ///是否黏在顶部 目前仅支持FMLayoutHeaderTypeSuspensionAlways, FMLayoutHeaderTypeSuspensionBigger悬浮模式 不同的type效果不同 FMLayoutHeaderTypeSuspensionAlways是下拉黏在当前位置 上拉黏在顶部 而FMLayoutHeaderTypeSuspensionBiggers是上拉黏在顶部 下拉时放大效果 @property(nonatomic, assign)BOOL isStickTop; /// 缩放模式(SuspensionBigger)下最小值 横向-宽度 纵向-高度 该值请务必小于size 默认是0 @property(nonatomic, assign)CGFloat minSize; /// 缩放模式(SuspensionBigger)下最大值 横向-宽度 纵向-高度 该值请务必大于size 默认是CGFLOAT_MAX @property(nonatomic, assign)CGFloat maxSize; @end NS_ASSUME_NONNULL_END ================================================ FILE: FMLayoutKit/Classes/Element/FMLayoutHeader.m ================================================ // // FMLayoutHeader.m // FMLayoutKit // // Created by 周发明 on 2020/3/20. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import "FMLayoutHeader.h" @implementation FMLayoutHeader + (instancetype)elementSize:(CGFloat)size viewClass:(Class)vClass isNib:(BOOL)isNib reuseIdentifier:(NSString *)reuseIdentifier{ FMLayoutHeader *header = [super elementSize:size viewClass:vClass isNib:isNib reuseIdentifier:reuseIdentifier]; return header; } - (NSString *)elementKind{ return UICollectionElementKindSectionHeader; } - (instancetype)init { self = [super init]; if (self) { self.maxSize = CGFLOAT_MAX; } return self; } - (id)copyWithZone:(NSZone *)zone{ FMLayoutHeader *header = [super copyWithZone:zone]; header.lastMargin = self.lastMargin; header.type = self.type; header.suspensionTopMargin = self.suspensionTopMargin; header.isStickTop = self.isStickTop; header.minSize = self.minSize; header.maxSize = self.maxSize; return header; } @end ================================================ FILE: FMLayoutKit/Classes/Element/FMSupplementary.h ================================================ // // FMSupplementary.h // FMLayoutKit // // Created by 周发明 on 2020/3/20. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import "FMLayoutElement.h" typedef NS_ENUM(NSInteger, FMLayoutZIndex) { ///最底层 头部 底部 Item的下方 FMLayoutZIndexBg = -9999, ///Item的下方 FMLayoutZIndexBackOfItem = -1, /// 自动悬浮可能会被覆盖 FMLayoutZIndexAuto = 0, /// Item的上方 FMLayoutZIndexFrontOfItem = 1, /// 最最上方 FMLayoutZIndexFrontAlways = 9999 }; NS_ASSUME_NONNULL_BEGIN /// 请使用子类Footer, Header, Background @interface FMSupplementary : FMLayoutElement ///该Element的大小 纵向-高度 横向-宽度 @property(nonatomic, assign)CGFloat size; ///视图层级 最上方还是最下方等 @property(nonatomic, assign)FMLayoutZIndex zIndex; ///内边距 HeaderFooter受sectionInset影响 Background不受sectionInset影响 @property(nonatomic, assign)UIEdgeInsets inset; ///Element类型 Header Footer Background等 @property(nonatomic, copy, readonly)NSString *elementKind; ///是否自适应高度 仅当垂直布局时可用 @property(nonatomic, assign)BOOL autoHeight; @property(nonatomic, copy)void(^configureDataAutoHeight)(UICollectionReusableView *view); + (instancetype)elementSize:(CGFloat)size viewClass:(Class)vClass; + (instancetype)elementSize:(CGFloat)size viewClass:(Class)vClass isNib:(BOOL)isNib; + (instancetype)elementSize:(CGFloat)size viewClass:(Class)vClass isNib:(BOOL)isNib reuseIdentifier:(NSString *)reuseIdentifier; - (UICollectionReusableView *)dequeueReusableViewWithCollection:(UICollectionView *)collectionView indexPath:(NSIndexPath *)indexPath; - (void)updateHeightWithCollection:(UICollectionView *)collectionView indexPath:(NSIndexPath *)indexPath maxWidth:(CGFloat)maxWidth; @end NS_ASSUME_NONNULL_END ================================================ FILE: FMLayoutKit/Classes/Element/FMSupplementary.m ================================================ // // FMSupplementary.m // FMLayoutKit // // Created by 周发明 on 2020/3/20. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import "FMSupplementary.h" @interface FMSupplementary () @end @implementation FMSupplementary - (id)copyWithZone:(NSZone *)zone{ FMSupplementary *supp = [super copyWithZone:zone]; supp.size = self.size; supp.zIndex = self.zIndex; supp.autoHeight = self.autoHeight; supp.configureDataAutoHeight = [self.configureDataAutoHeight copy]; return supp; } + (instancetype)elementSize:(CGFloat)size viewClass:(Class)vClass{ return [self elementSize:size viewClass:vClass isNib:NO]; } + (instancetype)elementSize:(CGFloat)size viewClass:(Class)vClass isNib:(BOOL)isNib{ return [self elementSize:size viewClass:vClass isNib:isNib reuseIdentifier:NSStringFromClass(vClass)]; } + (instancetype)elementSize:(CGFloat)size viewClass:(Class)vClass isNib:(BOOL)isNib reuseIdentifier:(NSString *)reuseIdentifier{ FMSupplementary *dec = [super elementWithViewClass:vClass isNib:isNib reuseIdentifier:reuseIdentifier]; dec.size = size; dec.zIndex = FMLayoutZIndexFrontOfItem; return dec; } - (void)registerElementWithCollection:(UICollectionView *)collectionView{ if (self.isNib) { [collectionView registerNib:[UINib nibWithNibName:NSStringFromClass(self.viewClass) bundle:[NSBundle mainBundle]] forSupplementaryViewOfKind:self.elementKind withReuseIdentifier:self.reuseIdentifier]; } else { [collectionView registerClass:self.viewClass forSupplementaryViewOfKind:self.elementKind withReuseIdentifier:self.reuseIdentifier]; } } - (UICollectionReusableView *)dequeueReusableViewWithCollection:(UICollectionView *)collectionView indexPath:(nonnull NSIndexPath *)indexPath{ return [collectionView dequeueReusableSupplementaryViewOfKind:self.elementKind withReuseIdentifier:self.reuseIdentifier forIndexPath:indexPath]; } - (void)updateHeightWithCollection:(UICollectionView *)collectionView indexPath:(NSIndexPath *)indexPath maxWidth:(CGFloat)maxWidth{ if (self.autoHeight) { UICollectionReusableView *view; if (self.isNib) { view = [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass(self.viewClass) owner:nil options:nil] lastObject]; } else { view = [[self.viewClass alloc] init]; } if (self.configureDataAutoHeight) { self.configureDataAutoHeight(view); } CGSize size = [view systemLayoutSizeFittingSize:CGSizeMake(maxWidth, MAXFLOAT)]; self.size = size.height; } } @end ================================================ FILE: FMLayoutKit/Classes/FMCollectionLayoutAttributes.h ================================================ // // FMCollectionLayoutAttributes.h // FMLayoutKit // // Created by 周发明 on 2020/3/25. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import #import "FMLayoutBaseSection.h" NS_ASSUME_NONNULL_BEGIN @interface FMCollectionLayoutAttributes : UICollectionViewLayoutAttributes @property(nonatomic, assign)FMLayoutDirection direction; + (instancetype)headerAttributesWithSection:(FMLayoutBaseSection *)section; - (instancetype)updateHeaderAttributesWithSection:(FMLayoutBaseSection *)section; + (instancetype)suspensionShowHeaderAttributes:(FMLayoutBaseSection *)section; + (instancetype)footerAttributesWithSection:(FMLayoutBaseSection *)section; - (instancetype)updateFooterAttributesWithSection:(FMLayoutBaseSection *)section; + (instancetype)bgAttributesWithSection:(FMLayoutBaseSection *)section; - (instancetype)updateBgAttributesWithSection:(FMLayoutBaseSection *)section; - (void)_onlyUpdateOffsetWith:(FMLayoutBaseSection *)section; @end NS_ASSUME_NONNULL_END ================================================ FILE: FMLayoutKit/Classes/FMCollectionLayoutAttributes.m ================================================ // // FMCollectionLayoutAttributes.m // FMLayoutKit // // Created by 周发明 on 2020/3/25. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import "FMCollectionLayoutAttributes.h" #import "FMLayoutFooter.h" #import "FMLayoutHeader.h" #import "FMLayoutBackground.h" @implementation FMCollectionLayoutAttributes + (instancetype)headerAttributesWithSection:(FMLayoutBaseSection *)section{ if (!section.header) { return nil; } FMCollectionLayoutAttributes *header = [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader withIndexPath:section.indexPath]; header.direction = section.direction; if (header.direction == FMLayoutDirectionVertical) { [section.header updateHeightWithCollection:section.collectionView indexPath:section.indexPath maxWidth:section.collectionView.frame.size.width - section.sectionInset.left- section.header.inset.left - section.sectionInset.right - section.header.inset.right]; header.frame = CGRectMake(section.sectionInset.left + section.header.inset.left, section.sectionInset.top + section.header.inset.top + section.sectionOffset, section.collectionView.frame.size.width - section.sectionInset.left- section.header.inset.left - section.sectionInset.right - section.header.inset.right, section.header.size); } else { header.frame = CGRectMake(section.sectionInset.left + section.header.inset.left + section.sectionOffset, section.sectionInset.top + section.header.inset.top,section.header.size, section.collectionView.frame.size.height - section.sectionInset.top- section.header.inset.top - section.sectionInset.bottom - section.header.inset.bottom); } header.zIndex = section.header.zIndex; return header; } - (instancetype)updateHeaderAttributesWithSection:(FMLayoutBaseSection *)section{ self.indexPath = section.indexPath; [self _onlyUpdateOffsetWith:section]; return self; } + (instancetype)suspensionShowHeaderAttributes:(FMLayoutBaseSection *)section{ if (section.direction == FMLayoutDirectionVertical) { if (section.header.type == FMLayoutHeaderTypeSuspension) { CGFloat columnMaxHeight = [section getColumnMaxHeight]; CGFloat itemMaxHeight = section.sectionOffset + section.sectionInset.top + section.header.size + section.header.lastMargin + columnMaxHeight; if (section.collectionView.contentOffset.y > section.sectionOffset + section.sectionInset.top && section.collectionView.contentOffset.y < itemMaxHeight - section.header.size) { FMCollectionLayoutAttributes *show = [section.headerAttribute copy]; CGRect frame = show.frame; frame.origin.y = section.collectionView.contentOffset.y; show.frame = frame; return show; } else if (section.collectionView.contentOffset.y >= itemMaxHeight - section.header.size) { FMCollectionLayoutAttributes *show = [section.headerAttribute copy]; CGRect frame = show.frame; frame.origin.y = itemMaxHeight - section.header.size; show.frame = frame; return show; } else { return section.headerAttribute; } } if (section.header.type == FMLayoutHeaderTypeSuspensionAlways) { if (section.collectionView.contentOffset.y > section.sectionOffset + section.sectionInset.top - section.header.suspensionTopMargin) { FMCollectionLayoutAttributes *show = [section.headerAttribute copy]; CGRect frame = show.frame; frame.origin.y = section.collectionView.contentOffset.y + section.header.suspensionTopMargin; show.frame = frame; return show; } else { if (section.header.isStickTop) {///黏在顶部 if (section.collectionView.contentOffset.y > 0) { return section.headerAttribute; } FMCollectionLayoutAttributes *show = [section.headerAttribute copy]; CGRect frame = show.frame; frame.origin.y = section.collectionView.contentOffset.y + frame.origin.y; show.frame = frame; return show; } else { return section.headerAttribute; } } } if (section.header.type == FMLayoutHeaderTypeSuspensionBigger && section.indexPath.section == 0) { FMCollectionLayoutAttributes *show = [section.headerAttribute copy]; CGFloat offsetY = section.collectionView.contentOffset.y; if (offsetY <= 0) { //放大 CGRect frame = show.frame; frame.origin.y += offsetY; frame.size.height -= offsetY; if (frame.size.height > section.header.maxSize) { CGFloat diff = frame.size.height - section.header.maxSize; frame.size.height -= diff; frame.origin.y += diff; } show.frame = frame; return show; } else { //缩小 CGRect frame = show.frame; CGRect originalFrame = section.headerAttribute.frame; CGFloat minHeight = section.header.minSize; if (offsetY <= frame.origin.y) {//顶部有间距 先移动到顶部 return show; } if (offsetY <= frame.origin.y + section.header.size - minHeight) {//缩小至最小过程 frame.origin.y = offsetY; frame.size.height -= (offsetY - originalFrame.origin.y); show.frame = frame; return show; } //缩小的最小之后大小固定 frame.origin.y = offsetY; frame.size.height = minHeight; //如果不是固定在顶固的 将偏移量重置 if (!section.header.isStickTop) { CGFloat minOffsetY = originalFrame.origin.y + (section.header.size - minHeight); if (offsetY > minOffsetY) { frame.origin.y = minOffsetY; } } show.frame = frame; return show; } } } else { if (section.header.type == FMLayoutHeaderTypeSuspension) { CGFloat columnMaxHeight = [section getColumnMaxHeight]; CGFloat itemMaxHeight = section.sectionOffset + section.sectionInset.left + section.header.size + section.header.lastMargin + columnMaxHeight; if (section.collectionView.contentOffset.x > section.sectionOffset + section.sectionInset.left && section.collectionView.contentOffset.x < itemMaxHeight - section.header.size) { FMCollectionLayoutAttributes *show = [section.headerAttribute copy]; CGRect frame = show.frame; frame.origin.x = section.collectionView.contentOffset.x; show.frame = frame; return show; } else if (section.collectionView.contentOffset.x >= itemMaxHeight - section.header.size) { FMCollectionLayoutAttributes *show = [section.headerAttribute copy]; CGRect frame = show.frame; frame.origin.x = itemMaxHeight - section.header.size; show.frame = frame; return show; } else { return section.headerAttribute; } } if (section.header.type == FMLayoutHeaderTypeSuspensionAlways) { if (section.collectionView.contentOffset.x > section.sectionOffset + section.sectionInset.left - section.header.suspensionTopMargin) { FMCollectionLayoutAttributes *show = [section.headerAttribute copy]; CGRect frame = show.frame; frame.origin.x = section.collectionView.contentOffset.x + section.header.suspensionTopMargin; show.frame = frame; return show; } else { if (section.header.isStickTop) {///黏在顶部 if (section.collectionView.contentOffset.x > 0) { return section.headerAttribute; } FMCollectionLayoutAttributes *show = [section.headerAttribute copy]; CGRect frame = show.frame; frame.origin.x = section.collectionView.contentOffset.x + frame.origin.x; show.frame = frame; return show; } else { return section.headerAttribute; } } } if (section.header.type == FMLayoutHeaderTypeSuspensionBigger && section.indexPath.section == 0) { FMCollectionLayoutAttributes *show = [section.headerAttribute copy]; CGFloat offsetX = section.collectionView.contentOffset.x; if (offsetX <= 0) { //放大 CGRect frame = show.frame; frame.origin.x += offsetX; frame.size.width -= offsetX; if (frame.size.width > section.header.maxSize) { CGFloat diff = frame.size.width - section.header.maxSize; frame.size.width -= diff; frame.origin.x += diff; } show.frame = frame; return show; } else { //缩小 CGRect frame = show.frame; CGRect originalFrame = section.headerAttribute.frame; CGFloat minHeight = section.header.minSize; if (offsetX <= frame.origin.x) {//顶部有间距 先移动到顶部 return show; } if (offsetX <= frame.origin.x + section.header.size - minHeight) {//缩小至最小过程 frame.origin.x = offsetX; frame.size.width -= (offsetX - originalFrame.origin.x); show.frame = frame; return show; } //缩小的最小之后大小固定 frame.origin.x = offsetX; frame.size.width = minHeight; //如果不是固定在顶固的 将偏移量重置 if (!section.header.isStickTop) { CGFloat minOffsetX = originalFrame.origin.x + (section.header.size - minHeight); if (offsetX > minOffsetX) { frame.origin.x = minOffsetX; } } show.frame = frame; return show; } } } return nil; } + (instancetype)footerAttributesWithSection:(FMLayoutBaseSection *)section{ if (!section.footer) { return nil; } FMCollectionLayoutAttributes *footer = [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionFooter withIndexPath:section.indexPath]; footer.direction = section.direction; if (footer.direction == FMLayoutDirectionVertical) { [section.footer updateHeightWithCollection:section.collectionView indexPath:section.indexPath maxWidth:section.collectionView.frame.size.width - section.sectionInset.left- section.footer.inset.left - section.sectionInset.right - section.footer.inset.right]; footer.frame = CGRectMake(section.sectionInset.left + section.footer.inset.left, section.sectionOffset + section.sectionInset.top + section.footer.inset.top + section.header.size + section.header.lastMargin + [section getColumnMaxHeight] + section.footer.topMargin, section.collectionView.frame.size.width - section.sectionInset.left - section.footer.inset.left - section.sectionInset.right - section.footer.inset.right, section.footer.size); } else { CGFloat x = section.sectionOffset + section.sectionInset.left + section.header.inset.left + section.header.size + section.header.inset.right + section.header.lastMargin + [section getColumnMaxHeight] + section.footer.topMargin; CGFloat y = section.sectionInset.top + section.footer.inset.top; CGFloat height = section.collectionView.frame.size.height - section.sectionInset.top- section.footer.inset.top - section.sectionInset.bottom - section.footer.inset.bottom; footer.frame = CGRectMake(x, y,section.footer.size, height); } footer.zIndex = section.footer.zIndex; return footer; } - (instancetype)updateFooterAttributesWithSection:(FMLayoutBaseSection *)section{ self.indexPath = section.indexPath; [self _onlyUpdateOffsetWith:section]; return self; } + (instancetype)bgAttributesWithSection:(FMLayoutBaseSection *)section{ if (!section.background) { return nil; } FMCollectionLayoutAttributes *bgAttr = [self layoutAttributesForSupplementaryViewOfKind:section.background.elementKind withIndexPath:section.indexPath]; bgAttr.direction = section.direction; if (bgAttr.direction == FMLayoutDirectionVertical) { bgAttr.frame = CGRectMake(section.background.inset.left, section.sectionOffset + section.background.inset.top, section.collectionView.frame.size.width - (section.background.inset.left + section.background.inset.right), section.sectionSize - (section.background.inset.top + section.background.inset.bottom)); } else { bgAttr.frame = CGRectMake(section.sectionOffset + section.background.inset.left, section.background.inset.top, section.sectionSize - (section.background.inset.left + section.background.inset.right) , section.collectionView.frame.size.height - (section.background.inset.top + section.background.inset.bottom)); } bgAttr.zIndex = section.background.zIndex; return bgAttr; } - (instancetype)updateBgAttributesWithSection:(FMLayoutBaseSection *)section{ self.indexPath = section.indexPath; [self _onlyUpdateOffsetWith:section]; return self; } - (void)_onlyUpdateOffsetWith:(FMLayoutBaseSection *)section{ CGAffineTransform transform = CGAffineTransformIdentity; if (!CGAffineTransformEqualToTransform(self.transform, CGAffineTransformIdentity)) { transform = self.transform; } self.transform = CGAffineTransformIdentity; if (self.direction == FMLayoutDirectionVertical) { CGRect frame = self.frame; frame.origin.y += section.changeOffset; self.frame = frame; } else { CGRect frame = self.frame; frame.origin.x += section.changeOffset; self.frame = frame; } self.transform = transform; } @end ================================================ FILE: FMLayoutKit/Classes/FMCollectionViewDelegateDataSourceProvider.h ================================================ // // FMCollectionViewDelegateDataSourceProvider.h // FMLayoutKit // // Created by 郑桂华 on 2021/3/27. // #import #import NS_ASSUME_NONNULL_BEGIN @class FMLayoutBaseSection; @interface FMCollectionViewDelegateDataSourceProvider : NSObject ///重写了set get 目标指向->layout.sections @property(nonatomic, strong)NSMutableArray *sections; @end NS_ASSUME_NONNULL_END ================================================ FILE: FMLayoutKit/Classes/FMCollectionViewDelegateDataSourceProvider.m ================================================ // // FMCollectionViewDelegateDataSourceProvider.m // FMLayoutKit // // Created by 郑桂华 on 2021/3/27. // #import "FMCollectionViewDelegateDataSourceProvider.h" #import "FMLayoutBaseSection.h" #import "FMLayoutHeader.h" #import "FMLayoutFooter.h" #import "FMLayoutBackground.h" #import "_FMLayoutSussEmptyView.h" @implementation FMCollectionViewDelegateDataSourceProvider - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{ return self.sections.count; } - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{ return self.sections[section].itemCount; } - (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{ FMLayoutBaseSection *sectionM = self.sections[indexPath.section]; UICollectionViewCell *cell = [sectionM dequeueReusableCellForIndexPath:indexPath]; if (sectionM.configureCellData) { sectionM.configureCellData(sectionM, cell, indexPath.item); } return cell; } - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath{ FMLayoutBaseSection *sectionM = self.sections[indexPath.section]; if (sectionM.header && [kind isEqualToString:UICollectionElementKindSectionHeader]) { UICollectionReusableView *header = [sectionM.header dequeueReusableViewWithCollection:collectionView indexPath:indexPath]; if (sectionM.configureHeaderData) { sectionM.configureHeaderData(sectionM, header); } return header; } if (sectionM.footer && [kind isEqualToString:UICollectionElementKindSectionFooter]) { UICollectionReusableView *footer = [sectionM.footer dequeueReusableViewWithCollection:collectionView indexPath:indexPath]; if (sectionM.configureFooterData) { sectionM.configureFooterData(sectionM, footer); } return footer; } if (sectionM.background && [kind isEqualToString:UICollectionElementKindSectionBackground]) { UICollectionReusableView *bg = [sectionM.background dequeueReusableViewWithCollection:collectionView indexPath:indexPath]; if (sectionM.configureBg) { sectionM.configureBg(sectionM, bg); } return bg; } return [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:NSStringFromClass([_FMLayoutSussEmptyView class]) forIndexPath:indexPath]; } #pragma mark ----- delegate - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{ if (indexPath.section < self.sections.count) { FMLayoutBaseSection *sectionM = self.sections[indexPath.section]; if (sectionM.clickCellBlock) { sectionM.clickCellBlock(sectionM, indexPath.item); } } } @end ================================================ FILE: FMLayoutKit/Classes/FMKVOArrayObject.h ================================================ // // FMKVOArrayObject.h // FMCollectionLayout // // Created by 周发明 on 2020/6/5. // #import NS_ASSUME_NONNULL_BEGIN @interface FMKVOArrayObject : NSObject @property (strong,nonatomic)NSMutableArray *targetArray; @end NS_ASSUME_NONNULL_END ================================================ FILE: FMLayoutKit/Classes/FMKVOArrayObject.m ================================================ // // FMKVOArrayObject.m // FMCollectionLayout // // Created by 周发明 on 2020/6/5. // #import "FMKVOArrayObject.h" #import "FMLayoutDebugLog.h" @implementation FMKVOArrayObject - (void)dealloc{ FMLayoutLog(@"FMKVOArrayObject dealloc"); } - (instancetype)init { self = [super init]; if (self) { self.targetArray = [NSMutableArray array]; } return self; } @end ================================================ FILE: FMLayoutKit/Classes/FMLayout.h ================================================ // // FMLayout.h // FMLayoutKit // // Created by 周发明 on 2020/6/16. // #import #import "FMLayoutBaseSection.h" #import "FMLayoutHeader.h" #import "FMLayoutFooter.h" #import "FMLayoutBackground.h" #import "FMCollectionLayoutAttributes.h" NS_ASSUME_NONNULL_BEGIN @interface FMLayout : UICollectionViewLayout @property(nonatomic, assign)FMLayoutDirection direction; @property(nonatomic, strong)NSMutableArray *sections; ///最后固定边距 跟section的inset无关 contentSize会自动加上去 @property(nonatomic, assign)CGFloat fixedLastMargin; ///是否只计算改变的布局 NO为每一次 都是重新计算所有布局 @property(nonatomic, assign)BOOL reLayoutOlnyChanged; ///最小可滑动的大小 横向-高度 纵向-宽度 @property(nonatomic, assign)CGFloat minContentSize; ///第一个Section的偏移量 @property(nonatomic, assign)CGFloat firstSectionOffset; @end NS_ASSUME_NONNULL_END ================================================ FILE: FMLayoutKit/Classes/FMLayout.m ================================================ // // FMLayout.m // FMLayoutKit // // Created by 周发明 on 2020/6/16. // #import "FMLayout.h" @interface FMLayout () @property(nonatomic, strong)NSMutableArray *headerInvalidateSections; @end @implementation FMLayout - (void)dealloc{ FMLayoutLog(@"FMLayout dealloc"); } - (instancetype)init{ if (self = [super init]) { self.headerInvalidateSections = [NSMutableArray array]; } return self; } - (void)prepareLayout{ [self handleSections]; } - (void)setSections:(NSMutableArray *)sections{ if (_sections == sections) { return; } if (![sections isKindOfClass:[NSMutableArray class]]) { _sections = [sections mutableCopy]; } else { _sections = sections; } [self invalidateLayout]; } - (void)setDirection:(FMLayoutDirection)direction{ if (_direction == direction) { return; } _direction = direction; for (FMLayoutBaseSection *section in self.sections) { section.hasHandle = NO; } [self invalidateLayout]; } - (void)handleSections{ [self registerSections]; self.headerInvalidateSections = [NSMutableArray array]; CFAbsoluteTime startTime =CFAbsoluteTimeGetCurrent(); CGFloat sectionOffset = self.firstSectionOffset; NSInteger sections = [self.collectionView numberOfSections]; sections = MIN(sections, self.sections.count); for (int i = 0; i < sections; i++) { CFAbsoluteTime oneTime =CFAbsoluteTimeGetCurrent(); FMLayoutBaseSection *section = self.sections[i]; section.direction = self.direction; if (section.isHidden) { continue; } NSIndexPath *sectionIndexPath = [NSIndexPath indexPathForItem:0 inSection:i]; section.indexPath = sectionIndexPath; if (self.reLayoutOlnyChanged) { if (section.sectionOffset != sectionOffset && section.hasHandle == YES) { section.handleType = FMLayoutHandleTypeOlnyChangeOffset; section.changeOffset = sectionOffset - section.sectionOffset; section.hasHandle = NO; } } else { section.hasHandle = NO; } if (!section.hasHandle) { section.sectionOffset = sectionOffset; [section handleLayout]; } sectionOffset = section.sectionOffset + section.sectionSize; section.changeOffset = 0; section.handleType = FMLayoutHandleTypeReLayout; section.hasHandle = YES; if (section.header) { if (section.header.type != FMLayoutHeaderTypeFixed) { [self.headerInvalidateSections addObject:section]; } } CFAbsoluteTime oneEnd = (CFAbsoluteTimeGetCurrent() - oneTime); FMLayoutLog([NSString stringWithFormat:@"单个Section%@布局计算耗时 %f ms", section,oneEnd *1000.0]); } CFAbsoluteTime linkTime = (CFAbsoluteTimeGetCurrent() - startTime); FMLayoutLog([NSString stringWithFormat:@"布局计算总耗时 %f ms", linkTime *1000.0]); } - (void)registerSections{ for (FMLayoutBaseSection *section in self.sections) { section.collectionView = self.collectionView; if (section.header) { [section.header registerElementWithCollection:section.collectionView]; } if (section.footer) { [section.footer registerElementWithCollection:section.collectionView]; } if (section.background) { [section.background registerElementWithCollection:section.collectionView]; } [section registerCells]; } } - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect{ if (self.direction == FMLayoutDirectionVertical) { rect.size.width = self.collectionView.frame.size.width; } else { rect.origin.y = 0; rect.size.height = self.collectionView.frame.size.height; } NSMutableArray *attrs = [NSMutableArray array]; for (FMLayoutBaseSection *section in self.sections) { [attrs addObjectsFromArray:[section showLayoutAttributesInRect:rect]]; } return attrs; } - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{ FMLayoutBaseSection *section = self.sections[indexPath.section]; if (!section.hasHandle) { return nil; } if (indexPath.item < section.itemsAttribute.count) { return section.itemsAttribute[indexPath.item]; } return nil; } - (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath{ FMLayoutBaseSection *section = self.sections[indexPath.section]; if (!section.hasHandle) { return nil; } if ([elementKind isEqualToString:UICollectionElementKindSectionHeader]) { return [section showHeaderLayout]; } else if ([elementKind isEqualToString:UICollectionElementKindSectionFooter]){ return section.footerAttribute; } else if ([elementKind isEqualToString:UICollectionElementKindSectionBackground]) { return section.bgAttribute; } return nil; } - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds{ if (!self.collectionView) { return NO; } BOOL change; if (self.direction == FMLayoutDirectionVertical) { change = self.collectionView.bounds.size.height != newBounds.size.height; newBounds.size.width = self.collectionView.frame.size.width; } else { change = self.collectionView.bounds.size.width != newBounds.size.width; newBounds.size.height = self.collectionView.frame.size.height; } NSMutableArray *headerIndexPaths = [NSMutableArray array]; for (FMLayoutBaseSection *section in self.headerInvalidateSections) { if ([section intersectsRect:newBounds]) { if (section.header.type != FMLayoutHeaderTypeFixed) { [headerIndexPaths addObject:section.indexPath]; } } else { if (section.header.type == FMLayoutHeaderTypeSuspensionAlways || section.header.type == FMLayoutHeaderTypeSuspensionBigger) { [headerIndexPaths addObject:section.indexPath]; } } } if (!change && headerIndexPaths.count > 0) { UICollectionViewLayoutInvalidationContext *context = [[UICollectionViewLayoutInvalidationContext alloc] init]; [context invalidateSupplementaryElementsOfKind:UICollectionElementKindSectionHeader atIndexPaths:headerIndexPaths]; [self invalidateLayoutWithContext:context]; } return change; } - (CGSize)collectionViewContentSize{ FMLayoutBaseSection *section = [self.sections lastObject]; if (self.direction == FMLayoutDirectionVertical) { CGSize contentSize = CGSizeMake(0, section.sectionOffset + section.sectionSize + self.fixedLastMargin); if (contentSize.height < self.minContentSize) { contentSize.height = self.minContentSize; } return contentSize; } else { CGSize contentSize = CGSizeMake(section.sectionOffset + section.sectionSize + self.fixedLastMargin, 0); if (contentSize.width < self.minContentSize) { contentSize.width = self.minContentSize; } return contentSize; } } - (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingSupplementaryElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)elementIndexPath{ return [self layoutAttributesForSupplementaryViewOfKind:elementKind atIndexPath:elementIndexPath]; } - (UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingSupplementaryElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)elementIndexPath{ return [self layoutAttributesForSupplementaryViewOfKind:elementKind atIndexPath:elementIndexPath]; } @end ================================================ FILE: FMLayoutKit/Classes/FMLayoutDebugLog.h ================================================ // // FMLayoutDebugLog.h // FMLayoutKit // // Created by 周发明 on 2020/6/17. // #import NS_ASSUME_NONNULL_BEGIN extern void FMLayoutLog(NSString *format); extern void FMLayoutOpenLog(void); extern void FMLayoutCloseLog(void); extern NSInteger FMLayoutRandomValue(NSInteger start, NSInteger end); NS_ASSUME_NONNULL_END ================================================ FILE: FMLayoutKit/Classes/FMLayoutDebugLog.m ================================================ // // FMLayoutDebugLog.m // FMLayoutKit // // Created by 周发明 on 2020/6/17. // #import "FMLayoutDebugLog.h" BOOL FMLayoutDebugLogOpen = NO; void FMLayoutLog(NSString *format){ #if DEBUG if (FMLayoutDebugLogOpen) { NSLog(@"%@", format); } #endif } void FMLayoutOpenLog(){ FMLayoutDebugLogOpen = YES; } void FMLayoutCloseLog(){ FMLayoutDebugLogOpen = NO; } NSInteger FMLayoutRandomValue(NSInteger start, NSInteger end){ NSInteger value = (arc4random() % (end - start + 1)) + start; return value; } ================================================ FILE: FMLayoutKit/Classes/FMLayoutKit.h ================================================ // // FMLayoutKit.h // FMLayoutKit // // Created by 周发明 on 2020/6/9. // #ifndef FMLayoutKit_h #define FMLayoutKit_h #import "FMTeslaLayoutView.h" #import "FMLayoutView.h" #import "FMLayout.h" #import "FMCollectionLayoutAttributes.h" #import "FMTeslaSuspensionHeightChangeDelegate.h" #import "FMLayoutFixedSection.h" #import "FMLayoutDynamicSection.h" #import "FMLayoutLabelSection.h" #import "FMLayoutFillSection.h" #import "FMLayoutAbsoluteSection.h" #import "FMLayoutCrossSection.h" #import "FMLayoutCrossTransformSection.h" #import "FMLayoutCombineSection.h" #import "FMLayoutScaleSection.h" #import "FMSupplementary.h" #import "FMLayoutHeader.h" #import "FMLayoutFooter.h" #import "FMLayoutBackground.h" #endif /* FMLayoutKit_h */ ================================================ FILE: FMLayoutKit/Classes/FMLayoutView.h ================================================ // // FMLayoutView.h // FMLayoutKit // // Created by 周发明 on 2020/4/1. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import #import "FMLayout.h" NS_ASSUME_NONNULL_BEGIN @interface FMLayoutView : UICollectionView @property(nonatomic, weak)FMLayout *layout; ///重写了set get 目标指向->layout.sections @property(nonatomic)NSMutableArray *sections; @property(nonatomic, assign)BOOL reloadOlnyChanged; ///是否允许长按拖拽排序 不支持夸分组 分组需要开启canLongPressExchange才可以移动拖拽排序 @property(nonatomic, assign)BOOL enableLongPressDrag; ///长按拖拽开始时配置cell显示的样式 @property(nonatomic, copy)UIView *(^configureSourceView)(UICollectionViewCell *sourceCell); - (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout NS_UNAVAILABLE; - (instancetype)initHorizontal; - (instancetype)initHorizontalWithFrame:(CGRect)frame; /// 循环遍历出更改过的sections 如果有过增删分组 请使用原有的reloadData方法 - (void)reloadChangedSectionsData; ///获取到滚动到indexPath位置偏移量 如果获取到的不准确 请先调用layoutIfNeeded方法 - (CGPoint)contentOffsetScrollToIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UICollectionViewScrollPosition)scrollPosition; @end NS_ASSUME_NONNULL_END ================================================ FILE: FMLayoutKit/Classes/FMLayoutView.m ================================================ // // FMLayoutView.m // FMLayoutKit // // Created by 周发明 on 2020/4/1. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import "FMLayoutView.h" #import "FMLayoutFixedSection.h" #import "FMLayoutLabelSection.h" #import "UIView+FMLayout.h" #import "_FMLayoutSussEmptyView.h" @interface FMLayoutView () @property(nonatomic, weak)id externalDataSource; @property(nonatomic, weak)id externalDelegate; @property(nonatomic, weak)UILongPressGestureRecognizer *dragLongPress; @property(nonatomic, weak)UIView *sourceCellView; @property(nonatomic, strong)NSIndexPath *sourceIndexPath; @property(nonatomic, assign)FMLayoutLongMoveType moveType; @end @implementation FMLayoutView #pragma mark ----- Public - (NSMutableArray *)sections{ return self.layout.sections; } - (void)setSections:(NSMutableArray *)sections{ self.layout.sections = sections; } - (void)setEnableLongPressDrag:(BOOL)enableLongPressDrag{ _enableLongPressDrag = enableLongPressDrag; self.dragLongPress.enabled = enableLongPressDrag; } - (void)setReloadOlnyChanged:(BOOL)reloadOlnyChanged{ _reloadOlnyChanged = reloadOlnyChanged; self.layout.reLayoutOlnyChanged = reloadOlnyChanged; } - (void)reloadChangedSectionsData{ if (self.reloadOlnyChanged) { if (self.sections == nil || self.sections.count == 0) { [super reloadData]; return; } NSMutableIndexSet *set = [NSMutableIndexSet indexSet]; for (int i = 0; i 0) { [super reloadSections:set]; } else { [super reloadData]; } } else { [super reloadData]; } } - (CGPoint)contentOffsetScrollToIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UICollectionViewScrollPosition)scrollPosition{ if (CGSizeEqualToSize(CGSizeZero, self.contentSize)) { [self layoutIfNeeded]; } UICollectionViewLayoutAttributes *layoutAttr = [self.layout layoutAttributesForItemAtIndexPath:indexPath]; CGPoint offset = self.contentOffset; if (!layoutAttr) { return offset; } if (self.layout.direction == FMLayoutDirectionVertical) { switch (scrollPosition) { case UICollectionViewScrollPositionTop: offset.y = CGRectGetMinY(layoutAttr.frame); break; case UICollectionViewScrollPositionCenteredVertically: offset.y = CGRectGetMinY(layoutAttr.frame) - self.frame.size.height * 0.5 + layoutAttr.frame.size.height * 0.5; break; case UICollectionViewScrollPositionBottom: offset.y = CGRectGetMinY(layoutAttr.frame) - self.frame.size.height + layoutAttr.frame.size.height; break; default: break; } if (offset.y < 0) { offset.y = 0; } } else { switch (scrollPosition) { case UICollectionViewScrollPositionLeft: offset.x = CGRectGetMinX(layoutAttr.frame); break; case UICollectionViewScrollPositionCenteredHorizontally: offset.x = CGRectGetMinX(layoutAttr.frame) - self.frame.size.width * 0.5 + layoutAttr.frame.size.width * 0.5; break; case UICollectionViewScrollPositionRight: offset.x = CGRectGetMinX(layoutAttr.frame) - self.frame.size.width + layoutAttr.frame.size.width; break; default: break; } if (offset.x < 0) { offset.x = 0; } } return offset; } #pragma mark --- 长按拖拽相关 - (void)setSourceIndexPath:(NSIndexPath *)sourceIndexPath{ if (sourceIndexPath) { FMLayoutBaseSection *section = self.sections[sourceIndexPath.section]; if (section.canLongPressExchange) { BOOL canLong = YES; if (section.canLongPressExchangeItem) { canLong = section.canLongPressExchangeItem(section, sourceIndexPath.item); } if (canLong) { _sourceIndexPath = sourceIndexPath; self.moveType = section.moveType; } } } else { _sourceIndexPath = nil; } } - (void)longPress:(UILongPressGestureRecognizer *)longP{ CGPoint location = [longP locationInView:self]; switch (longP.state) { case UIGestureRecognizerStateBegan: FMLayoutLog(@"长按开始"); self.sourceIndexPath = [self indexPathForItemAtPoint:location]; if (self.sourceIndexPath) { [self initSourceView]; [self sourceCellViewMoveLocation:location animation:YES]; } break; case UIGestureRecognizerStateChanged: FMLayoutLog(@"长按移动"); { NSIndexPath *indexPath = [self indexPathForItemAtPoint:location]; if (indexPath) { if (self.sourceIndexPath == nil) { self.sourceIndexPath = indexPath; [self initSourceView]; [self sourceCellViewMoveLocation:location animation:YES]; } else { if (![indexPath isEqual:self.sourceIndexPath] && indexPath.section == self.sourceIndexPath.section) { FMLayoutBaseSection *section = self.sections[indexPath.section]; BOOL canExchange = YES; if (section.canLongPressExchangeItem) { canExchange = section.canLongPressExchangeItem(section, indexPath.item); } if (canExchange) { [self moveItemAtIndexPath:self.sourceIndexPath toIndexPath:indexPath]; [section exchangeObjectAtIndex:self.sourceIndexPath.item toIndex:indexPath.item]; self.sourceIndexPath = indexPath; { UICollectionViewCell *cell = [self cellForItemAtIndexPath:indexPath]; CGRect frame = self.sourceCellView.frame; frame.size = cell.frame.size; [UIView animateWithDuration:0.2 animations:^{ self.sourceCellView.frame = frame; }]; } } } } } [self sourceCellViewMoveLocation:location animation:NO]; } break; case UIGestureRecognizerStateEnded: case UIGestureRecognizerStateCancelled: case UIGestureRecognizerStateFailed: FMLayoutLog(@"长按结束"); { if (self.sourceIndexPath) { UICollectionViewCell *cell = [self cellForItemAtIndexPath:self.sourceIndexPath]; self.sourceIndexPath = nil; [UIView animateWithDuration:0.2 animations:^{ self.sourceCellView.frame = cell.frame; } completion:^(BOOL finished) { [self.sourceCellView removeFromSuperview]; cell.hidden = NO; }]; } } break; default: break; } } - (void)initSourceView{ if (self.sourceCellView) { [self.sourceCellView removeFromSuperview]; } UICollectionViewCell *sourceCell = [self cellForItemAtIndexPath:self.sourceIndexPath]; UIView *sourceView; if (self.configureSourceView) { sourceView = self.configureSourceView(sourceCell); } else { sourceView = [sourceCell snapshotView]; } [self addSubview:sourceView]; sourceCell.hidden = YES; self.sourceCellView = sourceView; } - (void)sourceCellViewMoveLocation:(CGPoint)location animation:(BOOL)animation{ CGPoint center = self.sourceCellView.center; if (self.moveType == FMLayoutLongMoveTable) { center.y = location.y; } else { center = location; } if (animation) { [UIView animateWithDuration:0.2 animations:^{ self.sourceCellView.center = center; }]; } else { self.sourceCellView.center = center; } } #pragma mark --- dealloc - (void)dealloc{ FMLayoutLog(@"FMLayoutView dealloc"); } #pragma mark --- 初始化方法 - (instancetype)initHorizontal{ return [self initHorizontalWithFrame:CGRectZero]; } - (instancetype)initHorizontalWithFrame:(CGRect)frame{ if (self = [self initWithFrame:frame]) { self.layout.direction = FMLayoutDirectionHorizontal; } return self; } - (instancetype)init { return [self initWithFrame:CGRectZero]; } - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame collectionViewLayout:[[FMLayout alloc] init]]; if (self) { if(@available(iOS 11.0, *)) { self.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; } self.layout = (FMLayout *)self.collectionViewLayout; self.dataSource = self; self.delegate = self; self.reloadOlnyChanged = YES; self.directionalLockEnabled = YES; [self registerClass:[_FMLayoutSussEmptyView class] forSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:NSStringFromClass([_FMLayoutSussEmptyView class])]; [self registerClass:[_FMLayoutSussEmptyView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:NSStringFromClass([_FMLayoutSussEmptyView class])]; [self registerClass:[_FMLayoutSussEmptyView class] forSupplementaryViewOfKind:UICollectionElementKindSectionBackground withReuseIdentifier:NSStringFromClass([_FMLayoutSussEmptyView class])]; UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)]; [self addGestureRecognizer:longPress]; longPress.enabled = NO; self.dragLongPress = longPress; } return self; } #pragma mark --- 重写父类方法 - (void)setDataSource:(id)dataSource{ if (dataSource == self) { self.externalDataSource = nil; } else { self.externalDataSource = dataSource; } [super setDataSource:self]; } - (void)setDelegate:(id)delegate{ if (delegate == nil) { return; } if (delegate == self) { self.externalDelegate = nil; } else { self.externalDelegate = delegate; } [super setDelegate:self]; } - (void)scrollToItemAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UICollectionViewScrollPosition)scrollPosition animated:(BOOL)animated{ CGPoint offset = [self contentOffsetScrollToIndexPath:indexPath atScrollPosition:scrollPosition]; [self setContentOffset:offset animated:animated]; } - (void)reloadSections:(NSIndexSet *)sections{ NSArray *layoutSections = [self.sections objectsAtIndexes:sections]; for (FMLayoutBaseSection *section in layoutSections) { section.hasHandle = NO; } [super reloadSections:sections]; } - (void)reloadItemsAtIndexPaths:(NSArray *)indexPaths{ for (NSIndexPath *indexPath in indexPaths) { NSInteger section = indexPath.section; if (section < self.sections.count) { FMLayoutBaseSection *layoutSection = self.sections[section]; layoutSection.hasHandle = NO; } } [super reloadItemsAtIndexPaths:indexPaths]; } #pragma mark ----- dataSource - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{ if (self.externalDataSource && [self.externalDataSource respondsToSelector:@selector(numberOfSectionsInCollectionView:)]) { return [self.externalDataSource numberOfSectionsInCollectionView:collectionView]; } return self.sections.count; } - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{ if ([self.externalDataSource respondsToSelector:@selector(collectionView:numberOfItemsInSection:)]) { return [self.externalDataSource collectionView:collectionView numberOfItemsInSection:section]; } return self.sections[section].itemCount; } - (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{ if ([self.externalDataSource respondsToSelector:@selector(collectionView:cellForItemAtIndexPath:)]) { return [self.externalDataSource collectionView:collectionView cellForItemAtIndexPath:indexPath]; } FMLayoutBaseSection *sectionM = self.sections[indexPath.section]; UICollectionViewCell *cell = [sectionM dequeueReusableCellForIndexPath:indexPath]; if (sectionM.configureCellData) { sectionM.configureCellData(sectionM, cell, indexPath.item); } return cell; } - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath{ if (self.externalDataSource && [self.externalDataSource respondsToSelector:@selector(collectionView:viewForSupplementaryElementOfKind:atIndexPath:)]) { return [self.externalDataSource collectionView:collectionView viewForSupplementaryElementOfKind:kind atIndexPath:indexPath]; } FMLayoutBaseSection *sectionM = self.sections[indexPath.section]; if (sectionM.header && [kind isEqualToString:UICollectionElementKindSectionHeader]) { UICollectionReusableView *header = [sectionM.header dequeueReusableViewWithCollection:collectionView indexPath:indexPath]; if (sectionM.configureHeaderData) { sectionM.configureHeaderData(sectionM, header); } return header; } if (sectionM.footer && [kind isEqualToString:UICollectionElementKindSectionFooter]) { UICollectionReusableView *footer = [sectionM.footer dequeueReusableViewWithCollection:collectionView indexPath:indexPath]; if (sectionM.configureFooterData) { sectionM.configureFooterData(sectionM, footer); } return footer; } if (sectionM.background && [kind isEqualToString:UICollectionElementKindSectionBackground]) { UICollectionReusableView *bg = [sectionM.background dequeueReusableViewWithCollection:collectionView indexPath:indexPath]; if (sectionM.configureBg) { sectionM.configureBg(sectionM, bg); } return bg; } return [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:NSStringFromClass([_FMLayoutSussEmptyView class]) forIndexPath:indexPath]; } - (BOOL)collectionView:(UICollectionView *)collectionView canMoveItemAtIndexPath:(NSIndexPath *)indexPath API_AVAILABLE(ios(9.0)){ return [self.externalDataSource respondsToSelector:@selector(collectionView:canMoveItemAtIndexPath:)] && [self.externalDataSource collectionView:collectionView canMoveItemAtIndexPath:indexPath]; } - (void)collectionView:(UICollectionView *)collectionView moveItemAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath*)destinationIndexPath API_AVAILABLE(ios(9.0)){ if ([self.externalDataSource respondsToSelector:@selector(collectionView:moveItemAtIndexPath:toIndexPath:)]) { [self.externalDataSource collectionView:collectionView moveItemAtIndexPath:sourceIndexPath toIndexPath:destinationIndexPath]; } } - (nullable NSArray *)indexTitlesForCollectionView:(UICollectionView *)collectionView API_AVAILABLE(tvos(10.2)){ if ([self.externalDataSource respondsToSelector:@selector(indexTitlesForCollectionView:)]) { return [self.externalDataSource indexTitlesForCollectionView:collectionView]; } return nil; } - (NSIndexPath *)collectionView:(UICollectionView *)collectionView indexPathForIndexTitle:(NSString *)title atIndex:(NSInteger)index API_AVAILABLE(tvos(10.2)){ if ([self.externalDataSource respondsToSelector:@selector(collectionView:indexPathForIndexTitle:atIndex:)]) { return [self.externalDataSource collectionView:collectionView indexPathForIndexTitle:title atIndex:index]; } return nil; } #pragma mark ----- delegate - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{ if (indexPath.section < self.sections.count) { FMLayoutBaseSection *sectionM = self.sections[indexPath.section]; if (sectionM.clickCellBlock) { sectionM.clickCellBlock(sectionM, indexPath.item); } } if ([self.externalDelegate respondsToSelector:@selector(collectionView:didSelectItemAtIndexPath:)]) { [self.externalDelegate collectionView:collectionView didSelectItemAtIndexPath:indexPath]; } } - (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath{ if ([self.externalDelegate respondsToSelector:@selector(collectionView:willDisplayCell:forItemAtIndexPath:)]) { [self.externalDelegate collectionView:collectionView willDisplayCell:cell forItemAtIndexPath:indexPath]; } } - (void)collectionView:(UICollectionView *)collectionView willDisplaySupplementaryView:(UICollectionReusableView *)view forElementKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath{ if ([self.externalDelegate respondsToSelector:@selector(collectionView:willDisplaySupplementaryView:forElementKind:atIndexPath:)]) { [self.externalDelegate collectionView:collectionView willDisplaySupplementaryView:view forElementKind:elementKind atIndexPath:indexPath]; } } - (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath{ if ([self.externalDelegate respondsToSelector:@selector(collectionView:didEndDisplayingCell:forItemAtIndexPath:)]) { [self.externalDelegate collectionView:collectionView didEndDisplayingCell:cell forItemAtIndexPath:indexPath]; } } - (void)collectionView:(UICollectionView *)collectionView didEndDisplayingSupplementaryView:(UICollectionReusableView *)view forElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath{ if ([self.externalDelegate respondsToSelector:@selector(collectionView:didEndDisplayingSupplementaryView:forElementOfKind:atIndexPath:)]) { [self.externalDelegate collectionView:collectionView didEndDisplayingSupplementaryView:view forElementOfKind:elementKind atIndexPath:indexPath]; } } #pragma mark ----- scroll delegate - (void)scrollViewDidScroll:(UIScrollView *)scrollView{ if ([self.externalDelegate respondsToSelector:@selector(scrollViewDidScroll:)]) { [self.externalDelegate scrollViewDidScroll:scrollView]; } } - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{ if ([self.externalDelegate respondsToSelector:@selector(scrollViewWillBeginDragging:)]) { [self.externalDelegate scrollViewWillBeginDragging:scrollView]; } } - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset{ if ([self.externalDelegate respondsToSelector:@selector(scrollViewWillEndDragging:withVelocity:targetContentOffset:)]) { [self.externalDelegate scrollViewWillEndDragging:scrollView withVelocity:velocity targetContentOffset:targetContentOffset]; } } - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{ if ([self.externalDelegate respondsToSelector:@selector(scrollViewDidEndDragging:willDecelerate:)]) { [self.externalDelegate scrollViewDidEndDragging:scrollView willDecelerate:decelerate]; } } - (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView{ if ([self.externalDelegate respondsToSelector:@selector(scrollViewWillBeginDecelerating:)]) { [self.externalDelegate scrollViewWillBeginDecelerating:scrollView]; } } - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{ if ([self.externalDelegate respondsToSelector:@selector(scrollViewDidEndDecelerating:)]) { [self.externalDelegate scrollViewDidEndDecelerating:scrollView]; } } - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView{ if ([self.externalDelegate respondsToSelector:@selector(scrollViewDidEndScrollingAnimation:)]) { [self.externalDelegate scrollViewDidEndScrollingAnimation:scrollView]; } } - (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView{ if ([self.externalDelegate respondsToSelector:@selector(scrollViewShouldScrollToTop:)]) { return [self.externalDelegate scrollViewShouldScrollToTop:scrollView]; } return YES; } - (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView{ if ([self.externalDelegate respondsToSelector:@selector(scrollViewDidScrollToTop:)]) { [self.externalDelegate scrollViewDidScrollToTop:scrollView]; } } - (void)scrollViewDidChangeAdjustedContentInset:(UIScrollView *)scrollView API_AVAILABLE(ios(11.0), tvos(11.0)){ if ([self.externalDelegate respondsToSelector:@selector(scrollViewDidChangeAdjustedContentInset:)]) { [self.externalDelegate scrollViewDidChangeAdjustedContentInset:scrollView]; } } @end ================================================ FILE: FMLayoutKit/Classes/FMTeslaLayoutView.h ================================================ // // FMTeslaLayoutView.h // FMCollectionLayout_Example // // Created by 周发明 on 2020/4/8. // Copyright © 2020 周发明. All rights reserved. // #import NS_ASSUME_NONNULL_BEGIN @class FMLayoutView, FMTeslaLayoutView, FMLayoutBaseSection; @protocol FMTeslaLayoutViewDelegate @optional ///滚动结束事件 - (void)tesla:(FMTeslaLayoutView *)tesla didScrollEnd:(NSInteger)index currentScrollView:(UIScrollView *)scrollView; ///滚动事件 - (void)tesla:(FMTeslaLayoutView *)tesla scrollViewDidScroll:(UIScrollView *)scrollView; /// 当前上下滚动的事件 - (void)tesla:(FMTeslaLayoutView *)tesla currentScrollViewScrollDidScroll:(UIScrollView *)currentScrollView contentOffset:(CGPoint)contentOffset; /// 配置FMCollectionLayoutView ///2 - (void)tesla:(FMTeslaLayoutView *)tesla currentShowScrollView:(UIScrollView *)scrollView index:(NSInteger)index; ///0 即将根据Index创建FMCollectionLayoutView - (void)tesla:(FMTeslaLayoutView *)tesla willCreateScrollViewWithIndex:(NSInteger)index; ///0.5 根据Index自己创建FMCollectionLayoutView shareHeight为共享头部的高度 请将shareHeight顶部空出来并且请保持不使用contentInset 如果返回nil会自动创建FMLayoutView - (UIScrollView *)tesla:(FMTeslaLayoutView *)tesla customCreateWithIndex:(NSInteger)index shareHeight:(CGFloat)shareHeight; ///1 根据Index创建完毕UIScrollView - (void)tesla:(FMTeslaLayoutView *)tesla didCreatedScrollViewWithIndex:(NSInteger)index scrollView:(UIScrollView *)scrollView; /// 悬停标签控制view的尺寸最小高度 可以留着做效果 - (CGFloat)shareSuspensionMinHeightWithTesla:(FMTeslaLayoutView *)tesla; @end @protocol FMTeslaLayoutViewDataSource @required - (NSInteger)numberOfScreenInTesla:(FMTeslaLayoutView *)tesla; @optional - (NSArray *)shareSectionsInTesla:(FMTeslaLayoutView *)tesla; @end @class FMLayoutBaseSection; @interface FMTeslaLayoutView : UIView @property(nonatomic, weak)id delegate; @property(nonatomic, weak)id dataSource; @property(nonatomic, assign)BOOL horizontalCanScroll; @property(nonatomic, assign)BOOL allShareStickTop; @property(nonatomic, assign)NSInteger selectIndex; @property(nonatomic, assign)BOOL isLoadSubView; @property(nonatomic, assign)CGFloat shareHeight; @property(nonatomic, strong, readonly)FMLayoutView *shareLayoutView; - (void)reLoadSubViews; - (void)reloadData; - (void)reloadDataWithIndex:(NSInteger)index; - (void)scrollToIndex:(NSInteger)index animated:(BOOL)animated; @end NS_ASSUME_NONNULL_END ================================================ FILE: FMLayoutKit/Classes/FMTeslaLayoutView.m ================================================ // // FMTeslaLayoutView.m // FMCollectionLayout_Example // // Created by 周发明 on 2020/4/8. // Copyright © 2020 周发明. All rights reserved. // #import "FMTeslaLayoutView.h" #import "FMLayoutView.h" #import "FMTeslaSuspensionHeightChangeDelegate.h" @interface FM_ScrollView : UIScrollView @property(nonatomic, copy)BOOL(^panGesCanBegin)(CGPoint panPoint); @end @implementation FM_ScrollView - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{ if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) { UIPanGestureRecognizer *pan = (UIPanGestureRecognizer *)gestureRecognizer; CGPoint panPoint = [pan locationInView:self]; if (self.panGesCanBegin) { return self.panGesCanBegin(panPoint); } } return [super gestureRecognizerShouldBegin:gestureRecognizer]; } @end @interface FMTeslaLayoutView () @property(nonatomic, weak)FMLayoutBaseSection *suspensionAlwaysHeader; @property(nonatomic, weak)FM_ScrollView *scrollView; @property(nonatomic, strong)FMLayoutView *shareLayoutView; @property(nonatomic, weak)UIScrollView *currentScrollView; @property(nonatomic, strong)NSMutableDictionary *layoutViews; @property(nonatomic, assign)BOOL isLayoutSubView; @property(nonatomic, assign, readonly)CGFloat shareSuspensionDifferHeight; @end @implementation FMTeslaLayoutView - (void)reLoadSubViews{ if (self.isLayoutSubView && self.isLoadSubView) { self.isLoadSubView = NO; for (UIView *view in self.layoutViews.allValues) { [view removeFromSuperview]; } self.layoutViews = [NSMutableDictionary dictionary]; [self loadSubViews]; } } - (void)reloadData{ [self.shareLayoutView reloadData]; if ([self.currentScrollView isKindOfClass:[UITableView class]]) { [(UITableView *)self.currentScrollView reloadData]; } else if ([self.currentScrollView isKindOfClass:[UICollectionView class]]) { [(UICollectionView *)self.currentScrollView reloadData]; } } - (void)reloadDataWithIndex:(NSInteger)index{ UIScrollView *scrollView = self.layoutViews[@(index)]; if (scrollView) { if ([scrollView isKindOfClass:[UITableView class]]) { [(UITableView *)scrollView reloadData]; } else if ([scrollView isKindOfClass:[UICollectionView class]]) { [(UICollectionView *)scrollView reloadData]; } } } - (void)scrollToIndex:(NSInteger)index animated:(BOOL)animated{ CGFloat offsetX = index * self.scrollView.bounds.size.width; if (offsetX == self.scrollView.contentOffset.x) { return; } if (animated) { self.userInteractionEnabled = NO; } [self scrollStart]; [self.scrollView setContentOffset:CGPointMake(offsetX, 0) animated:animated]; if (!animated) { [self scrollEnd]; } } - (void)dealloc{ FMLayoutLog(@"FMTeslaLayoutView dealloc"); [self.currentScrollView removeObserver:self forKeyPath:@"contentOffset"]; } - (CGFloat)shareSuspensionDifferHeight{ if (self.suspensionAlwaysHeader) { if ([self.delegate respondsToSelector:@selector(shareSuspensionMinHeightWithTesla:)]) { CGFloat min = [self.delegate shareSuspensionMinHeightWithTesla:self]; if (self.suspensionAlwaysHeader.header.size > min) { return self.suspensionAlwaysHeader.header.size - min; } else { return 0; } } else { return 0; } } return 0; } - (FM_ScrollView *)scrollView{ if (_scrollView == nil) { FM_ScrollView *scroll = [[FM_ScrollView alloc] init]; if(@available(iOS 11.0, *)) { scroll.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; } scroll.backgroundColor = [UIColor clearColor]; scroll.pagingEnabled = YES; scroll.delegate = self; scroll.bounces = YES; scroll.alwaysBounceHorizontal = YES; scroll.showsHorizontalScrollIndicator = NO; [self addSubview:scroll]; __weak typeof(self) weakSelf = self; [scroll setPanGesCanBegin:^BOOL(CGPoint panPoint) { CGFloat offsetY = weakSelf.currentScrollView.contentOffset.y; CGFloat topCanPanY = weakSelf.shareLayoutView.frame.size.height + weakSelf.shareLayoutView.frame.origin.y - offsetY; if (topCanPanY < weakSelf.suspensionAlwaysHeader.header.size) { topCanPanY = weakSelf.suspensionAlwaysHeader.header.size; } return panPoint.y > topCanPanY; }]; _scrollView = scroll; } return _scrollView; } - (FMLayoutView *)shareLayoutView{ if (_shareLayoutView == nil) { _shareLayoutView = [[FMLayoutView alloc] init]; _shareLayoutView.backgroundColor = [UIColor clearColor]; } return _shareLayoutView; } - (void)setCurrentScrollView:(UIScrollView *)currentScrollView{ if (_currentScrollView) { [_currentScrollView removeObserver:self forKeyPath:@"contentOffset"]; } _currentScrollView = currentScrollView; if (currentScrollView) { [currentScrollView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil]; } } - (void)setHorizontalCanScroll:(BOOL)horizontalCanScroll{ _horizontalCanScroll = horizontalCanScroll; self.scrollView.scrollEnabled = horizontalCanScroll; } - (void)setClipsToBounds:(BOOL)clipsToBounds{ self.scrollView.clipsToBounds = clipsToBounds; self.shareLayoutView.clipsToBounds = clipsToBounds; [self.layoutViews.allValues enumerateObjectsUsingBlock:^(UIScrollView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { obj.clipsToBounds = clipsToBounds; }]; [super setClipsToBounds:clipsToBounds]; } - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.backgroundColor = [UIColor whiteColor]; self.clipsToBounds = YES; self.horizontalCanScroll = YES; self.layoutViews = [NSMutableDictionary dictionary]; } return self; } - (void)loadSubViews{ CGFloat shareHeight = 0; if ([self.dataSource respondsToSelector:@selector(shareSectionsInTesla:)]) { NSMutableArray *sections = [[self.dataSource shareSectionsInTesla:self] mutableCopy]; if (self.shareLayoutView.superview != self) { [self.shareLayoutView removeFromSuperview]; [self addSubview:self.shareLayoutView]; self.shareLayoutView.frame = self.bounds; } [self.shareLayoutView.layout setSections:sections]; [self.shareLayoutView reloadData]; [self.shareLayoutView layoutIfNeeded]; shareHeight = [self.shareLayoutView.layout collectionViewContentSize].height; self.shareLayoutView.frame = CGRectMake(0, 0, self.bounds.size.width, shareHeight); self.suspensionAlwaysHeader = sections.count > 0 ? ([sections lastObject].header.type == FMLayoutHeaderTypeSuspensionAlways ? [sections lastObject] :nil) : nil; } else { self.shareLayoutView.frame = CGRectZero; } self.shareHeight = shareHeight; NSInteger nums = [self.dataSource numberOfScreenInTesla:self]; self.scrollView.contentSize = CGSizeMake(self.scrollView.bounds.size.width * nums, 0); [self setCurrentLayoutViewWithIndex:self.selectIndex]; [self.shareLayoutView removeFromSuperview]; [self.currentScrollView addSubview:self.shareLayoutView]; [self.shareLayoutView reloadData]; self.isLoadSubView = YES; [self scrollToIndex:self.selectIndex animated:NO]; } - (void)setCurrentLayoutViewWithIndex:(NSInteger)index{ UIScrollView *layoutView = self.layoutViews[@(index)]; if (layoutView == nil) { if ([self.delegate respondsToSelector:@selector(tesla:willCreateScrollViewWithIndex:)]) { [self.delegate tesla:self willCreateScrollViewWithIndex:index]; } UIScrollView *scrollView; if ([self.delegate respondsToSelector:@selector(tesla:customCreateWithIndex:shareHeight:)]) { scrollView = [self.delegate tesla:self customCreateWithIndex:index shareHeight:self.shareHeight]; } if (scrollView == nil) { FMLayoutView *layoutView = [[FMLayoutView alloc] init]; layoutView.backgroundColor = [UIColor clearColor]; layoutView.bounces = YES; layoutView.alwaysBounceVertical = YES; layoutView.showsVerticalScrollIndicator = NO; layoutView.clipsToBounds = self.clipsToBounds; layoutView.layout.minContentSize = self.shareHeight - self.suspensionAlwaysHeader.header.size + self.scrollView.bounds.size.height; [layoutView.layout setFirstSectionOffset:self.shareHeight]; scrollView = layoutView; } if ([self.delegate respondsToSelector:@selector(tesla:didCreatedScrollViewWithIndex:scrollView:)]) { [self.delegate tesla:self didCreatedScrollViewWithIndex:index scrollView:scrollView]; } scrollView.frame = CGRectMake(self.scrollView.bounds.size.width * index, 0, self.scrollView.bounds.size.width, self.scrollView.bounds.size.height); [self.scrollView addSubview:scrollView]; if ([scrollView isKindOfClass:[UITableView class]]) { [(UITableView *)scrollView reloadData]; } else if ([scrollView isKindOfClass:[UICollectionView class]]) { [(UICollectionView *)scrollView reloadData]; } self.layoutViews[@(index)] = scrollView; layoutView = scrollView; if (self.currentScrollView) { CGPoint contentOffset = self.currentScrollView.contentOffset; if (contentOffset.y < self.shareLayoutView.frame.size.height-self.suspensionAlwaysHeader.sectionSize+self.shareSuspensionDifferHeight) { scrollView.contentOffset = contentOffset; } else { scrollView.contentOffset = CGPointMake(contentOffset.x, self.shareLayoutView.frame.size.height-self.suspensionAlwaysHeader.sectionSize+self.shareSuspensionDifferHeight); } } } if ([self.delegate respondsToSelector:@selector(tesla:currentShowScrollView:index:)]) { [self.delegate tesla:self currentShowScrollView:layoutView index:index]; } self.currentScrollView = layoutView; } - (void)layoutSubviews{ [super layoutSubviews]; self.scrollView.frame = self.bounds; self.isLayoutSubView = YES; if (!self.isLoadSubView) { [self loadSubViews]; } } - (void)scrollStart{ if (!self.scrollView.tracking) { self.userInteractionEnabled = NO; } if (self.shareLayoutView.superview != self) { [self.shareLayoutView removeFromSuperview]; } CGRect frame = self.shareLayoutView.frame; frame.origin.y = - self.currentScrollView.contentOffset.y; CGFloat minY = self.suspensionAlwaysHeader.sectionSize - self.shareLayoutView.frame.size.height - self.shareSuspensionDifferHeight; if (frame.origin.y < minY) { frame.origin.y = minY; } self.shareLayoutView.frame = frame; [self addSubview:self.shareLayoutView]; } - (void)scrollEnd{ self.userInteractionEnabled = YES; NSInteger index = self.scrollView.contentOffset.x / self.scrollView.bounds.size.width; [self setCurrentLayoutViewWithIndex:index]; if (self.shareLayoutView.superview != self.currentScrollView) { [self.shareLayoutView removeFromSuperview]; } if ([self.delegate respondsToSelector:@selector(tesla:didScrollEnd:currentScrollView:)]) { [self.delegate tesla:self didScrollEnd:index currentScrollView:self.currentScrollView]; } CGFloat y = self.currentScrollView.contentOffset.y; if (y < self.shareLayoutView.frame.size.height-self.suspensionAlwaysHeader.sectionSize+self.shareSuspensionDifferHeight) { CGRect frame = self.shareLayoutView.frame; frame.origin.y = 0; frame.origin.x = 0; self.shareLayoutView.frame = frame; } else { CGRect frame = self.shareLayoutView.frame; frame.origin.y = y + self.suspensionAlwaysHeader.sectionSize - self.shareSuspensionDifferHeight - self.shareLayoutView.frame.size.height; frame.origin.x = 0; self.shareLayoutView.frame = frame; } [self.currentScrollView addSubview:self.shareLayoutView]; self.selectIndex = index; } #pragma mark ------- observeValueForKeyPath - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{ CGPoint contentOffset = [change[NSKeyValueChangeNewKey] CGPointValue]; if ([self.delegate respondsToSelector:@selector(tesla:currentScrollViewScrollDidScroll:contentOffset:)]) { [self.delegate tesla:self currentScrollViewScrollDidScroll:self.currentScrollView contentOffset:contentOffset]; } if (contentOffset.y < self.shareLayoutView.frame.size.height-self.suspensionAlwaysHeader.sectionSize+self.shareSuspensionDifferHeight) { for (UIScrollView *coll in self.layoutViews.allValues) { if (coll != self.currentScrollView) { coll.contentOffset = contentOffset; } else { CGRect frame = self.shareLayoutView.frame; frame.origin.y = 0; frame.size.height = self.shareHeight; self.shareLayoutView.frame = frame; if (contentOffset.y < 0) { CGRect frame = self.shareLayoutView.frame; frame.origin.y = contentOffset.y; frame.size.height = self.shareHeight - contentOffset.y; self.shareLayoutView.frame = frame; if (!self.allShareStickTop) { self.shareLayoutView.contentOffset = CGPointMake(0, contentOffset.y); } } if (contentOffset.y > self.shareLayoutView.frame.size.height-self.suspensionAlwaysHeader.sectionSize) { if (@available(iOS 9.0, *)) { UICollectionReusableView *header = [self.shareLayoutView supplementaryViewForElementKind:self.suspensionAlwaysHeader.header.elementKind atIndexPath:self.suspensionAlwaysHeader.indexPath]; CGFloat diff = (contentOffset.y - self.shareLayoutView.frame.size.height+self.suspensionAlwaysHeader.sectionSize); CGFloat showHeight = self.suspensionAlwaysHeader.header.size - diff; if ([header conformsToProtocol:@protocol(FMTeslaSuspensionHeightChangeDelegate)] && [header respondsToSelector:@selector(teslaSuspensionHeaderShouldShowHeight:)]) { id delegate = header; [delegate teslaSuspensionHeaderShouldShowHeight:showHeight]; } } else { // Fallback on earlier versions } } else { if (@available(iOS 9.0, *)) { UICollectionReusableView *header = [self.shareLayoutView supplementaryViewForElementKind:self.suspensionAlwaysHeader.header.elementKind atIndexPath:self.suspensionAlwaysHeader.indexPath]; CGFloat diff = 0; CGFloat showHeight = self.suspensionAlwaysHeader.header.size - diff; if ([header conformsToProtocol:@protocol(FMTeslaSuspensionHeightChangeDelegate)] && [header respondsToSelector:@selector(teslaSuspensionHeaderShouldShowHeight:)]) { id delegate = header; [delegate teslaSuspensionHeaderShouldShowHeight:showHeight]; } } else { // Fallback on earlier versions } } } } } else { for (UIScrollView *coll in self.layoutViews.allValues) { if (coll != self.currentScrollView) { if (coll.contentOffset.y < self.shareLayoutView.frame.size.height-self.suspensionAlwaysHeader.sectionSize + self.shareSuspensionDifferHeight) { coll.contentOffset = CGPointMake(0, self.shareLayoutView.frame.size.height-self.suspensionAlwaysHeader.sectionSize + self.shareSuspensionDifferHeight); } } else { CGRect frame = self.shareLayoutView.frame; frame.origin.y = contentOffset.y - self.shareLayoutView.frame.size.height+self.suspensionAlwaysHeader.sectionSize-self.shareSuspensionDifferHeight; frame.size.height = self.shareHeight; self.shareLayoutView.frame = frame; if (@available(iOS 9.0, *)) { UICollectionReusableView *header = [self.shareLayoutView supplementaryViewForElementKind:self.suspensionAlwaysHeader.header.elementKind atIndexPath:self.suspensionAlwaysHeader.indexPath]; CGFloat diff = self.shareSuspensionDifferHeight; CGFloat showHeight = self.suspensionAlwaysHeader.header.size - diff; if ([header conformsToProtocol:@protocol(FMTeslaSuspensionHeightChangeDelegate)] && [header respondsToSelector:@selector(teslaSuspensionHeaderShouldShowHeight:)]) { id delegate = header; [delegate teslaSuspensionHeaderShouldShowHeight:showHeight]; } } else { } } } } } #pragma mark ------- scrollView delegate - (void)scrollViewDidScroll:(UIScrollView *)scrollView{ if (scrollView == self.scrollView) { if ([self.delegate respondsToSelector:@selector(tesla:scrollViewDidScroll:)]) { [self.delegate tesla:self scrollViewDidScroll:scrollView]; } } } - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{ if (scrollView == self.scrollView) { [self scrollStart]; } } - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{ if (scrollView == self.scrollView) { [self scrollEnd]; } } - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{ if (scrollView == self.scrollView) { if (!decelerate) { [self scrollEnd]; } else { self.userInteractionEnabled = NO; } } } - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView{ if (scrollView == self.scrollView) { [self scrollEnd]; } } @end ================================================ FILE: FMLayoutKit/Classes/FMTeslaSuspensionHeightChangeDelegate.h ================================================ // // FMTeslaSuspensionHeightChangeDelegate.h // FMCollectionLayout // // Created by 周发明 on 2020/5/13. // #import #import NS_ASSUME_NONNULL_BEGIN @protocol FMTeslaSuspensionHeightChangeDelegate - (void)teslaSuspensionHeaderShouldShowHeight:(CGFloat)showHeight; @end NS_ASSUME_NONNULL_END ================================================ FILE: FMLayoutKit/Classes/Sections/FMLayoutAbsoluteSection.h ================================================ // // FMLayoutAbsoluteSection.h // FMCollectionLayout // // Created by 周发明 on 2020/6/9. // #import "FMLayoutDynamicSection.h" NS_ASSUME_NONNULL_BEGIN typedef CGRect(^FMLayoutBaseSectionItemFrameBlock)(id section, NSInteger item); ///支持纵向插横向 @interface FMLayoutAbsoluteSection : FMLayoutDynamicSection @property(nonatomic, copy)FMLayoutBaseSectionItemFrameBlock frameBlock; @end NS_ASSUME_NONNULL_END ================================================ FILE: FMLayoutKit/Classes/Sections/FMLayoutAbsoluteSection.m ================================================ // // FMLayoutAbsoluteSection.m // FMCollectionLayout // // Created by 周发明 on 2020/6/9. // #import "FMLayoutAbsoluteSection.h" #import "FMCollectionLayoutAttributes.h" @interface FMLayoutAbsoluteSection () @property(nonatomic, assign)CGFloat maxSize; @end @implementation FMLayoutAbsoluteSection - (id)copyWithZone:(NSZone *)zone{ FMLayoutAbsoluteSection *section = [super copyWithZone:zone]; section.frameBlock = [self.frameBlock copy]; return section; } - (void)prepareItems{ self.maxSize = self.handleType == FMLayoutHandleTypeOlnyChangeOffset ? [self.columnSizes[@0] floatValue]:0; [super prepareItems]; self.columnSizes[@0] = @(self.maxSize); } - (FMCollectionLayoutAttributes *)getItemAttributesWithIndex:(NSInteger)j{ FMCollectionLayoutAttributes *itemAttr = [FMCollectionLayoutAttributes layoutAttributesForCellWithIndexPath:[NSIndexPath indexPathForItem:j inSection:self.indexPath.section]]; CGRect frame = self.frameBlock?self.frameBlock(self, j): CGRectZero; frame.origin.y += self.firstItemStartY; frame.origin.x += self.firstItemStartX; itemAttr.frame = frame; if (self.direction == FMLayoutDirectionVertical) { if (self.maxSize < frame.origin.y + frame.size.height) { self.maxSize = frame.origin.y + frame.size.height; self.maxSize -= self.firstItemStartY; } } else { if (self.maxSize < frame.origin.x + frame.size.width) { self.maxSize = frame.origin.x + frame.size.width; self.maxSize -= self.firstItemStartX; } } return itemAttr; } - (CGFloat)crossSingleSectionSize{ if (self.direction == FMLayoutDirectionHorizontal) { CGFloat maxSize = 0; for (int j = 0; j < self.itemCount; j++) { CGRect frame = self.frameBlock?self.frameBlock(self, j): CGRectZero; if (maxSize < frame.origin.y + frame.size.height) { maxSize = frame.origin.y + frame.size.height; } } return maxSize + self.sectionInset.top + self.sectionInset.bottom; } else { CGFloat maxSize = 0; for (int j = 0; j < self.itemCount; j++) { CGRect frame = self.frameBlock?self.frameBlock(self, j): CGRectZero; if (maxSize < frame.origin.x + frame.size.width) { maxSize = frame.origin.x + frame.size.width; } } return maxSize + self.sectionInset.left + self.sectionInset.right; } } @end ================================================ FILE: FMLayoutKit/Classes/Sections/FMLayoutBaseSection.h ================================================ // // FMLayoutBaseSection.h // FMLayoutKit // // Created by 周发明 on 2020/3/20. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import #import #import "FMLayoutDebugLog.h" typedef NS_ENUM(NSUInteger, FMLayoutHandleType) { /// 重新计算 重新布局该分组 FMLayoutHandleTypeReLayout, /// 只是分组偏移高度改变 FMLayoutHandleTypeOlnyChangeOffset, /// 追加布局 FMLayoutHandleTypeAppend }; ///布局方向 typedef NS_ENUM(NSUInteger, FMLayoutDirection) { ///垂直布局 FMLayoutDirectionVertical, ///水平布局 FMLayoutDirectionHorizontal }; ///Item布局方向 typedef NS_ENUM(NSUInteger, FMLayoutItemDirection) { ///水平左边开始 垂直上面开始 FMLayoutItemDirectionLeftTop, ///水平右边开始 垂直下面开始 FMLayoutItemDirectionRightBottom }; ///长按移动的方式 typedef NS_ENUM(NSUInteger, FMLayoutLongMoveType) { ///方格布局时 长按哪里 该cell的中心点就会跟着移动 FMLayoutLongMoveItem, ///列表布局时 上下移动 X不动 FMLayoutLongMoveTable, }; NS_ASSUME_NONNULL_BEGIN @class FMLayoutHeader, FMLayoutFooter, FMLayoutBackground, FMCollectionLayoutAttributes; @interface FMLayoutBaseSection : NSObject ///仅当布局生效之后才会有值 @property(nonatomic, weak)UICollectionView *collectionView; ///仅当布局生效之后才会有值 @property(nonatomic, strong)NSIndexPath *indexPath; ///是否需要重新计算 设置为NO 布局会重新计算 @property(nonatomic, assign)FMLayoutDirection direction; @property(nonatomic, assign)BOOL hasHandle; @property(nonatomic, assign)NSInteger handleItemStart;///重新计算哪一个开始 @property(nonatomic, assign)FMLayoutHandleType handleType; @property(nonatomic, assign)CGFloat changeOffset; @property(nonatomic, strong)FMCollectionLayoutAttributes * __nullable bgAttribute; @property(nonatomic, strong)FMCollectionLayoutAttributes * __nullable headerAttribute; @property(nonatomic, strong)FMCollectionLayoutAttributes * __nullable footerAttribute; @property(nonatomic, strong)NSArray *itemsAttribute; /// 分组偏移高度 @property(nonatomic, assign)CGFloat sectionOffset; /// 分组大小 纵向-高度 横向-宽度 @property(nonatomic, assign)CGFloat sectionSize; /// 分组内边距 @property(nonatomic, assign)UIEdgeInsets sectionInset; ///分组头部 @property(nonatomic, strong)FMLayoutHeader * __nullable header; ///分组底部 @property(nonatomic, strong)FMLayoutFooter * __nullable footer; ///分组背景 @property(nonatomic, strong)FMLayoutBackground * __nullable background; ///cell行间距 @property(nonatomic, assign)CGFloat lineSpace; ///cell间距 @property(nonatomic, assign)CGFloat itemSpace; ///cell列数 纵向-列数 横向-行数 @property(nonatomic, assign)NSInteger column; ///每一列的高度缓存 @property(nonatomic, strong)NSMutableDictionary *columnSizes; ///每一个分组的item个数 默认返回itemDatas.count @property(nonatomic, assign)NSInteger itemCount; ///cell数据数组 @property(nonatomic, strong)NSMutableArray *itemDatas; ///是否可以长按移动排序该分组 默认No 需配合FMLayoutView的enableLongPressDrag使用 @property(nonatomic, assign)BOOL canLongPressExchange; ///长按移动的方式 @property(nonatomic, assign)FMLayoutLongMoveType moveType; ///某一个item是否可以移动替换 @property(nonatomic, copy)BOOL(^canLongPressExchangeItem)(id section, NSInteger item); /// 显示隐藏 @property(nonatomic, assign, getter=isHidden)BOOL hidden; ///第一个Item的Y值 横向纵向有区别 @property(nonatomic, assign, readonly)CGFloat firstItemStartY; ///第一个Item的X值 横向纵向有区别 @property(nonatomic, assign, readonly)CGFloat firstItemStartX; ///配置一下Attributes @property(nonatomic, copy)void(^configureCellLayoutAttributes)(id section, UICollectionViewLayoutAttributes *attributes, NSInteger item); ///配置头部的block @property(nonatomic, copy)void(^configureHeaderData)(FMLayoutBaseSection *section, UICollectionReusableView *header); ///配置底部的block @property(nonatomic, copy)void(^configureFooterData)(FMLayoutBaseSection *section, UICollectionReusableView *footer); ///配置背景的block @property(nonatomic, copy)void(^configureBg)(FMLayoutBaseSection *section, UICollectionReusableView *bg); ///配置Cell的block @property(nonatomic, copy)void(^configureCellData)(FMLayoutBaseSection *section, UICollectionViewCell *cell, NSInteger item); ///cell点击事件 @property(nonatomic, copy)void(^clickCellBlock)(FMLayoutBaseSection *section, NSInteger item); + (instancetype)sectionWithSectionInset:(UIEdgeInsets)inset itemSpace:(CGFloat)itemSpace lineSpace:(CGFloat)lineSpace column:(NSInteger)column; ///标记某一个改变 即将刷新该分组的大小 主要用于动态分组 - (void)markChangeAt:(NSInteger)index; - (void)handleLayout; - (BOOL)intersectsRect:(CGRect)rect; - (void)prepareHeader; - (void)prepareFooter; - (void)prepareItems; - (void)prepareBackground; - (NSArray *)showLayoutAttributesInRect:(CGRect)rect; ///即将显示的头部布局 - (UICollectionViewLayoutAttributes *)showHeaderLayout; ///根据index计算出该布局对象 - (FMCollectionLayoutAttributes *)getItemAttributesWithIndex:(NSInteger)index; - (BOOL)prepareLayoutItemsIsOlnyChangeOffset; ///获取最小高度的列 - (NSInteger)getMinHeightColumn; - (CGFloat)getColumnMaxHeight; ///重置所有列的高度缓存 - (void)resetcolumnSizes; ///交叉布局时单一sention的大小 - (CGFloat)crossSingleSectionSize; - (void)exchangeObjectAtIndex:(NSInteger)index toIndex:(NSInteger)toIndex; - (UICollectionViewCell *)dequeueReusableCellForIndexPath:(NSIndexPath *)indexPath; - (UICollectionViewCell *)dequeueReusableCellForIndexPath:(NSIndexPath *)indexPath collectionView:(UICollectionView *)collectionView; - (void)registerCells; - (void)registerCellsWithCollectionView:(UICollectionView *)collectionView; - (void)reload; - (void)reloadItem:(NSInteger)item; @end NS_ASSUME_NONNULL_END ================================================ FILE: FMLayoutKit/Classes/Sections/FMLayoutBaseSection.m ================================================ // // FMLayoutBaseSection.m // FMLayoutKit // // Created by 周发明 on 2020/3/20. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import "FMLayoutBaseSection.h" #import "FMLayoutFooter.h" #import "FMLayoutHeader.h" #import "FMLayoutBackground.h" #import "FMCollectionLayoutAttributes.h" #import "FMKVOArrayObject.h" @interface FMLayoutBaseSection () @property(nonatomic, strong)FMKVOArrayObject *kvoArray; @end @implementation FMLayoutBaseSection - (id)copyWithZone:(NSZone *)zone{ FMLayoutBaseSection *section = [[[self class] allocWithZone:zone] init]; section.hasHandle = NO; section.handleItemStart = 0; section.handleType = FMLayoutHandleTypeReLayout; section.changeOffset = 0; section.sectionInset = self.sectionInset; section.header = [self.header copy]; section.footer = [self.footer copy]; section.background = [self.background copy]; section.column = self.column; section.lineSpace = self.lineSpace; section.itemSpace = self.itemSpace; section.configureCellLayoutAttributes = [self.configureCellLayoutAttributes copy]; section.itemDatas = [self.itemDatas copy]; return section; } - (void)dealloc{ FMLayoutLog([NSString stringWithFormat:@"%@ dealloc", NSStringFromClass([self class])]); [self.kvoArray removeObserver:self forKeyPath:@"targetArray" context:nil]; } - (NSInteger)itemCount{ return self.itemDatas ? self.itemDatas.count : 0; } - (void)setHeader:(FMLayoutHeader *)header{ _header = header; self.hasHandle = NO; } - (void)setFooter:(FMLayoutFooter *)footer{ _footer = footer; self.hasHandle = NO; } - (void)setBackground:(FMLayoutBackground *)background{ _background = background; self.hasHandle = NO; } - (void)setLineSpace:(CGFloat)lineSpace{ _lineSpace = lineSpace; self.hasHandle = NO; } - (void)setItemSpace:(CGFloat)itemSpace{ _itemSpace = itemSpace; self.hasHandle = NO; } - (void)setColumn:(NSInteger)column{ _column = column; self.hasHandle = NO; } - (void)setDirection:(FMLayoutDirection)direction{ if (_direction == direction) { return; } _direction = direction; self.hasHandle = NO; } + (instancetype)sectionWithSectionInset:(UIEdgeInsets)inset itemSpace:(CGFloat)itemSpace lineSpace:(CGFloat)lineSpace column:(NSInteger)column{ FMLayoutBaseSection *section = [[self alloc] init]; section.sectionInset = inset; section.itemSpace = itemSpace; section.lineSpace = lineSpace; section.column = column; [section resetcolumnSizes]; return section; } - (instancetype)init { self = [super init]; if (self) { self.kvoArray = [[FMKVOArrayObject alloc] init]; [self.kvoArray addObserver:self forKeyPath:@"targetArray" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil]; } return self; } - (void)setHandleItemStart:(NSInteger)handleItemStart{ if (handleItemStart < _handleItemStart) { _handleItemStart = handleItemStart; self.handleType = FMLayoutHandleTypeReLayout; } if (self.handleType == FMLayoutHandleTypeReLayout && _handleItemStart == self.itemsAttribute.count) { self.handleType = FMLayoutHandleTypeAppend; } } - (void)setConfigureHeaderData:(void (^)(FMLayoutBaseSection * _Nonnull, UICollectionReusableView * _Nonnull))configureHeaderData{ _configureHeaderData = configureHeaderData; if (self.header && self.header.autoHeight && !self.header.configureDataAutoHeight) { __weak typeof(self) weakSelf = self; [self.header setConfigureDataAutoHeight:^(UICollectionReusableView * _Nonnull view) { !weakSelf.configureHeaderData?:weakSelf.configureHeaderData(weakSelf, view); }]; } } - (void)setConfigureFooterData:(void (^)(FMLayoutBaseSection * _Nonnull, UICollectionReusableView * _Nonnull))configureFooterData{ _configureFooterData = configureFooterData; if (self.footer && self.footer.autoHeight && !self.footer.configureDataAutoHeight) { __weak typeof(self) weakSelf = self; [self.footer setConfigureDataAutoHeight:^(UICollectionReusableView * _Nonnull view) { !weakSelf.configureFooterData?:weakSelf.configureFooterData(weakSelf, view); }]; } } - (NSMutableArray *)itemDatas{ return [self.kvoArray mutableArrayValueForKey:@"targetArray"]; } - (void)setItemDatas:(NSMutableArray *)itemDatas{ if (self.kvoArray.targetArray == itemDatas) { return; } self.hasHandle = NO; self.handleType = FMLayoutHandleTypeReLayout; if (self.kvoArray.targetArray) { [self.kvoArray removeObserver:self forKeyPath:@"targetArray" context:nil]; } if (![itemDatas isKindOfClass:[NSMutableArray class]]) { self.kvoArray.targetArray = [itemDatas mutableCopy]; [self.kvoArray addObserver:self forKeyPath:@"targetArray" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil]; } else { self.kvoArray.targetArray = itemDatas; [self.kvoArray addObserver:self forKeyPath:@"targetArray" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil]; } } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{ if ([keyPath isEqualToString:@"targetArray"]) { self.hasHandle = NO; // NSInteger kind = [change[@"kind"] integerValue]; NSIndexSet *set = change[@"indexes"]; self.handleItemStart = set.firstIndex; // if (kind == 2) { //增加 需判断是插入 还是 // // } // /* // NSKeyValueChangeSetting = 1, // NSKeyValueChangeInsertion = 2, //插入 // NSKeyValueChangeRemoval = 3, // 移除 // NSKeyValueChangeReplacement = 4, // 替换 // */ // } FMLayoutLog([NSString stringWithFormat:@"base section itemDatas changeed %@", change]); } - (CGFloat)firstItemStartY{ if (self.direction == FMLayoutDirectionVertical) { return self.sectionOffset + self.sectionInset.top + self.header.inset.top + self.header.size + self.header.inset.bottom + self.header.lastMargin; } else { return self.sectionInset.top; } } - (CGFloat)firstItemStartX{ if (self.direction == FMLayoutDirectionVertical) { return self.sectionInset.left; } else { return self.sectionOffset + self.sectionInset.left + self.header.inset.left + self.header.size + self.header.inset.right + self.header.lastMargin; } } - (void)markChangeAt:(NSInteger)index{ self.hasHandle = NO; self.handleItemStart = index; } - (void)handleLayout{ if (self.header) { [self prepareHeader]; } [self prepareItems]; if (self.footer) { [self prepareFooter]; } if (self.direction == FMLayoutDirectionVertical) { self.sectionSize = self.sectionInset.top + self.header.inset.top +self.header.size + self.header.inset.bottom + self.header.lastMargin + [self getColumnMaxHeight] + self.footer.inset.top + self.footer.size + self.footer.topMargin + self.footer.inset.bottom + self.sectionInset.bottom; } else { self.sectionSize = self.sectionInset.left + self.header.inset.left +self.header.size + self.header.inset.right + self.header.lastMargin + [self getColumnMaxHeight] + self.footer.inset.left + self.footer.size + self.footer.topMargin + self.footer.inset.right + self.sectionInset.right; } [self prepareBackground]; } - (BOOL)intersectsRect:(CGRect)rect{ if (self.direction == FMLayoutDirectionVertical) { return CGRectIntersectsRect(CGRectMake(0, self.sectionOffset, self.collectionView.frame.size.width, self.sectionSize), rect); } else { return CGRectIntersectsRect(CGRectMake(self.sectionOffset, 0, self.sectionSize, self.collectionView.frame.size.height), rect); } } - (void)prepareHeader{ if (self.handleType == FMLayoutHandleTypeOlnyChangeOffset && self.headerAttribute) { [self.headerAttribute updateHeaderAttributesWithSection:self]; return; } self.headerAttribute = [FMCollectionLayoutAttributes headerAttributesWithSection:self]; } - (void)prepareFooter{ if (self.handleType == FMLayoutHandleTypeOlnyChangeOffset && self.footerAttribute) { [self.footerAttribute updateFooterAttributesWithSection:self]; return; } self.footerAttribute = [FMCollectionLayoutAttributes footerAttributesWithSection:self]; } - (void)prepareItems{ if ([self prepareLayoutItemsIsOlnyChangeOffset]) return; [self resetcolumnSizes]; NSInteger items = MIN([self.collectionView numberOfItemsInSection:self.indexPath.section], self.itemCount); NSMutableArray *attrs = [NSMutableArray array]; int first = 0; if (self.handleType == FMLayoutHandleTypeAppend) { attrs = [self.itemsAttribute?:@[] mutableCopy]; first = (int)self.handleItemStart; } for (int j = first; j < items; j++) { [attrs addObject:[self getItemAttributesWithIndex:j]]; } self.itemsAttribute = [attrs copy]; } - (void)prepareBackground{ if (self.handleType == FMLayoutHandleTypeOlnyChangeOffset && self.bgAttribute) { [self.bgAttribute updateBgAttributesWithSection:self]; return; } if (self.background) { self.bgAttribute = [FMCollectionLayoutAttributes bgAttributesWithSection:self]; } } - (NSArray *)showLayoutAttributesInRect:(CGRect)rect{ if (self.isHidden) { return @[]; } NSMutableArray *attrs = [NSMutableArray array]; if ([self intersectsRect:rect]) { if (self.headerAttribute) { UICollectionViewLayoutAttributes *showHeaderAttr = [self showHeaderLayout]; if (CGRectIntersectsRect(rect, showHeaderAttr.frame)) { [attrs addObject:showHeaderAttr]; } } if (self.footerAttribute) { if (CGRectIntersectsRect(rect, self.footerAttribute.frame)) { [attrs addObject:self.footerAttribute]; } } if (self.bgAttribute) { if (CGRectIntersectsRect(rect, self.bgAttribute.frame)) { [attrs addObject:self.bgAttribute]; } } for (UICollectionViewLayoutAttributes *item in self.itemsAttribute) { if (CGRectIntersectsRect(rect, item.frame)) { [attrs addObject:item]; } } } else { if (self.header.type == FMLayoutHeaderTypeSuspensionAlways) { if (self.headerAttribute) { UICollectionViewLayoutAttributes *showHeaderAttr = [self showHeaderLayout]; if (CGRectIntersectsRect(rect, showHeaderAttr.frame)) { [attrs addObject:showHeaderAttr]; } } } } return attrs; } ///头部悬停布局计算 - (UICollectionViewLayoutAttributes *)showHeaderLayout{ if (self.header.type == FMLayoutHeaderTypeFixed) { return self.headerAttribute; } UICollectionViewLayoutAttributes *show = [FMCollectionLayoutAttributes suspensionShowHeaderAttributes:self]; if (show) { return show; } return self.headerAttribute; } /// 判断是否只改变偏移量 - (BOOL)prepareLayoutItemsIsOlnyChangeOffset{ if (self.handleType == FMLayoutHandleTypeOlnyChangeOffset) { [self.itemsAttribute enumerateObjectsUsingBlock:^(FMCollectionLayoutAttributes * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { obj.indexPath = [NSIndexPath indexPathForItem:idx inSection:self.indexPath.section]; obj.direction = self.direction; [obj _onlyUpdateOffsetWith:self]; }]; return YES; } else { return NO; } } ///获取最小高度的列 - (NSInteger)getMinHeightColumn{ if (self.columnSizes.allKeys.count == 0) { return 0; } NSInteger column = 0; CGFloat minHeight = [self.columnSizes[@0] floatValue]; for (int i = 1; i maxHeight) { maxHeight = height; } } return maxHeight; } ///重置所有列的高度缓存 - (void)resetcolumnSizes{ self.columnSizes = [NSMutableDictionary dictionary]; for (int i = 0; i < self.column; i++) { self.columnSizes[@(i)] = @0; } } - (CGFloat)crossSingleSectionSize{ return 0; } - (void)exchangeObjectAtIndex:(NSInteger)index toIndex:(NSInteger)toIndex{ id obj = self.itemDatas[index]; [self.itemDatas removeObjectAtIndex:index]; [self.itemDatas insertObject:obj atIndex:toIndex]; } - (UICollectionViewCell *)dequeueReusableCellForIndexPath:(NSIndexPath *)indexPath{ return [self dequeueReusableCellForIndexPath:indexPath collectionView:self.collectionView]; } - (UICollectionViewCell *)dequeueReusableCellForIndexPath:(NSIndexPath *)indexPath collectionView:(UICollectionView *)collectionView{ @throw [NSException exceptionWithName:@"child class must implementation this method" reason:@"FMLayoutBaseSection" userInfo:nil]; } - (void)registerCells{ [self registerCellsWithCollectionView:self.collectionView]; } - (void)registerCellsWithCollectionView:(UICollectionView *)collectionView{ } - (FMCollectionLayoutAttributes *)getItemAttributesWithIndex:(NSInteger)j{ @throw [NSException exceptionWithName:@"child class must implementation this method" reason:@"FMLayoutBaseSection" userInfo:nil]; } - (void)reload{ [self.collectionView reloadSections:[NSIndexSet indexSetWithIndex:self.indexPath.section]]; } - (void)reloadItem:(NSInteger)item{ [self.collectionView reloadItemsAtIndexPaths:@[[NSIndexPath indexPathForItem:item inSection:self.indexPath.section]]]; } @end ================================================ FILE: FMLayoutKit/Classes/Sections/FMLayoutCombineSection.h ================================================ // // FMLayoutCombineSection.h // FMLayoutKit // // Created by 郑桂华 on 2020/7/12. // #import "FMLayoutBaseSection.h" NS_ASSUME_NONNULL_BEGIN ///可以将不同Cell, 不同的布局方式, 放到同一个分组去合并,只合并cell, 如果子分组有头部和底部讲被忽略,合并分组的头部与底部不影响配置, cell的点击事件已经在init方法中配置block分发到子分组上 合并分组不支持拖拽排序 想要支持 可以继承自该类重写canLongPressExchange的get方法 并实现- (void)exchangeObjectAtIndex:(NSInteger)index toIndex:(NSInteger)toIndex; @interface FMLayoutCombineSection : FMLayoutBaseSection @property(nonatomic, readonly)NSArray *subSections; + (instancetype)combineSections:(NSArray *)sections; - (void)appendSection:(FMLayoutBaseSection *)section; - (void)insetSection:(FMLayoutBaseSection *)section atIndex:(NSInteger)index; @end NS_ASSUME_NONNULL_END ================================================ FILE: FMLayoutKit/Classes/Sections/FMLayoutCombineSection.m ================================================ // // FMLayoutCombineSection.m // FMLayoutKit // // Created by 郑桂华 on 2020/7/12. // #import "FMLayoutCombineSection.h" #import "FMCollectionLayoutAttributes.h" #import "FMLayoutHeader.h" @interface __FMCombineModel : NSObject @property(nonatomic, assign)NSInteger start; @property(nonatomic, strong)FMLayoutBaseSection *section; @end @implementation __FMCombineModel @end @interface FMLayoutCombineSection () @property(nonatomic, strong)NSArray<__FMCombineModel *> *sections; @end @implementation FMLayoutCombineSection - (BOOL)canLongPressExchange{ return NO; } - (NSArray *)subSections{ return [self.sections valueForKey:@"section"]; } - (id)copyWithZone:(NSZone *)zone{ FMLayoutCombineSection *section = [super copyWithZone:zone]; section.sections = [self.sections copy]; return section; } - (NSInteger)itemCount{ NSInteger count = 0; for (__FMCombineModel *combine in self.sections) { count += combine.section.itemCount; } return count; } + (instancetype)combineSections:(NSArray *)sections{ FMLayoutCombineSection *section = [[self alloc] init]; [section resetSecionsWithSections:sections]; return section; } - (void)appendSection:(FMLayoutBaseSection *)section{ NSMutableArray *sections = [NSMutableArray arrayWithArray:self.subSections]; [sections addObject:section]; [self resetSecionsWithSections:sections]; } - (void)insetSection:(FMLayoutBaseSection *)section atIndex:(NSInteger)index{ NSMutableArray *sections = [NSMutableArray arrayWithArray:self.subSections]; [sections insertObject:section atIndex:index]; [self resetSecionsWithSections:sections]; } - (void)resetSecionsWithSections:(NSArray *)sections{ NSMutableArray *arrM = [NSMutableArray array]; for (int i = 0; i < sections.count; i++) { __FMCombineModel *com = [[__FMCombineModel alloc] init]; com.section = sections[i]; [arrM addObject:com]; } self.sections = [arrM copy]; self.hasHandle = NO; } - (instancetype)init { self = [super init]; if (self) { self.column = 1; __weak typeof(self) weakSelf = self; [self setClickCellBlock:^(FMLayoutBaseSection * _Nonnull section, NSInteger item) { for (__FMCombineModel *com in weakSelf.sections) { if (item < com.start + com.section.itemCount) { if (com.section.clickCellBlock) { com.section.clickCellBlock(com.section, item - com.start); } return; } } }]; [self setConfigureCellData:^(FMLayoutBaseSection * _Nonnull section, UICollectionViewCell * _Nonnull cell, NSInteger item) { for (__FMCombineModel *com in weakSelf.sections) { if (item < com.start + com.section.itemCount) { if (com.section.configureCellData) { com.section.configureCellData(com.section, cell,item - com.start); } return; } } }]; } return self; } - (void)handleLayout{ NSInteger start = 0; for (__FMCombineModel *com in self.sections) { com.start = start; start += com.section.itemCount; } [super handleLayout]; } - (void)prepareItems{ [self resetcolumnSizes]; CGFloat startOffset = self.direction == FMLayoutDirectionVertical ? self.firstItemStartY : self.firstItemStartX; CGFloat offset = startOffset; NSInteger start = 0; NSArray *sections = self.subSections; for (int i = 0; i < sections.count; i++) { FMLayoutBaseSection *section = sections[i]; section.header = nil; section.footer = nil; section.background = nil; section.direction = self.direction; section.collectionView = self.collectionView; section.sectionOffset = offset; section.handleType = self.handleType; section.changeOffset = self.changeOffset; section.indexPath = self.indexPath; [section handleLayout]; offset += section.sectionSize; [section.itemsAttribute enumerateObjectsUsingBlock:^(FMCollectionLayoutAttributes * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { obj.indexPath = [NSIndexPath indexPathForItem:idx + start inSection:self.indexPath.section]; }]; section.changeOffset = 0; section.handleType = FMLayoutHandleTypeReLayout; section.hasHandle = YES; start += section.itemCount; } self.columnSizes[@0] = @(offset - startOffset); } - (NSArray *)showLayoutAttributesInRect:(CGRect)rect{ NSMutableArray *attrs = [NSMutableArray array]; if ([self intersectsRect:rect]) { if (self.headerAttribute) { UICollectionViewLayoutAttributes *showHeaderAttr = [self showHeaderLayout]; if (CGRectIntersectsRect(rect, showHeaderAttr.frame)) { [attrs addObject:showHeaderAttr]; } } if (self.footerAttribute) { if (CGRectIntersectsRect(rect, self.footerAttribute.frame)) { [attrs addObject:self.footerAttribute]; } } if (self.bgAttribute) { if (CGRectIntersectsRect(rect, self.bgAttribute.frame)) { [attrs addObject:self.bgAttribute]; } } NSArray *sections = self.subSections; for (FMLayoutBaseSection *section in sections) { NSArray *subAttrs = [section showLayoutAttributesInRect:rect]; [attrs addObjectsFromArray:subAttrs]; } } else { if (self.header.type == FMLayoutHeaderTypeSuspensionAlways) { if (self.headerAttribute) { UICollectionViewLayoutAttributes *showHeaderAttr = [self showHeaderLayout]; if (CGRectIntersectsRect(rect, showHeaderAttr.frame)) { [attrs addObject:showHeaderAttr]; } } } } return attrs; } - (UICollectionViewCell *)dequeueReusableCellForIndexPath:(NSIndexPath *)indexPath collectionView:(UICollectionView *)collectionView{ for (__FMCombineModel *com in self.sections) { if (indexPath.item < com.start + com.section.itemCount) { return [com.section dequeueReusableCellForIndexPath:indexPath collectionView:collectionView]; } } @throw [NSException exceptionWithName:@"FMLayoutCombineSection instance dequeueReusableCellForIndexPath" reason:@"FMLayoutCombineSection" userInfo:nil]; } - (void)registerCellsWithCollectionView:(UICollectionView *)collectionView{ NSArray *sections = self.subSections; for (FMLayoutBaseSection *section in sections) { [section registerCellsWithCollectionView:collectionView]; } } - (CGFloat)crossSingleSectionSize{ CGFloat maxSize = self.direction == FMLayoutDirectionVertical ? self.firstItemStartY : self.firstItemStartX; NSArray *sections = self.subSections; for (FMLayoutBaseSection *section in sections) { CGFloat sectionSize = [section crossSingleSectionSize]; if (maxSize < sectionSize) { maxSize = sectionSize; } } return maxSize; } @end ================================================ FILE: FMLayoutKit/Classes/Sections/FMLayoutDynamicSection.h ================================================ // // FMLayoutDynamicSection.h // FMLayoutKit // // Created by 周发明 on 2020/4/1. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import "FMLayoutBaseSection.h" #import "FMLayoutElement.h" NS_ASSUME_NONNULL_BEGIN ///返回cell大小的block 横向-返回宽度 纵向-返回高度 typedef CGFloat(^FMLayoutItemOtherBlock)(id section, NSInteger item); typedef CGFloat(^FMLayoutAutoHeightLaterBlock)(id section, NSInteger item, CGFloat autoHeight); ///动态 可以注册多种cell 宽度固定 高度可以自适应 但需要用block填充数据 需要设置deqCellReturnReuseId该block值以获取cell 高度亦可以通过手动计算heightBlock返回 手动计算优先级要高 @interface FMLayoutDynamicSection : FMLayoutBaseSection /// yes时 布局耗时比较长 是否自动计算高度 需设置configurationCell方法填充数据 仅支持纵向布局时使用 @property(nonatomic, assign)BOOL autoHeightFixedWidth; @property(nonatomic, copy)FMLayoutAutoHeightLaterBlock autoHeightLaterHander; ///cell固定一个方向的大小 纵向-宽度 横向-高度 @property(nonatomic, assign)CGFloat cellFixedSize; ///需要注册的cell元素 @property(nonatomic, strong)NSArray *cellElements; ///固定单一分组 当固定单一分组时 可以不用手动配置deqCellReturnReuseId @property(nonatomic, strong)FMLayoutElement *cellElement; ///获取cell的复用FMLayoutElement @property(nonatomic, copy)FMLayoutElement *(^deqCellReturnElement)(FMLayoutDynamicSection *section, NSInteger item); ///填充数据 仅当autoHeightFixedWidth为Yes时有用 @property(nonatomic, copy)void(^configurationCell)(FMLayoutDynamicSection *section, UICollectionViewCell *cell, NSInteger item); ///block返回手动计算的高度 优先级比自动的高 @property(nonatomic, copy)FMLayoutItemOtherBlock otherBlock; - (CGFloat)autoHeightVerticalWithWidth:(CGFloat)fixedWidth index:(NSInteger)index; @end NS_ASSUME_NONNULL_END ================================================ FILE: FMLayoutKit/Classes/Sections/FMLayoutDynamicSection.m ================================================ // // FMLayoutDynamicSection.m // FMLayoutKit // // Created by 周发明 on 2020/4/1. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import "FMLayoutDynamicSection.h" #import "FMCollectionLayoutAttributes.h" #import "FMLayoutHeader.h" #import "FMLayoutFooter.h" @interface FMLayoutDynamicSection () @property(nonatomic, strong)NSMapTable *autoHeightCells; @end @implementation FMLayoutDynamicSection - (NSMapTable *)autoHeightCells{ if (_autoHeightCells == nil) { _autoHeightCells = [NSMapTable mapTableWithKeyOptions:NSPointerFunctionsWeakMemory valueOptions:NSPointerFunctionsStrongMemory]; } return _autoHeightCells; } - (CGFloat)autoHeightVerticalWithWidth:(CGFloat)fixedWidth index:(NSInteger)index{ CGFloat itemOther = 0; if (self.direction == FMLayoutDirectionHorizontal) { @throw [NSException exceptionWithName:@"autoHeightFixedWidth must for FMLayoutDirectionVertical" reason:@"FMLayoutDynamicSection" userInfo:nil]; } if (self.deqCellReturnElement) { FMLayoutElement *element = self.deqCellReturnElement(self, index); UICollectionViewCell *cell = [self.autoHeightCells objectForKey:element.viewClass]; if (cell == nil) { if (element.isNib) { cell = [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass(element.viewClass) owner:nil options:nil] lastObject]; } else { cell = [[element.viewClass alloc] init]; } [self.autoHeightCells setObject:cell forKey:element.viewClass]; } if (self.configurationCell) { self.configurationCell(self ,cell, index); } itemOther = [cell systemLayoutSizeFittingSize:CGSizeMake(fixedWidth, MAXFLOAT)].height; } if (self.autoHeightLaterHander) { itemOther = self.autoHeightLaterHander(self, index, itemOther); } return itemOther; } - (id)copyWithZone:(NSZone *)zone{ FMLayoutDynamicSection *section = [super copyWithZone:zone]; section.autoHeightFixedWidth = self.autoHeightFixedWidth; section.cellFixedSize = self.cellFixedSize; NSMutableArray *arrM = [NSMutableArray array]; for (FMLayoutElement *element in self.cellElements) { [arrM addObject:[element copy]]; } section.cellElements = arrM; section.deqCellReturnElement = [self.deqCellReturnElement copy]; section.autoHeightLaterHander = [self.autoHeightLaterHander copy]; section.configurationCell = [self.configurationCell copy]; section.otherBlock = [self.otherBlock copy]; return section; } - (void)setCellFixedSize:(CGFloat)cellFixedSize{ _cellFixedSize = cellFixedSize; self.hasHandle = NO; } - (void)setCellElements:(NSArray *)cellElements{ _cellElements = cellElements; self.hasHandle = NO; } - (void)setCellElement:(FMLayoutElement *)cellElement{ _cellElement = cellElement; self.cellElements = @[cellElement]; __weak typeof(self) weakSelf = self; [self setDeqCellReturnElement:^FMLayoutElement * _Nonnull(FMLayoutDynamicSection * _Nonnull section, NSInteger index) { return weakSelf.cellElement; }]; } - (void)setConfigureCellData:(void (^)(FMLayoutBaseSection * _Nonnull, UICollectionViewCell * _Nonnull, NSInteger))configureCellData{ [super setConfigureCellData:configureCellData]; if (!self.configurationCell && self.autoHeightFixedWidth) { self.configurationCell = configureCellData; } } - (FMCollectionLayoutAttributes *)getItemAttributesWithIndex:(NSInteger)j{ NSIndexPath *indexPath = [NSIndexPath indexPathForItem:j inSection:self.indexPath.section]; FMCollectionLayoutAttributes *itemAttr = [FMCollectionLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; CGFloat itemFixed = self.cellFixedSize; CGFloat itemOther = 0; if (self.autoHeightFixedWidth) { itemOther = [self autoHeightVerticalWithWidth:itemFixed index:j]; } else { itemOther = !self.otherBlock?0:self.otherBlock(self, j); } if (self.direction == FMLayoutDirectionVertical) { CGSize itemSize = CGSizeMake(itemFixed, itemOther); NSInteger column = [self getMinHeightColumn]; CGFloat x = self.sectionInset.left + column * (self.itemSpace + itemSize.width); CGFloat height = [self.columnSizes[@(column)] floatValue]; CGFloat y = self.firstItemStartY + (height > 0 ? (height + self.lineSpace) : height); itemAttr.frame = CGRectMake(x, y, itemSize.width, itemSize.height); self.columnSizes[@(column)] = @(height + itemSize.height + (height > 0 ? self.lineSpace : 0)); } else { CGSize itemSize = CGSizeMake(itemOther, itemFixed); NSInteger column = [self getMinHeightColumn]; CGFloat minWidth = [self.columnSizes[@(column)] floatValue]; CGFloat x = self.firstItemStartX + (minWidth > 0 ? (minWidth + self.itemSpace) : minWidth); CGFloat y = self.firstItemStartY + column * (self.lineSpace + itemSize.height); itemAttr.frame = CGRectMake(x, y, itemSize.width, itemSize.height); self.columnSizes[@(column)] = @(minWidth + itemSize.width + (minWidth > 0 ? self.itemSpace : 0)); } if (self.configureCellLayoutAttributes) { self.configureCellLayoutAttributes(self, itemAttr, j); } return itemAttr; } - (UICollectionViewCell *)dequeueReusableCellForIndexPath:(NSIndexPath *)indexPath collectionView:(nonnull UICollectionView *)collectionView{ if (!self.deqCellReturnElement) { @throw [NSException exceptionWithName:@"dynamic section must have to set deqCellReturnElement value" reason:@"FMLayoutDynamicSection" userInfo:nil]; } return [collectionView dequeueReusableCellWithReuseIdentifier:self.deqCellReturnElement(self, indexPath.item).reuseIdentifier forIndexPath:indexPath]; } - (void)registerCellsWithCollectionView:(UICollectionView *)collectionView{ for (FMLayoutElement *element in self.cellElements) { [element registerElementWithCollection:collectionView]; } } - (CGFloat)crossSingleSectionSize{ if (self.itemCount == 0 || self.column == 0) { return 0; } CGFloat maxSize = 0; if (self.itemCount > self.column) { maxSize = self.column * self.cellFixedSize + (self.column - 1) * self.lineSpace; } else { maxSize = self.itemCount * self.cellFixedSize + (self.itemCount - 1) * self.lineSpace; } if (self.direction == FMLayoutDirectionHorizontal) { maxSize += self.sectionInset.top + self.sectionInset.bottom; } else { maxSize += self.sectionInset.left + self.sectionInset.right; } return maxSize; } @end ================================================ FILE: FMLayoutKit/Classes/Sections/FMLayoutFillSection.h ================================================ // // FMLayoutFillSection.h // FMCollectionLayout // // Created by 周发明 on 2020/4/11. // #import "FMLayoutDynamicSection.h" NS_ASSUME_NONNULL_BEGIN ///返回cell大小的block typedef CGSize(^FMLayoutItemSizeBlock)(id section, NSInteger item); ///支持纵向插横向 只可以上对齐以及左对齐 @interface FMLayoutFillSection : FMLayoutDynamicSection @property(nonatomic, copy)FMLayoutItemSizeBlock sizeBlock; @end NS_ASSUME_NONNULL_END ================================================ FILE: FMLayoutKit/Classes/Sections/FMLayoutFillSection.m ================================================ // // FMLayoutFillSection.m // FMCollectionLayout // // Created by 周发明 on 2020/4/11. // #import "FMLayoutFillSection.h" #import "FMCollectionLayoutAttributes.h" #import "FMLayoutHeader.h" @interface FMLayoutFillSection () @property(nonatomic, assign)CGFloat maxSize; @end @implementation FMLayoutFillSection - (id)copyWithZone:(NSZone *)zone{ FMLayoutFillSection *section = [super copyWithZone:zone]; section.sizeBlock = [self.sizeBlock copy]; return section; } - (void)prepareItems{ if ([self prepareLayoutItemsIsOlnyChangeOffset]) return; [self resetcolumnSizes]; NSInteger items = MIN([self.collectionView numberOfItemsInSection:self.indexPath.section], self.itemCount); NSMutableArray *attrs = [NSMutableArray array]; int first = 0; if (self.handleType == FMLayoutHandleTypeAppend) { attrs = [self.itemsAttribute?:@[] mutableCopy]; first = (int)self.handleItemStart; } CGFloat maxHeight = 0; for (int j = first; j < items; j++) { NSIndexPath *indexPath = [NSIndexPath indexPathForItem:j inSection:self.indexPath.section]; FMCollectionLayoutAttributes *itemAttr = [FMCollectionLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; CGSize itemSize = !self.sizeBlock?CGSizeZero:self.sizeBlock(self, j); if (attrs.count == 0) { CGFloat x = self.firstItemStartX; CGFloat y = self.firstItemStartY; itemAttr.frame = CGRectMake(x, y, itemSize.width, itemSize.height); maxHeight = itemSize.height; } else { if (self.direction == FMLayoutDirectionVertical) { CGFloat lastX = 0; CGFloat lastY = 0; /// 放在右侧寻找最适合 for (FMCollectionLayoutAttributes *attr in attrs) { CGFloat thisX = CGRectGetMaxX(attr.frame) + self.itemSpace; CGFloat thisY = CGRectGetMinY(attr.frame); if (thisX + itemSize.width > self.collectionView.frame.size.width-self.sectionInset.right) { continue; } else { CGRect frame = CGRectMake(thisX, thisY, itemSize.width, itemSize.height); if (![self intersectsRectInExsitAttributes:attrs frame:frame verticle:NO]) {///没有交集 可以是放 if (lastX == 0 && lastY == 0) { ///如果都没有设置 则就设置为最合适的 lastY = thisY; lastX = thisX; } else { if (thisY <= lastY) { lastY = thisY; lastX = thisX; } else { if (thisX < lastX) { lastX = thisX; lastY = thisY; } } } } } } /// 放在下侧寻找最适合 for (FMCollectionLayoutAttributes *attr in attrs) { CGFloat thisX = CGRectGetMinX(attr.frame); CGFloat thisY = CGRectGetMaxY(attr.frame) + self.lineSpace; if (thisX + itemSize.width > self.collectionView.frame.size.width-self.sectionInset.right) { continue; } else { CGRect frame = CGRectMake(thisX, thisY, itemSize.width, itemSize.height); if (![self intersectsRectInExsitAttributes:attrs frame:frame verticle:YES]) {///没有交集 可以是放 if (lastX == 0 && lastY == 0) { lastY = thisY; lastX = thisX; } else { if (lastX > 0 || lastY > 0) { ///找到合适位置 if (thisY < lastY) { /// 如果找到的合适的y值小于之前的找到的y值 则设置为现在 lastY = thisY; lastX = thisX; } else if([self roundFloat:thisY] == [self roundFloat:lastY]) {///会有精度比较问题 if (thisX < lastX) { lastY = thisY; lastX = thisX; } } } } } } } if (lastY == 0 && lastX == 0) { lastY = self.firstItemStartY + maxHeight + self.lineSpace; lastX = self.firstItemStartX; } CGRect frame = CGRectMake(lastX, lastY, itemSize.width, itemSize.height); CGFloat height = CGRectGetMaxY(frame) - self.sectionOffset - self.sectionInset.top - self.header.inset.top - self.header.size - - self.header.inset.bottom - self.header.lastMargin; if (height > maxHeight) { maxHeight = height; } itemAttr.frame = frame; } else { CGFloat lastX = 0; CGFloat lastY = 0; /// 放在下侧寻找最适合 for (FMCollectionLayoutAttributes *attr in attrs) { CGFloat thisX = CGRectGetMinX(attr.frame); CGFloat thisY = CGRectGetMaxY(attr.frame) + self.lineSpace; if (thisY + itemSize.height > self.collectionView.frame.size.height-self.sectionInset.bottom) { continue; } else { CGRect frame = CGRectMake(thisX, thisY, itemSize.width, itemSize.height); if (![self intersectsRectInExsitAttributes:attrs frame:frame verticle:YES]) {///没有交集 可以是放 if (lastX == 0 && lastY == 0) { lastY = thisY; lastX = thisX; } else { if (thisX < lastX) { /// 如果找到的合适的x值小于之前的找到的x值 则设置为现在 lastX = thisX; lastY = thisY; } else if([self roundFloat:thisY] == [self roundFloat:lastY]) {///会有精度比较问题 if (thisX < lastX) { lastY = thisY; lastX = thisX; } } } } } } /// 放在右侧寻找最适合 for (FMCollectionLayoutAttributes *attr in attrs) { CGFloat thisX = CGRectGetMaxX(attr.frame) + self.itemSpace; CGFloat thisY = CGRectGetMinY(attr.frame); if (thisY + itemSize.height > self.collectionView.frame.size.height-self.sectionInset.bottom) { continue; } else { CGRect frame = CGRectMake(thisX, thisY, itemSize.width, itemSize.height); if (![self intersectsRectInExsitAttributes:attrs frame:frame verticle:YES]) {///没有交集 可以是放 if (lastX == 0 && lastY == 0) { ///如果都没有设置 则就设置为最合适的 lastY = thisY; lastX = thisX; } else { if (thisX < lastX) { lastY = thisY; lastX = thisX; } } } } } if (lastY == 0 && lastX == 0) { lastY = self.firstItemStartY; lastX = self.firstItemStartX + maxHeight + self.itemSpace; } CGRect frame = CGRectMake(lastX, lastY, itemSize.width, itemSize.height); CGFloat height = CGRectGetMaxX(frame) - self.sectionOffset - self.sectionInset.left - self.header.inset.left - self.header.size - self.header.inset.right - self.header.lastMargin; if (height > maxHeight) { maxHeight = height; } itemAttr.frame = frame; } } [attrs addObject:itemAttr]; if (self.configureCellLayoutAttributes) { self.configureCellLayoutAttributes(self, itemAttr, j); } } self.columnSizes[@(0)] = @(maxHeight); self.itemsAttribute = [attrs copy]; } - (BOOL)intersectsRectInExsitAttributes:(NSArray *)attributes frame:(CGRect)frame verticle:(BOOL)verticle{ for (FMCollectionLayoutAttributes *attr in attributes) { CGRect attrFrame = attr.frame; CGRect itemFrame = frame; if (!verticle) { attrFrame.size.height += self.lineSpace; itemFrame.size.width += self.itemSpace; } else { attrFrame.size.width += self.itemSpace; itemFrame.size.height += self.lineSpace; } if (CGRectIntersectsRect(attrFrame, itemFrame)) { return YES; } } return NO; } -(CGFloat)roundFloat:(CGFloat)value{ return roundf(value*100)/100; } @end ================================================ FILE: FMLayoutKit/Classes/Sections/FMLayoutFixedSection.h ================================================ // // FMLayoutFixedSection.h // FMLayoutKit // // Created by 周发明 on 2020/4/1. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import "FMLayoutBaseSection.h" #import "FMLayoutElement.h" NS_ASSUME_NONNULL_BEGIN ///固定cell的大小 单一一种cell样式 支持同样cell是否可以横向滚动 内嵌collectionView 支持纵向插横向 @interface FMLayoutFixedSection : FMLayoutBaseSection @property(nonatomic, assign)CGSize itemSize;///分组cell大小 @property(nonatomic, strong)FMLayoutElement *cellElement;///固定分组 @end NS_ASSUME_NONNULL_END ================================================ FILE: FMLayoutKit/Classes/Sections/FMLayoutFixedSection.m ================================================ // // FMLayoutFixedSection.m // FMLayoutKit // // Created by 周发明 on 2020/4/1. // Copyright © 2020 ZhouFaMing. All rights reserved. // #import "FMLayoutFixedSection.h" #import "FMCollectionLayoutAttributes.h" #import "FMLayoutHeader.h" #import "FMLayoutFooter.h" @implementation FMLayoutFixedSection - (id)copyWithZone:(NSZone *)zone{ FMLayoutFixedSection *section = [super copyWithZone:zone]; section.itemSize = self.itemSize; section.cellElement = [self.cellElement copy]; return section; } - (void)setItemSize:(CGSize)itemSize{ _itemSize = itemSize; self.hasHandle = NO; } - (void)setCellElement:(FMLayoutElement *)cellElement{ _cellElement = cellElement; self.hasHandle = NO; } - (FMCollectionLayoutAttributes *)getItemAttributesWithIndex:(NSInteger)j{ FMCollectionLayoutAttributes *itemAttr = [FMCollectionLayoutAttributes layoutAttributesForCellWithIndexPath:[NSIndexPath indexPathForItem:j inSection:self.indexPath.section]]; CGSize itemSize = self.itemSize; NSInteger column = [self getMinHeightColumn]; if (self.direction == FMLayoutDirectionVertical) { CGFloat x = self.firstItemStartX + column * (self.itemSpace + itemSize.width); CGFloat height = [self.columnSizes[@(column)] floatValue]; CGFloat y = self.firstItemStartY + (height > 0 ? (height + self.lineSpace) : height); itemAttr.frame = CGRectMake(x, y, itemSize.width, itemSize.height); self.columnSizes[@(column)] = @(height + itemSize.height + (height > 0 ? self.lineSpace : 0)); } else { CGFloat height = [self.columnSizes[@(column)] floatValue]; CGFloat x = self.firstItemStartX + (height > 0 ? (height + self.itemSpace) : height); CGFloat y = self.firstItemStartY + column * (self.lineSpace + itemSize.height); itemAttr.frame = CGRectMake(x, y, itemSize.width, itemSize.height); self.columnSizes[@(column)] = @(height + itemSize.width + (height > 0 ? self.itemSpace : 0)); } if (self.configureCellLayoutAttributes) { self.configureCellLayoutAttributes(self, itemAttr, j); } return itemAttr; } - (UICollectionViewCell *)dequeueReusableCellForIndexPath:(NSIndexPath *)indexPath collectionView:(nonnull UICollectionView *)collectionView{ return [collectionView dequeueReusableCellWithReuseIdentifier:self.cellElement.reuseIdentifier forIndexPath:indexPath]; } - (void)registerCellsWithCollectionView:(UICollectionView *)collectionView{ [self.cellElement registerElementWithCollection:collectionView]; } - (CGFloat)crossSingleSectionSize{ if (self.direction == FMLayoutDirectionHorizontal) { NSInteger itemCount = self.itemCount; if (itemCount == 0) { return self.sectionInset.top + self.sectionInset.bottom; } NSInteger singleCount = (self.collectionView.frame.size.width - self.sectionInset.left - self.sectionInset.right) / (self.itemSize.width + self.itemSpace);///单行可显示的最大个数 if (itemCount > singleCount * self.column) { //可滚动 singleCount = itemCount % self.column == 0 ? itemCount / self.column : (itemCount / self.column + 1); } NSInteger realLines = itemCount % singleCount == 0 ? itemCount / singleCount : (itemCount / singleCount + 1); return self.itemSize.height * realLines + (realLines - 1) * self.lineSpace + self.sectionInset.top + self.sectionInset.bottom; } else { NSInteger realLines = self.column; return self.itemSize.width * realLines + (realLines - 1) * self.itemSpace + self.sectionInset.left + self.sectionInset.right; } } @end ================================================ FILE: FMLayoutKit/Classes/Sections/FMLayoutLabelSection.h ================================================ // // FMLayoutLabelSection.h // FMCollectionLayout // // Created by 周发明 on 2020/4/8. // #import "FMLayoutDynamicSection.h" #import "FMLayoutElement.h" NS_ASSUME_NONNULL_BEGIN ///返回cell大小的block typedef CGFloat(^FMLayoutItemWidthBlock)(id section, NSInteger item); ///当到第多少个的时候超出最大行 可移除数据处理 itemDatas会清理 否则frame为zero typedef CGFloat(^FMLayoutOverItemBlock)(id section, NSInteger item); ///标签式布局 根据文本伸缩布局 宽度不够 换行 适用于历史搜索记录 sku选择等样式 @interface FMLayoutLabelSection : FMLayoutDynamicSection ///最大行数 超出讲不显示 纵向布局时生效 @property(nonatomic, assign)NSInteger maxLine; ///cell固定的高度 @property(nonatomic, assign)CGFloat cellFixedHeight; ///cell最大宽度 不设置的话 就是collection的宽度减去左右分组内边距 @property(nonatomic, assign)CGFloat cellMaxWidth; ///block返回手动计算的宽度 @property(nonatomic, copy)FMLayoutItemWidthBlock widthBlock; ///block返回手动计算的宽度 @property(nonatomic, copy)FMLayoutOverItemBlock overItemBlock; @end NS_ASSUME_NONNULL_END ================================================ FILE: FMLayoutKit/Classes/Sections/FMLayoutLabelSection.m ================================================ // // FMLayoutLabelSection.m // FMCollectionLayout // // Created by 周发明 on 2020/4/8. // #import "FMLayoutLabelSection.h" #import "FMCollectionLayoutAttributes.h" #import "FMLayoutHeader.h" #import "FMLayoutFooter.h" @interface FMLayoutLabelSection () @property(nonatomic, assign)NSInteger vLastLines; @end @implementation FMLayoutLabelSection - (id)copyWithZone:(NSZone *)zone{ FMLayoutLabelSection *label = [super copyWithZone:zone]; label.maxLine = self.maxLine; label.cellFixedHeight = self.cellFixedHeight; label.cellMaxWidth = self.cellMaxWidth; label.widthBlock = [self.widthBlock copy]; label.overItemBlock = [self.overItemBlock copy]; return label; } - (void)prepareItems{ if ([self prepareLayoutItemsIsOlnyChangeOffset]) return; if (self.direction == FMLayoutDirectionVertical) { self.column = 1; [self resetcolumnSizes]; NSInteger items = MIN([self.collectionView numberOfItemsInSection:self.indexPath.section], self.itemCount); NSMutableArray *attrs = [NSMutableArray array]; int first = 0; NSInteger lines = 0; if (self.handleType == FMLayoutHandleTypeAppend) { attrs = [self.itemsAttribute mutableCopy]; first = (int)self.handleItemStart; lines = self.vLastLines; } if (self.cellMaxWidth == 0) { self.cellMaxWidth = self.collectionView.frame.size.width - self.sectionInset.left - self.sectionInset.right; } CGFloat startX = attrs.count > 0 ? CGRectGetMaxX([attrs firstObject].frame) : self.firstItemStartX; CGFloat startY = self.firstItemStartY; CGFloat maxCellHeight = 0; CGFloat leftWidth = self.collectionView.frame.size.width - startX - self.sectionInset.right; for (int j = 0; j < items; j++) { FMCollectionLayoutAttributes *itemAttr = [FMCollectionLayoutAttributes layoutAttributesForCellWithIndexPath:[NSIndexPath indexPathForItem:j inSection:self.indexPath.section]]; CGFloat x; CGFloat y; CGFloat width = !self.widthBlock?0:self.widthBlock(self, j); width = MIN(width, self.cellMaxWidth); if (width <= leftWidth) { //够放一行 x = startX; y = startY; startX += width + self.itemSpace; leftWidth = leftWidth - width - self.itemSpace; } else { //需换行 if (self.maxLine > 0) { if (lines < self.maxLine - 1) { //还可以继续算 lines += 1; startX = self.firstItemStartX; x = startX; startY += self.cellFixedHeight + self.lineSpace; y = startY; leftWidth = self.collectionView.frame.size.width - self.firstItemStartX - self.sectionInset.right - width - self.itemSpace; startX += width + self.itemSpace; } else { //到最大行数了 if (self.overItemBlock) { self.overItemBlock(self, j); } break; } } else { lines += 1; startX = self.firstItemStartX; x = startX; startY += self.cellFixedHeight + self.lineSpace; y = startY; leftWidth = self.collectionView.frame.size.width - self.firstItemStartX - self.sectionInset.right - width - self.itemSpace; startX += width + self.itemSpace; } } maxCellHeight = lines * (self.cellFixedHeight + self.lineSpace) + self.cellFixedHeight; self.vLastLines = lines; CGSize itemSize = CGSizeMake(width, self.cellFixedHeight); itemAttr.frame = CGRectMake(x, y, itemSize.width, itemSize.height); [attrs addObject:itemAttr]; if (self.configureCellLayoutAttributes) { self.configureCellLayoutAttributes(self, itemAttr, j); } } self.columnSizes[@(0)] = @(maxCellHeight); self.itemsAttribute = [attrs copy]; } else { self.column = self.maxLine; [self resetcolumnSizes]; NSInteger items = MIN([self.collectionView numberOfItemsInSection:self.indexPath.section], self.itemCount); NSMutableArray *attrs = [NSMutableArray array]; int first = 0; if (self.handleType == FMLayoutHandleTypeAppend) { attrs = [self.itemsAttribute mutableCopy]; first = (int)self.handleItemStart; } for (int j = first; j < items; j++) { FMCollectionLayoutAttributes *itemAttr = [FMCollectionLayoutAttributes layoutAttributesForCellWithIndexPath:[NSIndexPath indexPathForItem:j inSection:self.indexPath.section]]; CGFloat width = !self.widthBlock?0:self.widthBlock(self, j); CGSize itemSize = CGSizeMake(width, self.cellFixedHeight); NSInteger column = [self getMinHeightColumn]; CGFloat minWidth = [self.columnSizes[@(column)] floatValue]; CGFloat x = self.firstItemStartX + (minWidth > 0 ? (minWidth + self.itemSpace) : minWidth); CGFloat y = self.firstItemStartY + column * (self.lineSpace + itemSize.height); itemAttr.frame = CGRectMake(x, y, itemSize.width, itemSize.height); [attrs addObject:itemAttr]; self.columnSizes[@(column)] = @(minWidth + itemSize.width + (minWidth > 0 ? self.itemSpace : 0)); if (self.configureCellLayoutAttributes) { self.configureCellLayoutAttributes(self, itemAttr, j); } } self.itemsAttribute = [attrs copy]; } } - (CGFloat)crossSingleSectionSize{ if (self.direction == FMLayoutDirectionHorizontal) { if (self.itemCount > self.maxLine) { return self.maxLine * self.cellFixedHeight + (self.maxLine - 1) * self.lineSpace + self.sectionInset.top + self.sectionInset.bottom; } else { return self.itemCount * self.cellFixedHeight + (self.itemCount - 1) * self.lineSpace + self.sectionInset.top + self.sectionInset.bottom; } } else { if (self.itemCount > self.maxLine) { return self.maxLine * self.cellFixedHeight + (self.maxLine - 1) * self.itemSpace + self.sectionInset.left + self.sectionInset.right; } else { return self.itemCount * self.cellFixedHeight + (self.itemCount - 1) * self.itemSpace + self.sectionInset.left + self.sectionInset.right; } } } @end ================================================ FILE: FMLayoutKit/Classes/Sections/FMLayoutScaleSection.h ================================================ // // FMLayoutScaleSection.h // FMLayoutKit // // Created by 郑桂华 on 2020/7/20. // #import "FMLayoutDynamicSection.h" NS_ASSUME_NONNULL_BEGIN ///支持两种设置固定大小的方式 一种直接给数组sizeNums 一种给比例字符串scales 后设置的生效 @interface FMLayoutScaleSection : FMLayoutDynamicSection /// 纵向布局 则是宽度比例 横向布局 则是高度比例 例如纵向布局时该值为: 1:2:3 则就是3列 宽度比为剩下的值的比例 仅支持当前样式 可以是小数值 但不能为非数值类型 @property(nonatomic, copy)NSString *scales; ///每一列的固定大小 如:@[@100, @200] 则表示两列 一个固定宽度为100 另外一列为200 共两列 @property(nonatomic, strong)NSArray *sizeNums; @end NS_ASSUME_NONNULL_END ================================================ FILE: FMLayoutKit/Classes/Sections/FMLayoutScaleSection.m ================================================ // // FMLayoutScaleSection.m // FMLayoutKit // // Created by 郑桂华 on 2020/7/20. // #import "FMLayoutScaleSection.h" #import "FMCollectionLayoutAttributes.h" @interface __FMLayoutScaleModel : NSObject @property(nonatomic, assign)BOOL hasHandle; @property(nonatomic, assign)NSInteger index; @property(nonatomic, assign)CGFloat scale; @property(nonatomic, assign)CGFloat beginValue; @property(nonatomic, assign)CGFloat fixedSize; @property(nonatomic, assign)CGFloat x; @property(nonatomic, assign)CGFloat y; @end @implementation __FMLayoutScaleModel + (instancetype)modelWithIndex:(NSInteger)index scale:(CGFloat)scale{ __FMLayoutScaleModel *model = [[__FMLayoutScaleModel alloc] init]; model.index = index; model.scale = scale; model.x = -1; model.y = -1; model.fixedSize = -1; return model; } @end @interface FMLayoutScaleSection () @property(nonatomic, strong)NSMutableDictionary *fixedSizes; @end @implementation FMLayoutScaleSection - (void)setScales:(NSString *)scales{ _scales = scales; NSArray *scaleNums = [scales componentsSeparatedByString:@":"]; self.column = scaleNums.count; CGFloat total = 0.0; for (NSString *num in scaleNums) { total += [num floatValue]; } self.fixedSizes = [NSMutableDictionary dictionary]; CGFloat totalS = 0.0; for (int i = 0; i < self.column; i++) { NSString *num = scaleNums[i]; __FMLayoutScaleModel *model = [__FMLayoutScaleModel modelWithIndex:i scale:[num floatValue] / total]; model.beginValue = totalS; self.fixedSizes[@(i)] = model; totalS += model.scale; } } - (void)setSizeNums:(NSArray *)sizeNums{ _sizeNums = sizeNums; self.column = sizeNums.count; self.fixedSizes = [NSMutableDictionary dictionary]; CGFloat begin = 0; for (int i = 0; i < self.column; i++) { NSNumber *num = sizeNums[i]; __FMLayoutScaleModel *model = [[__FMLayoutScaleModel alloc] init]; model.index = i; model.fixedSize = [num floatValue]; model.beginValue = begin; self.fixedSizes[@(i)] = model; begin += model.fixedSize; } } - (__FMLayoutScaleModel *)getScaleModelColumn:(NSInteger)column{ __FMLayoutScaleModel *model = self.fixedSizes[@(column)]; if (model.hasHandle) { return model; } if (model.fixedSize > 0) { if (self.direction == FMLayoutDirectionVertical) { model.x = model.beginValue + self.sectionInset.left + column * self.itemSpace; } else { model.y = model.beginValue + self.sectionInset.top + column * self.lineSpace; } model.hasHandle = YES; return model; } else { CGFloat scale = model.scale; if (self.direction == FMLayoutDirectionVertical) { CGFloat totalWidth = self.collectionView.frame.size.width - self.sectionInset.left - self.sectionInset.right - (self.column - 1) * self.itemSpace; CGFloat size = totalWidth * scale; model.fixedSize = size; model.x = totalWidth * model.beginValue + self.sectionInset.left + column * self.itemSpace; } else { CGFloat totalHeight = self.collectionView.frame.size.height - self.sectionInset.top - self.sectionInset.bottom - (self.column - 1) * self.lineSpace; CGFloat size = totalHeight * scale; model.fixedSize = size; model.y = totalHeight * model.beginValue + self.sectionInset.top + column * self.lineSpace; } model.hasHandle = YES; return model; } } - (FMCollectionLayoutAttributes *)getItemAttributesWithIndex:(NSInteger)j{ NSIndexPath *indexPath = [NSIndexPath indexPathForItem:j inSection:self.indexPath.section]; FMCollectionLayoutAttributes *itemAttr = [FMCollectionLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; NSInteger column = [self getMinHeightColumn]; __FMLayoutScaleModel *model = [self getScaleModelColumn:column]; CGFloat itemFixed = model.fixedSize; CGFloat itemOther = 0; if (self.autoHeightFixedWidth) { itemOther = [self autoHeightVerticalWithWidth:itemFixed index:j]; } else { itemOther = !self.otherBlock?0:self.otherBlock(self, j); } if (self.direction == FMLayoutDirectionVertical) { CGSize itemSize = CGSizeMake(itemFixed, itemOther); CGFloat x = model.x; CGFloat height = [self.columnSizes[@(column)] floatValue]; CGFloat y = self.firstItemStartY + (height > 0 ? (height + self.lineSpace) : height); itemAttr.frame = CGRectMake(x, y, itemSize.width, itemSize.height); self.columnSizes[@(column)] = @(height + itemSize.height + (height > 0 ? self.lineSpace : 0)); } else { CGSize itemSize = CGSizeMake(itemOther, itemFixed); CGFloat minWidth = [self.columnSizes[@(column)] floatValue]; CGFloat x = self.firstItemStartX + (minWidth > 0 ? (minWidth + self.itemSpace) : minWidth); CGFloat y = model.y; itemAttr.frame = CGRectMake(x, y, itemSize.width, itemSize.height); self.columnSizes[@(column)] = @(minWidth + itemSize.width + (minWidth > 0 ? self.itemSpace : 0)); } if (self.configureCellLayoutAttributes) { self.configureCellLayoutAttributes(self, itemAttr, j); } return itemAttr; } @end ================================================ FILE: FMLayoutKit/Classes/UIView+FMLayout.h ================================================ // // UIView+FMLayout.h // FMLayoutKit // // Created by 郑桂华 on 2021/3/27. // #import NS_ASSUME_NONNULL_BEGIN @interface UIView (FMLayout) - (UIView *)snapshotView; @end NS_ASSUME_NONNULL_END ================================================ FILE: FMLayoutKit/Classes/UIView+FMLayout.m ================================================ // // UIView+FMLayout.m // FMLayoutKit // // Created by 郑桂华 on 2021/3/27. // #import "UIView+FMLayout.h" @implementation UIView (FMLayout) - (UIView *)snapshotView{ UIGraphicsBeginImageContextWithOptions(self.frame.size, NO, [UIScreen mainScreen].scale); CGContextRef context = UIGraphicsGetCurrentContext(); [self.layer renderInContext:context]; UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); UIImageView *imageView = [[UIImageView alloc] initWithImage:image]; UIView *sourceView = [[UIView alloc] initWithFrame:self.frame]; sourceView.layer.shadowColor = [UIColor darkGrayColor].CGColor; sourceView.layer.shadowOffset = CGSizeMake(0, 0); sourceView.layer.shadowOpacity = 0.7; [sourceView addSubview:imageView]; imageView.translatesAutoresizingMaskIntoConstraints = NO; NSLayoutConstraint *left = [NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:sourceView attribute:NSLayoutAttributeLeft multiplier:1 constant:0]; NSLayoutConstraint *right = [NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:sourceView attribute:NSLayoutAttributeRight multiplier:1 constant:0]; NSLayoutConstraint *top = [NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:sourceView attribute:NSLayoutAttributeTop multiplier:1 constant:0]; NSLayoutConstraint *bottom = [NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:sourceView attribute:NSLayoutAttributeBottom multiplier:1 constant:0]; [sourceView addConstraints:@[left,right,top,bottom]]; return sourceView; } @end ================================================ FILE: FMLayoutKit/Classes/_FMLayoutSussEmptyView.h ================================================ // // _FMLayoutSussEmptyView.h // FMLayoutKit // // Created by 郑桂华 on 2021/4/8. // #import NS_ASSUME_NONNULL_BEGIN @interface _FMLayoutSussEmptyView : UICollectionReusableView @end NS_ASSUME_NONNULL_END ================================================ FILE: FMLayoutKit/Classes/_FMLayoutSussEmptyView.m ================================================ // // _FMLayoutSussEmptyView.m // FMLayoutKit // // Created by 郑桂华 on 2021/4/8. // #import "_FMLayoutSussEmptyView.h" @implementation _FMLayoutSussEmptyView - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.hidden = YES; } return self; } @end ================================================ FILE: FMLayoutKit.podspec ================================================ # # Be sure to run `pod lib lint FMLayoutKit.podspec' to ensure this is a # valid spec before submitting. # # Any lines starting with a # are optional, but their use is encouraged # To learn more about a Podspec see https://guides.cocoapods.org/syntax/podspec.html # Pod::Spec.new do |s| s.name = 'FMLayoutKit' s.version = '1.2.0' s.summary = 'A short description of FMLayoutKit.' # This description is used to generate tags and improve search results. # * Think: What does it do? Why did you write it? What is the focus? # * Try to keep it short, snappy and to the point. # * Write the description between the DESC delimiters below. # * Finally, don't worry about the indent, CocoaPods strips it! s.description = <<-DESC TODO: Add long description of the pod here. DESC s.homepage = 'https://github.com/CoderFM/FMLayoutKit' # s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2' s.license = { :type => 'MIT', :file => 'LICENSE' } s.author = { 'CoderFM' => 'zhoufaming251@163.com' } s.source = { :git => 'https://github.com/CoderFM/FMLayoutKit.git', :tag => s.version.to_s } # s.social_media_url = 'https://twitter.com/' s.ios.deployment_target = '8.0' s.source_files = 'FMLayoutKit/Classes/**/*' # s.resource_bundles = { # 'FMLayoutKit' => ['FMLayoutKit/Assets/*.png'] # } # s.public_header_files = 'Pod/Classes/**/*.h' # s.frameworks = 'UIKit', 'MapKit' # s.dependency 'AFNetworking', '~> 2.3' end ================================================ FILE: LICENSE ================================================ Copyright (c) 2020 周发明 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # FMLayoutKit [![CI Status](https://img.shields.io/travis/周发明/FMLayoutKit.svg?style=flat)](https://travis-ci.org/周发明/FMLayoutKit) [![Version](https://img.shields.io/cocoapods/v/FMLayoutKit.svg?style=flat)](https://cocoapods.org/pods/FMLayoutKit) [![License](https://img.shields.io/cocoapods/l/FMLayoutKit.svg?style=flat)](https://cocoapods.org/pods/FMLayoutKit) [![Platform](https://img.shields.io/cocoapods/p/FMCollectionLayout.svg?style=flat)](https://cocoapods.org/pods/FMCollectionLayout) ## 简介 ### 一个可以让你更快的搞定复杂页面(电商首页,方格+列表多样式布局)的CollectionView自定义布局,目前支持纵向横向布局,可以穿插布局,动态cell高度做一些适配可以做到自动计算高度,也可以手动计算通过block返回,并且支持长按拖拽排序通过section以及layoutView开关控制是否可以拖拽排序,代码可以高度集中在一块,效果下面有演示,有什么问题随时issue我,感谢Star ## 安装方式 已发布到CocoaPods. podfile中添加以下代码: ```ruby pod 'FMLayoutKit' ``` Spec的官方源实在拉取不下来的话,可以用我自己的一个Spec仓: ```ruby https://gitee.com/Coder_FM/FMPodSpec.git ``` ## 联系方式 周发明, zhoufaming251@163.com ## License FMCollectionLayout is available under the MIT license. See the LICENSE file for more info. ## 提示 ### 使用动态自动计算高度的时候 label的preferredMaxLayoutWidth属性请给一个准确的值 否则计算label布局的高度不准确 穿插其他方向的布局 请使用FMLayoutCrossSection将所需要显示的section包裹进去, 可以包裹多个分组布局, 该分组也可以增加头部底部以及背景等 ## 支持的Cell布局样式以及头部悬停效果 ![效果图片](Jietu20200430-154528@2x.jpg) #### 分组Cell样式1 单一Cell,固定大小,支持多列,从左往右,从上往下布局 #### 分组Cell样式2 单一Cell,固定大小,支持最大行数,从左往右,如果当前屏幕够放,不会滚动,多的才会滚动 ![效果图片](Jietu20200430-154538@2x.jpg) #### 分组Cell样式3 可以多种Cell,block返回每一个item的大小,从左往右,从上往下,寻找最合适的位置放 ![效果图片](Jietu20200430-154718@2x.jpg) ![效果图片](Jietu20200430-154732@2x.jpg) #### 分组Cell样式4 瀑布流样式,支持多种cell样式,单列就是列表样式,列表可变,高度可以通过手动计算,也可以通过autolayout布局自动计算(续配置数据) ![效果图片](Jietu20200430-154739@2x.jpg) #### 分组Cell样式5 标签式布局,支持单种cell,可以单行滚动,也可以纵向布局,可限制最大行数(历史搜索记录那种样式) #### 分组头部支持的样式有4种 - 一般样式跟着滚动 - 悬浮跟着分组滚动 - 一直悬浮,滚动置顶样式 - 第一个分组下拉放大效果(效果无法截图) ## 多屏滑动效果 ![效果图片](Jietu20200430-154610@2x.jpg) ![效果图片](Jietu20200430-154705@2x.jpg) 每一个分组都可以设置头部,底部,背景,这三个都有inset可以设置内边距,灵活多变 特斯拉滚动视图是基于FMLayoutView的,共享的头部是一个FMLayoutView,横向每一屏都是FMLayoutView,最底部可以横向滚动是一个ScrollView,当触摸到头部的时候,ScrollView的pan手势会失效,横向滚动时,会将共享的头部移到最顶部视图上,滚动结束静止下来的时候,会将共享头部加到当前上下滚动的FMLayoutView,以达到效果 ### 使用示例 ``` objc /// 创建CollectionView delegate以及dataSource默认自己已遵守实现了一些方法 FMLayoutView *view = [[FMLayoutView alloc] init]; /// 需要布局的分组 [view.layout setSections:self.shareSections]; view.backgroundColor = [UIColor whiteColor]; [self.view addSubview:view]; [view mas_makeConstraints:^(MASConstraintMaker *make) { make.left.right.bottom.mas_equalTo(0); make.top.mas_equalTo(100); }]; self.collectionView = view; /// 固定大小 单一cell样式的分组 FMLayoutFixedSection *section = [FMLayoutFixedSection sectionWithSectionInset:UIEdgeInsetsMake(0, 15, 15, 15) itemSpace:10 lineSpace:10 column:2]; /// 配置分组头部 高度以及view类 section.header = [FMLayoutHeader elementSize:100 viewClass:[FMCollectionCustomDecoration class]]; /// 头部最底距离item的间距 section.header.bottomMargin = 10; /// 头部样式是否悬停 section.header.type = FMHeaderTypeSuspensionBigger; /// 头部内边距 section.header.inset = UIEdgeInsetsMake(0, -15, 0, -15); /// [section setConfigureHeaderData:^(FMLayoutBaseSection * _Nonnull section, UICollectionReusableView * _Nonnull header) { FMCollectionCustomDecoration *customHeader = (FMCollectionCustomDecoration *)header; customHeader.textLabel.text = @"固定大小, 从左往右从上往下排的分组, 头部放大缩放效果"; }]; /// 配置分组底部 section.footer = [FMLayoutFooter elementSize:50 viewClass:[FMCollectionCustomDecoration class]]; section.footer.topMargin = 10; /// 配置Item样式 section.itemSize = CGSizeMake(100, 100); section.itemDatas = [@[@"1", @"2", @"3"] mutableCopy]; /// cell的类 可以纯代码也可以Xib section.cellElement = [FMLayoutElement elementWithViewClass:[FMCollectionCustomCell class]]; /// cell赋值数据 [section setConfigureCellData:^(FMLayoutBaseSection * _Nonnull section, UICollectionViewCell * _Nonnull cell, NSInteger item) { }]; /// cell点击事件 [section setClickCellBlock:^(FMLayoutBaseSection * _Nonnull section, NSInteger item) { FMAddViewController *add = [[FMAddViewController alloc] init]; [self.navigationController pushViewController:add animated:YES]; }]; #pragma mark --- 动态分组 /// cell类的数组 section.cellElements = @[[FMLayoutElement elementWithViewClass:[FMCollectionCustomCell class]]]; /// 需固定宽度 section.cellFixedSize = [UIScreen mainScreen].bounds.size.width; /// 手动计算高度 [section setOtherBlock:^CGFloat(id _Nonnull section, NSInteger item) { return 100 + item * 100; }]; /// 或者可以自动计算高度 布局约束好 数据填充完 section.autoHeightFixedWidth = YES; /// 对应index需要返回的reusedId来取对应的cell [section setDeqCellReturnReuseId:^NSString * _Nonnull(FMLayoutDynamicSection * _Nonnull section, NSInteger index) { return [section.cellElements firstObject].reuseIdentifier; }]; #pragma mark --- 标签分组 /// 不是单行的话 可以限制最大行数 section.maxLine = 6; /// 固定每一个高度 section.cellFixedHeight = 40; /// 返回对应的宽度 [section setWidthBlock:^CGFloat(id _Nonnull section, NSInteger item) { return item * 20 + 100; }]; #pragma mark --- 填充布局分组 /// 需返回大小 插入到合适的位置 [section setSizeBlock:^CGSize(id _Nonnull section, NSInteger item) { switch (item) { case 2: return CGSizeMake(150, 140.32); case 5: return CGSizeMake((self.view.frame.size.width-20-150)/2, 70.19); case 8: case 11: return CGSizeMake(100, 240); case 10: return CGSizeMake(self.view.frame.size.width-20-200, 140); case 9: case 12: return CGSizeMake(self.view.frame.size.width-20-100, 100); case 0: case 1: case 3: case 4: return CGSizeMake((self.view.frame.size.width-20-150)/4, 70.13); default: return CGSizeMake((self.view.frame.size.width-20-150)/4, 70.19); } }]; #pragma mark --- 特斯拉组件的使用说明 内部都是FMCollectionLayoutView的组合 /// 创建组件 遵守代理并实现必须的方法 FMTeslaLayoutView *multi = [[FMTeslaLayoutView alloc] init]; multi.delegate = self; multi.dataSource = self; [self.view addSubview:multi]; /// 悬停头部的最小高度 伸缩动画用 - (CGFloat)shareSuspensionMinHeightWithTesla:(FMTeslaLayoutView *)tesla{ return 70; } /// 即将创建FMCollectionLayoutView 每一个分页只创建一个 懒加载 - (void)tesla:(FMTeslaLayoutView *)tesla willCreateLayoutViewWithIndex:(NSInteger)index{ NSLog(@"willCreateLayoutViewWithIndex %ld", (long)index); } // 已创建FMCollectionLayoutView - (void)tesla:(FMTeslaLayoutView *)tesla didCreatedLayoutViewWithIndex:(NSInteger)index layoutView:(FMCollectionLayoutView *)layoutView{ NSLog(@"didCreatedLayoutViewWithIndex %ld", (long)index); } // 分页滚动到哪一页 并返回当前页的layoutView - (void)tesla:(FMTeslaLayoutView *)tesla didScrollEnd:(NSInteger)index currentLayoutView:(nonnull FMCollectionLayoutView *)layoutView{ [self.navTitleView selectWithIndex:index]; } /// 分页个数 - (NSInteger)numberOfScreenInTesla:(nonnull FMTeslaLayoutView *)tesla { return 4; } /// 头部共享的集合 - (NSArray *)shareSectionsInTesla:(FMTeslaLayoutView *)tesla{ return self.shareSections; } ``` #### 版本更新 2020-08-21(1.2.0) 新增单分组隐藏显示 新增动态计算高度计算之后再更改一次的方法 2020-08-21(1.1.9) 修复小bug,增加section刷新方法 2020-08-21(1.1.8) tesla优化修复bug, 填充布局支持间距 2020-08-02(1.1.6) 自动计算高度优化 2020-07-24(1.1.3) iOS10,11自动计算高度奔溃的问题修复 2020-07-24(1.1.2) 合并分组优化, 创建完之后可以插入分组追加分组 2020-07-21(1.1.1) 合并取消支持拖拽, 会出现多重问题, 拖拽切换数据的问题修复 2020-07-21(1.1.0) 清楚长按拖拽View的背景色 长按拖拽可控制分组中某些item不支持拖拽, 修复合并分组的奔溃问题 2020-07-20(1.0.8) 代码优化, 新增动态布局不等宽的布局, 可实现更多种布局方案 2020-07-16(1.0.7) 优化tesla组件, 可以主创建scrollView 但是顶部边距空出来 不可用inset操作 2020-07-15(1.0.6) 新增长按拖拽 通过layoutView以及section控制开关。 新增纵向穿插横向布局自动滚到中间,并支持自定义根据进度做动画效果 2020-07-14(1.0.5) 修复分组头部底部背景重用标识符问题, 代码优化 2020-07-13(1.0.3) 放大缩小效果优化 新增是否可以黏在顶部 新增合并分组 将不同的cell合并到一个分组去 2020-07-09(1.0.2) 新增可复制分组, 以便于快读创建分组 2020-07-09 重写滚动到某一行的方法, 计算出偏移量 2020-07-08(1.0.1) 由老版本FMCollectionLayout优化更改名字FMLayoutKit重新上传 #### 感谢观看 有使用问题,欢迎联系我随时交流,QQ:847881570, 能Star一下的话,感激不尽 ================================================ FILE: submitNewVersion.sh ================================================ #! /bin/bash basePath=$(cd "$(dirname "$0")";pwd) cd $basePath pod repo push FMPodSpec FMLayoutKit.podspec --allow-warnings && pod trunk push FMLayoutKit.podspec --allow-warnings