Customized post insertion animation

Summary:
The current animation is the collection default animation - fade in/out: demo: https://pxl.cl/bj8R
Based on our design, we want the Shelf to be push down: demo https://pxl.cl/bj9R

1. Created **IGListCollectionViewDelegate** which inherits **UICollectionViewDelegateFlowLayout**
2. **IGListAdapter ** conforms **UICollectionViewDelegateFlowLayout**
3. add **transitionDelegate** to IGListSectionController
4. **IGFeedSectionController** sets transitionDelegate as itself and handles IGListCollectionViewDelegate methods

Reviewed By: rnystrom

Differential Revision: D6785726

fbshipit-source-id: bdf19f84fef05264ca0e082c6a326a31494a20da
This commit is contained in:
Sue Suhan Ma 2018-01-29 10:54:42 -08:00 committed by Facebook Github Bot
parent b0283bfcdb
commit 26924ec3b6
7 changed files with 144 additions and 2 deletions

View file

@ -0,0 +1,36 @@
/**
* 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.
*/
/**
Conform to `IGListCollectionViewDelegateLayout` to provide customized layout information for a collection view.
*/
@protocol IGListCollectionViewDelegateLayout <UICollectionViewDelegateFlowLayout>
/**
Asks the delegate to customize and return the starting layout information for an item being inserted into the collection view.
@param collectionView The collection view to perform the transition on.
@param collectionViewLayout The layout to use with the collection view.
@param attributes The starting layout information for an item being inserted into the collection view.
@param indexPath The index path of the item being inserted.
*/
- (UICollectionViewLayoutAttributes *)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout customizedInitialLayoutAttributes:(UICollectionViewLayoutAttributes *)attributes atIndexPath:(NSIndexPath *)indexPath;
/**
Asks the delegate to customize and return the final layout information for an item that is about to be removed from the collection view.
@param collectionView The collection view to perform the transition on.
@param collectionViewLayout The layout to use with the collection view.
@param attributes The final layout information for an item that is about to be removed from the collection view.
@param indexPath The index path of the item being deleted.
*/
- (UICollectionViewLayoutAttributes *)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout customizedFinalLayoutAttributes:(UICollectionViewLayoutAttributes *)attributes atIndexPath:(NSIndexPath *)indexPath;
@end

View file

