Container Inset Size For Section Controller

Summary:
Add API for #315. Not sure if this is what you want rnystrom though 🤔. Will add tests after you confirm.

- [x] All tests pass. Demo project builds and runs.
- [x] I added tests, an experiment, or detailed why my change isn't tested.
- [ ] I added an entry to the `CHANGELOG.md` for any breaking changes, enhancements, or bug fixes.
- [x] I have reviewed the [contributing guide](https://github.com/Instagram/IGListKit/blob/master/.github/CONTRIBUTING.md)
Closes https://github.com/Instagram/IGListKit/pull/456

Reviewed By: jessesquires

Differential Revision: D4697190

Pulled By: rnystrom

fbshipit-source-id: f8513cf2fa33441eb40f486954136553d19dda0c
This commit is contained in:
Bofei Zhu 2017-03-15 09:25:03 -07:00 committed by Facebook Github Bot
parent 79348164a7
commit f7702fa713
10 changed files with 142 additions and 3 deletions

View file

@ -236,6 +236,8 @@
8285404D1DE40C6E00118B94 /* IGListTestHorizontalSection.m in Sources */ = {isa = PBXBuildFile; fileRef = 8285404B1DE40C6E00118B94 /* IGListTestHorizontalSection.m */; };
828540501DE40D2D00118B94 /* IGListTestAdapterHorizontalDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 8285404F1DE40D2D00118B94 /* IGListTestAdapterHorizontalDataSource.m */; };
828540511DE40D2D00118B94 /* IGListTestAdapterHorizontalDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 8285404F1DE40D2D00118B94 /* IGListTestAdapterHorizontalDataSource.m */; };
82914C5B1E6E2DEC0066C2F8 /* IGListTestContainerSizeSection.m in Sources */ = {isa = PBXBuildFile; fileRef = 82914C5A1E6E2DEC0066C2F8 /* IGListTestContainerSizeSection.m */; };
82914C5C1E6E2DEC0066C2F8 /* IGListTestContainerSizeSection.m in Sources */ = {isa = PBXBuildFile; fileRef = 82914C5A1E6E2DEC0066C2F8 /* IGListTestContainerSizeSection.m */; };
829D7BAA1DD1819000549816 /* IGListSectionMapTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 829D7BA81DD1816400549816 /* IGListSectionMapTests.m */; };
88144F071D870EDC007C7F66 /* IGListAdapterE2ETests.m in Sources */ = {isa = PBXBuildFile; fileRef = 88144EE21D870EDC007C7F66 /* IGListAdapterE2ETests.m */; };
88144F081D870EDC007C7F66 /* IGListAdapterTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 88144EE31D870EDC007C7F66 /* IGListAdapterTests.m */; };
@ -451,6 +453,8 @@
8285404B1DE40C6E00118B94 /* IGListTestHorizontalSection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IGListTestHorizontalSection.m; sourceTree = "<group>"; };
8285404E1DE40D2D00118B94 /* IGListTestAdapterHorizontalDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IGListTestAdapterHorizontalDataSource.h; sourceTree = "<group>"; };
8285404F1DE40D2D00118B94 /* IGListTestAdapterHorizontalDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IGListTestAdapterHorizontalDataSource.m; sourceTree = "<group>"; };
82914C591E6E2DEC0066C2F8 /* IGListTestContainerSizeSection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IGListTestContainerSizeSection.h; sourceTree = "<group>"; };
82914C5A1E6E2DEC0066C2F8 /* IGListTestContainerSizeSection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IGListTestContainerSizeSection.m; sourceTree = "<group>"; };
829D7BA81DD1816400549816 /* IGListSectionMapTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IGListSectionMapTests.m; sourceTree = "<group>"; };
841726B542A3E9A4BD48946F /* Pods-IGListKit-tvOSTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-IGListKit-tvOSTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-IGListKit-tvOSTests/Pods-IGListKit-tvOSTests.debug.xcconfig"; sourceTree = "<group>"; };
88144EE21D870EDC007C7F66 /* IGListAdapterE2ETests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IGListAdapterE2ETests.m; sourceTree = "<group>"; };
@ -739,6 +743,8 @@
298DD9D91E3ADE3300F76F50 /* IGTestStringBindableCell.m */,
88144F051D870EDC007C7F66 /* IGTestSupplementarySource.h */,
88144F061D870EDC007C7F66 /* IGTestSupplementarySource.m */,
82914C591E6E2DEC0066C2F8 /* IGListTestContainerSizeSection.h */,
82914C5A1E6E2DEC0066C2F8 /* IGListTestContainerSizeSection.m */,
);
path = Objects;
sourceTree = "<group>";
@ -1344,6 +1350,7 @@
298DDA3C1E3B170300F76F50 /* IGLayoutTestSection.m in Sources */,
298DDA0A1E3AE31E00F76F50 /* IGTestDiffingSectionController.m in Sources */,
29C4748D1DDF45F900AE68CE /* IGListAdapterProxyTests.m in Sources */,
82914C5C1E6E2DEC0066C2F8 /* IGListTestContainerSizeSection.m in Sources */,
885FE22C1DC51B76009CE2B4 /* IGListAdapterTests.m in Sources */,
298DDA051E3AE2B000F76F50 /* IGTestStringBindableCell.m in Sources */,
885FE22D1DC51B76009CE2B4 /* IGListAdapterUpdaterTests.m in Sources */,
@ -1431,6 +1438,7 @@
298DDA3D1E3B170400F76F50 /* IGLayoutTestSection.m in Sources */,
298DDA091E3AE31D00F76F50 /* IGTestDiffingSectionController.m in Sources */,
88144F151D870EDC007C7F66 /* IGListTestSection.m in Sources */,
82914C5B1E6E2DEC0066C2F8 /* IGListTestContainerSizeSection.m in Sources */,
88144F1D1D870EDC007C7F66 /* IGTestSupplementarySource.m in Sources */,
298DDA071E3AE2B100F76F50 /* IGTestStringBindableCell.m in Sources */,
88144F081D870EDC007C7F66 /* IGListAdapterTests.m in Sources */,

