mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-23 06:35:51 +00:00
Add default ASCollectionViewLayoutInspecting for custom ASCollectionViewLayout
This commit is contained in:
@@ -254,7 +254,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
|||||||
// Custom layouts will need to roll their own ASCollectionViewLayoutInspecting implementation and set a layout
|
// Custom layouts will need to roll their own ASCollectionViewLayoutInspecting implementation and set a layout
|
||||||
// delegate. In the meantime ASDK provides a null layout inspector that does not provide any implementation
|
// delegate. In the meantime ASDK provides a null layout inspector that does not provide any implementation
|
||||||
// and throws an exception for methods that should be implemented in the <ASCollectionViewLayoutInspecting>
|
// and throws an exception for methods that should be implemented in the <ASCollectionViewLayoutInspecting>
|
||||||
_defaultLayoutInspector = [[ASCollectionViewNullLayoutInspector alloc] init];
|
_defaultLayoutInspector = [[ASCollectionViewDefaultCustomLayoutInspector alloc] initWithCollectionView:self];
|
||||||
}
|
}
|
||||||
_layoutInspector = _defaultLayoutInspector;
|
_layoutInspector = _defaultLayoutInspector;
|
||||||
|
|
||||||
|
|||||||
@@ -60,10 +60,14 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
@end
|
@end
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple "Null Object" inspector for non-flow layouts that does throws exceptions if methods are called
|
* A layout inspector for non-flow layouts that returns a constrained size to let the cells layout itself as
|
||||||
* from <ASCollectionViewLayoutInspecting>
|
* far as possible based on the scrollable direction of the collection view. It throws exceptions for delegate
|
||||||
|
* methods that are related to supplementary node's management.
|
||||||
*/
|
*/
|
||||||
@interface ASCollectionViewNullLayoutInspector : NSObject <ASCollectionViewLayoutInspecting>
|
@interface ASCollectionViewDefaultCustomLayoutInspector : NSObject <ASCollectionViewLayoutInspecting>
|
||||||
|
|
||||||
|
- (instancetype)init NS_UNAVAILABLE;
|
||||||
|
- (instancetype)initWithCollectionView:(ASCollectionView *)collectionView NS_DESIGNATED_INITIALIZER;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@@ -74,7 +78,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
|
|
||||||
@property (nonatomic, weak, readonly) UICollectionViewFlowLayout *layout;
|
@property (nonatomic, weak, readonly) UICollectionViewFlowLayout *layout;
|
||||||
|
|
||||||
- (instancetype)initWithCollectionView:(ASCollectionView *)collectionView flowLayout:(UICollectionViewFlowLayout *)flowLayout;
|
- (instancetype)init NS_UNAVAILABLE;
|
||||||
|
- (instancetype)initWithCollectionView:(ASCollectionView *)collectionView flowLayout:(UICollectionViewFlowLayout *)flowLayout NS_DESIGNATED_INITIALIZER;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
@@ -15,14 +15,57 @@
|
|||||||
|
|
||||||
#define kDefaultItemSize CGSizeMake(50, 50)
|
#define kDefaultItemSize CGSizeMake(50, 50)
|
||||||
|
|
||||||
#pragma mark - ASCollectionViewNullLayoutInspector
|
#pragma mark - Helper Functions
|
||||||
|
|
||||||
@implementation ASCollectionViewNullLayoutInspector
|
// Returns a constrained size to let the cells layout itself as far as possible based on the scrollable direction
|
||||||
|
// of the collection view
|
||||||
|
static ASSizeRange ASDefaultConstrainedSizeForNodeForCollectionView(ASCollectionView *collectionView) {
|
||||||
|
CGSize maxSize = collectionView.bounds.size;
|
||||||
|
if (ASScrollDirectionContainsHorizontalDirection(collectionView.scrollableDirections)) {
|
||||||
|
maxSize.width = FLT_MAX;
|
||||||
|
} else {
|
||||||
|
maxSize.height = FLT_MAX;
|
||||||
|
}
|
||||||
|
return ASSizeRangeMake(CGSizeZero, maxSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - ASCollectionViewDefaultCustomLayoutInspector
|
||||||
|
|
||||||
|
@implementation ASCollectionViewDefaultCustomLayoutInspector {
|
||||||
|
struct {
|
||||||
|
unsigned int implementsConstrainedSizeForNodeAtIndexPath:1;
|
||||||
|
} _dataSourceFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark Lifecycle
|
||||||
|
|
||||||
|
- (instancetype)initWithCollectionView:(ASCollectionView *)collectionView
|
||||||
|
{
|
||||||
|
self = [super init];
|
||||||
|
if (self != nil) {
|
||||||
|
[self didChangeCollectionViewDataSource:collectionView.asyncDataSource];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark ASCollectionViewLayoutInspecting
|
||||||
|
|
||||||
|
- (void)didChangeCollectionViewDataSource:(id<ASCollectionDataSource>)dataSource
|
||||||
|
{
|
||||||
|
if (dataSource == nil) {
|
||||||
|
memset(&_dataSourceFlags, 0, sizeof(_dataSourceFlags));
|
||||||
|
} else {
|
||||||
|
_dataSourceFlags.implementsConstrainedSizeForNodeAtIndexPath = [dataSource respondsToSelector:@selector(collectionView:constrainedSizeForNodeAtIndexPath:)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath
|
- (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath
|
||||||
{
|
{
|
||||||
ASDisplayNodeAssert(NO, @"To support a custom collection view layout in ASCollectionView, it must have a layoutInspector for layout inspection. (See ASCollectionViewFlowLayoutInspector for an example.)");
|
if (_dataSourceFlags.implementsConstrainedSizeForNodeAtIndexPath) {
|
||||||
return ASSizeRangeMake(CGSizeZero, CGSizeZero);
|
return [collectionView.asyncDataSource collectionView:collectionView constrainedSizeForNodeAtIndexPath:indexPath];
|
||||||
|
}
|
||||||
|
|
||||||
|
return ASDefaultConstrainedSizeForNodeForCollectionView(collectionView);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForSupplementaryNodeOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
|
- (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForSupplementaryNodeOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
|
||||||
@@ -64,7 +107,7 @@
|
|||||||
} _dataSourceFlags;
|
} _dataSourceFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Accessors
|
#pragma mark Lifecycle
|
||||||
|
|
||||||
- (instancetype)initWithCollectionView:(ASCollectionView *)collectionView flowLayout:(UICollectionViewFlowLayout *)flowLayout;
|
- (instancetype)initWithCollectionView:(ASCollectionView *)collectionView flowLayout:(UICollectionViewFlowLayout *)flowLayout;
|
||||||
{
|
{
|
||||||
@@ -80,6 +123,8 @@
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma mark ASCollectionViewLayoutInspecting
|
||||||
|
|
||||||
- (void)didChangeCollectionViewDelegate:(id<ASCollectionDelegate>)delegate;
|
- (void)didChangeCollectionViewDelegate:(id<ASCollectionDelegate>)delegate;
|
||||||
{
|
{
|
||||||
if (delegate == nil) {
|
if (delegate == nil) {
|
||||||
@@ -100,29 +145,18 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - ASCollectionViewLayoutInspecting
|
|
||||||
|
|
||||||
- (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath
|
- (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath
|
||||||
{
|
{
|
||||||
// First check if delegate provides a constrained size
|
|
||||||
if (_dataSourceFlags.implementsConstrainedSizeForNodeAtIndexPath) {
|
if (_dataSourceFlags.implementsConstrainedSizeForNodeAtIndexPath) {
|
||||||
return [collectionView.asyncDataSource collectionView:collectionView constrainedSizeForNodeAtIndexPath:indexPath];
|
return [collectionView.asyncDataSource collectionView:collectionView constrainedSizeForNodeAtIndexPath:indexPath];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if item size as constrained size is given
|
|
||||||
CGSize itemSize = _layout.itemSize;
|
CGSize itemSize = _layout.itemSize;
|
||||||
if (!CGSizeEqualToSize(itemSize, kDefaultItemSize)) {
|
if (!CGSizeEqualToSize(itemSize, kDefaultItemSize)) {
|
||||||
return ASSizeRangeMake(itemSize, itemSize);
|
return ASSizeRangeMake(itemSize, itemSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
// No constrained size is given try to let the cells layout itself as far as possible based on the scrollable direction
|
return ASDefaultConstrainedSizeForNodeForCollectionView(collectionView);
|
||||||
CGSize maxSize = collectionView.bounds.size;
|
|
||||||
if (ASScrollDirectionContainsHorizontalDirection([collectionView scrollableDirections])) {
|
|
||||||
maxSize.width = FLT_MAX;
|
|
||||||
} else {
|
|
||||||
maxSize.height = FLT_MAX;
|
|
||||||
}
|
|
||||||
return ASSizeRangeMake(CGSizeZero, maxSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForSupplementaryNodeOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
|
- (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForSupplementaryNodeOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
|
||||||
|
|||||||
@@ -124,14 +124,12 @@
|
|||||||
XCTAssert([collectionView.layoutInspector isKindOfClass:[ASCollectionViewFlowLayoutInspector class]], @"should have a flow layout inspector by default");
|
XCTAssert([collectionView.layoutInspector isKindOfClass:[ASCollectionViewFlowLayoutInspector class]], @"should have a flow layout inspector by default");
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)testThatItDoesNotSetALayoutInspectorForCustomLayouts
|
- (void)testThatISetALayoutInspectorForCustomLayouts
|
||||||
{
|
{
|
||||||
UICollectionViewLayout *layout = [[UICollectionViewLayout alloc] init];
|
UICollectionViewLayout *layout = [[UICollectionViewLayout alloc] init];
|
||||||
ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
|
ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
|
||||||
XCTAssert(collectionView.layoutInspector != nil, @"should automatically set a layout delegate for custom layouts");
|
XCTAssert(collectionView.layoutInspector != nil, @"should automatically set a layout delegate for flow layouts");
|
||||||
XCTAssert([collectionView.layoutInspector isKindOfClass:[ASCollectionViewNullLayoutInspector class]], @"should have a null layout inspector by default if no layout inspector is given for a custom layout");
|
XCTAssert([collectionView.layoutInspector isKindOfClass:[ASCollectionViewDefaultCustomLayoutInspector class]], @"should have a flow layout inspector by default");
|
||||||
XCTAssertThrows([collectionView.layoutInspector collectionView:collectionView constrainedSizeForNodeAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]], @"should throw an exception for <ASCollectionViewLayoutInspecting> methods");
|
|
||||||
XCTAssertThrows([collectionView.layoutInspector collectionView:collectionView supplementaryNodesOfKind:UICollectionElementKindSectionHeader inSection:0], @"should throw an exception for <ASCollectionViewLayoutInspecting> methods");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)testThatRegisteringASupplementaryNodeStoresItForIntrospection
|
- (void)testThatRegisteringASupplementaryNodeStoresItForIntrospection
|
||||||
|
|||||||
Reference in New Issue
Block a user