@ -14,6 +14,7 @@
#import <vector>
#import <IGListKit/IGListAssert.h>
#import <IGListKit/IGListCollectionViewDelegateLayout.h>
static CGFloat UIEdgeInsetsLeadingInsetInDirection(UIEdgeInsets insets, UICollectionViewScrollDirection direction) {
switch (direction) {
@ -206,6 +207,30 @@ static void adjustZIndexForAttributes(UICollectionViewLayoutAttributes *attribut
#pragma mark - UICollectionViewLayout
- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath {
UICollectionViewLayoutAttributes *attributes = [super initialLayoutAttributesForAppearingItemAtIndexPath:itemIndexPath];
id<IGListCollectionViewDelegateLayout> delegate = (id<IGListCollectionViewDelegateLayout>)self.collectionView.delegate;
if ([delegate respondsToSelector:@selector(collectionView:layout:customizedInitialLayoutAttributes:atIndexPath:)]) {
return [delegate collectionView:self.collectionView
layout:self
customizedInitialLayoutAttributes:attributes
atIndexPath:itemIndexPath];
}
return attributes;
}
- (UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingItemAtIndexPath:(NSIndexPath *)itemIndexPath{
UICollectionViewLayoutAttributes *attributes = [super finalLayoutAttributesForDisappearingItemAtIndexPath:itemIndexPath];
id<IGListCollectionViewDelegateLayout> delegate = (id<IGListCollectionViewDelegateLayout>)self.collectionView.delegate;
if ([delegate respondsToSelector:@selector(collectionView:layout:customizedFinalLayoutAttributes:atIndexPath:)]) {
return [delegate collectionView:self.collectionView
layout:self
customizedFinalLayoutAttributes:attributes
atIndexPath:itemIndexPath];
}
return attributes;
}
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
IGAssertMainThread();

View file

@ -14,6 +14,7 @@
#import <IGListKit/IGListScrollDelegate.h>
#import <IGListKit/IGListSupplementaryViewSource.h>
#import <IGListKit/IGListWorkingRangeDelegate.h>
#import <IGListKit/IGListTransitionDelegate.h>
NS_ASSUME_NONNULL_BEGIN
@ -200,6 +201,15 @@ NS_SWIFT_NAME(ListSectionController)
*/
@property (nonatomic, weak, nullable) id <IGListScrollDelegate> scrollDelegate;
/**
An object that handles transition events for the section controller. Can be `nil`.
@return An object that conforms to `IGListTransitionDelegat` or `nil`.
@note You may wish to return `self` if your section controller implements this protocol.
*/
@property (nonatomic, weak, nullable) id<IGListTransitionDelegate> transitionDelegate;
@end
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,36 @@
/**
* 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.
*/
/**
Conform to `IGListTransitionDelegate` to provide customized layout information for a collection view.
*/
@protocol IGListTransitionDelegate
/**
Asks the delegate to customize and return the starting layout information for an item being inserted into the collection view.
@param listAdapter The adapter controlling the list.
@param attributes The starting layout information for an item being inserted into the collection view.
@param sectionController The section controller to perform the transition on.
@param index The index of the item being inserted.
*/
- (UICollectionViewLayoutAttributes *)listAdapter:(IGListAdapter *)listAdapter customizedInitialLayoutAttributes:(UICollectionViewLayoutAttributes *)attributes sectionController:(IGListSectionController *)sectionController atIndex:(NSInteger)index;
/**
Asks the delegate to customize and return the final layout information for an item that is about to be removed from the collection view.
@param listAdapter The adapter controlling the list.
@param attributes The final layout information for an item that is about to be removed from the collection view.
@param sectionController The section controller to perform the transition on.
@param index The index of the item being deleted.
*/
- (UICollectionViewLayoutAttributes *)listAdapter:(IGListAdapter *)listAdapter customizedFinalLayoutAttributes:(UICollectionViewLayoutAttributes *)attributes sectionController:(IGListSectionController *)sectionController atIndex:(NSInteger)index;
@end

View file

@ -10,10 +10,11 @@
#import <UIKit/UIKit.h>
#import <IGListKit/IGListAdapter.h>
#import <IGListKit/IGListCollectionViewDelegateLayout.h>
@interface IGListAdapter (UICollectionView)
<
UICollectionViewDataSource,
UICollectionViewDelegateFlowLayout
IGListCollectionViewDelegateLayout
>
@end

View file

@ -211,4 +211,34 @@
return [self sizeForSupplementaryViewOfKind:UICollectionElementKindSectionFooter atIndexPath:indexPath];
}
#pragma mark - IGListCollectionViewDelegateLayout
- (UICollectionViewLayoutAttributes *)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout*)collectionViewLayout
customizedInitialLayoutAttributes:(UICollectionViewLayoutAttributes *)attributes
atIndexPath:(NSIndexPath *)indexPath {
IGListSectionController *sectionController = [self sectionControllerForSection:indexPath.section];
if (sectionController.transitionDelegate) {
return [sectionController.transitionDelegate listAdapter:self
customizedInitialLayoutAttributes:attributes
sectionController:sectionController
atIndex:indexPath.item];
}
return attributes;
}
- (UICollectionViewLayoutAttributes *)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout*)collectionViewLayout
customizedFinalLayoutAttributes:(UICollectionViewLayoutAttributes *)attributes
atIndexPath:(NSIndexPath *)indexPath {
IGListSectionController *sectionController = [self sectionControllerForSection:indexPath.section];
if (sectionController.transitionDelegate) {
return [sectionController.transitionDelegate listAdapter:self
customizedFinalLayoutAttributes:attributes
sectionController:sectionController
atIndex:indexPath.item];
}
return attributes;
}
@end

View file

@ -10,6 +10,7 @@
#import "IGListAdapterProxy.h"
#import <IGListKit/IGListAssert.h>
#import "IGListCollectionViewDelegateLayout.h"
/**
Define messages that you want the IGListAdapter object to intercept. Pattern copied from
@ -34,7 +35,10 @@ static BOOL isInterceptedSelector(SEL sel) {
sel == @selector(scrollViewDidScroll:) ||
sel == @selector(scrollViewWillBeginDragging:) ||
sel == @selector(scrollViewDidEndDragging:willDecelerate:) ||
sel == @selector(scrollViewDidEndDecelerating:)
sel == @selector(scrollViewDidEndDecelerating:) ||
// IGListCollectionViewDelegateLayout
sel == @selector(collectionView:layout:customizedInitialLayoutAttributes:atIndexPath:) ||
sel == @selector(collectionView:layout:customizedFinalLayoutAttributes:atIndexPath:)
);
}