View file

@ -818,6 +818,12 @@
return UIEdgeInsetsInsetRect(self.collectionView.bounds, self.collectionView.contentInset).size;
}
- (CGSize)containerSizeForSectionController:(IGListSectionController<IGListSectionType> *)sectionController {
const UIEdgeInsets inset = sectionController.inset;
return CGSizeMake(self.containerSize.width - inset.left - inset.right,
self.containerSize.height - inset.top - inset.bottom);
}
- (NSInteger)indexForCell:(UICollectionViewCell *)cell sectionController:(nonnull IGListSectionController<IGListSectionType> *)sectionController {
IGAssertMainThread();
IGParameterAssert(cell != nil);

View file

@ -25,6 +25,15 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property (nonatomic, readonly) CGSize containerSize;
/**
Returns size of the collection view relative to the section controller.
@param sectionController The section controller requesting this information.
@return The size of the collection view minus the given section controller's insets.
*/
- (CGSize)containerSizeForSectionController:(IGListSectionController<IGListSectionType> *)sectionController;
/**
Returns the index of the specified cell in the collection relative to the section controller.

View file

@ -165,6 +165,12 @@ static void * kStackedSectionControllerIndexKey = &kStackedSectionControllerInde
return [self.collectionContext containerSize];
}
- (CGSize)containerSizeForSectionController:(IGListSectionController<IGListSectionType> *)sectionController {
const UIEdgeInsets inset = sectionController.inset;
return CGSizeMake(self.containerSize.width - inset.left - inset.right,
self.containerSize.height - inset.top - inset.bottom);
}
- (NSInteger)indexForCell:(UICollectionViewCell *)cell sectionController:(IGListSectionController<IGListSectionType> *)sectionController {
const NSInteger index = [self.collectionContext indexForCell:cell sectionController:self];
return [self localIndexForSectionController:sectionController index:index];

View file

@ -27,6 +27,12 @@ CGPoint p = CGPointMake(x, y); \
XCTAssertEqual(CGPointEqualToPoint(point, p), YES); \
} while(0)
#define IGAssertEqualSize(size, w, h, ...) \
do { \
CGSize s = CGSizeMake(w, h); \
XCTAssertEqual(CGSizeEqualToSize(size, s), YES); \
} while(0)
@interface IGListAdapterTests : XCTestCase
// infra does not hold a strong ref to collection view
@ -1083,4 +1089,12 @@ XCTAssertEqual(CGPointEqualToPoint(point, p), YES); \
XCTAssertEqualObjects(self.adapter.objects, expected);
}
- (void)test_whenSectionEdgeInsetIsNotZero {
// IGListTestAdapterDataSource does not handle NSStrings
self.dataSource.objects = @[@42];
[self.adapter reloadDataWithCompletion:nil];
IGListSectionController<IGListSectionType> *controller = [self.adapter sectionControllerForObject:@42];
IGAssertEqualSize([self.adapter containerSizeForSectionController:controller], 98, 98);
}
@end

View file

@ -17,6 +17,7 @@
#import "IGListDisplayHandler.h"
#import "IGListStackedSectionControllerInternal.h"
#import "IGListTestSection.h"
#import "IGListTestContainerSizeSection.h"
#import "IGTestCell.h"
#import "IGTestStackedDataSource.h"
#import "IGTestStoryboardCell.h"
@ -25,6 +26,12 @@
#import "IGTestSupplementarySource.h"
#import "IGTestStoryboardSupplementarySource.h"
#define IGAssertEqualSize(size, w, h, ...) \
do { \
CGSize s = CGSizeMake(w, h); \
XCTAssertEqual(CGSizeEqualToSize(size, s), YES); \
} while(0)
static const CGRect kStackTestFrame = (CGRect){{0.0, 0.0}, {100.0, 100.0}};
@interface IGListStackSectionControllerTests : XCTestCase
@ -142,6 +149,15 @@ static const CGRect kStackTestFrame = (CGRect){{0.0, 0.0}, {100.0, 100.0}};
XCTAssertTrue(CGSizeEqualToSize([section1.collectionContext containerSize], kStackTestFrame.size));
}
- (void)test_whenSectionEdgeInsetIsNotZero {
[self setupWithObjects:@[
[[IGTestObject alloc] initWithKey:@0 value:@[@42]]
]];
IGListStackedSectionController *stack = [self.adapter sectionControllerForObject:self.dataSource.objects[0]];
IGListTestContainerSizeSection *section1 = stack.sectionControllers[0];
IGAssertEqualSize([stack containerSizeForSectionController:section1], 98, 98);
}
- (void)test_whenQueryingCellIndex_thatIndexIsRelativeToSectionController {
[self setupWithObjects:@[
[[IGTestObject alloc] initWithKey:@0 value:@[@1, @1, @2]]

View file

@ -12,6 +12,7 @@
#import <IGListKit/IGListAdapter.h>
#import "IGListTestSection.h"
#import "IGListTestContainerSizeSection.h"
@implementation IGListTestAdapterDataSource
@ -21,6 +22,9 @@
- (IGListSectionController <IGListSectionType> *)listAdapter:(IGListAdapter *)listAdapter sectionControllerForObject:(id)object {
if ([object isKindOfClass:[NSNumber class]]) {
if ([(NSNumber*)object isEqual: @42]) {
return [IGListTestContainerSizeSection new];
}
return [IGListTestSection new];
}
return nil;

View file

@ -0,0 +1,19 @@
/**
* Copyright (c) 2016-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <UIKit/UIKit.h>
#import <IGListKit/IGListSectionController.h>
#import <IGListKit/IGListSectionType.h>
@interface IGListTestContainerSizeSection : IGListSectionController <IGListSectionType>
@property (nonatomic, assign) NSInteger items;
@end

View file

@ -0,0 +1,50 @@
/**
* Copyright (c) 2016-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import "IGListTestContainerSizeSection.h"
@implementation IGListTestContainerSizeSection
- (instancetype)init
{
self = [super init];
if (self) {
self.inset = UIEdgeInsetsMake(1.0, 1.0, 1.0, 1.0);
}
return self;
}
- (NSArray <Class> *)cellClasses {
return @[UICollectionViewCell.class];
}
- (NSInteger)numberOfItems {
return self.items;
}
- (CGSize)sizeForItemAtIndex:(NSInteger)index {
return CGSizeMake(100, 10);
}
- (UICollectionViewCell *)cellForItemAtIndex:(NSInteger)index {
return [self.collectionContext dequeueReusableCellOfClass:UICollectionViewCell.class
forSectionController:self
atIndex:index];
}
- (void)didUpdateToObject:(id)object {
if ([object isKindOfClass:[NSNumber class]]) {
self.items = [object integerValue];
}
}
- (void)didSelectItemAtIndex:(NSInteger)index {
}
@end

View file

@ -13,6 +13,7 @@
#import "IGTestCell.h"
#import "IGListTestSection.h"
#import "IGListTestContainerSizeSection.h"
@implementation IGTestStackedDataSource
@ -26,9 +27,15 @@
id controller;
// use a standard IGListTestSection
if ([value isKindOfClass:[NSNumber class]]) {
IGListTestSection *section = [[IGListTestSection alloc] init];
section.items = [value integerValue];
controller = section;
if ([(NSNumber*)value isEqual: @42]) {
IGListTestContainerSizeSection *section = [[IGListTestContainerSizeSection alloc] init];
section.items = [value integerValue];
controller = section;
} else {
IGListTestSection *section = [[IGListTestSection alloc] init];
section.items = [value integerValue];
controller = section;
}
} else if ([value isKindOfClass:[NSString class]]) {
void (^configureBlock)(id, __kindof UICollectionViewCell *) = ^(id obj, IGTestCell *cell) {
// capturing the value in block scope so we use the CHILD OBJECT of the stack