598 lines
25 KiB
Mathematica
598 lines
25 KiB
Mathematica
|
|
//
|
|||
|
|
// JXPagerListContainerView.m
|
|||
|
|
// JXCategoryView
|
|||
|
|
//
|
|||
|
|
// Created by jiaxin on 2018/9/12.
|
|||
|
|
// Copyright © 2018年 jiaxin. All rights reserved.
|
|||
|
|
//
|
|||
|
|
|
|||
|
|
#import "JXPagerListContainerView.h"
|
|||
|
|
#import <objc/runtime.h>
|
|||
|
|
|
|||
|
|
@interface JXPagerListContainerScrollView: UIScrollView <UIGestureRecognizerDelegate>
|
|||
|
|
@property (nonatomic, assign, getter=isCategoryNestPagingEnabled) BOOL categoryNestPagingEnabled;
|
|||
|
|
@end
|
|||
|
|
@implementation JXPagerListContainerScrollView
|
|||
|
|
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
|
|||
|
|
if (self.isCategoryNestPagingEnabled) {
|
|||
|
|
if ([gestureRecognizer isMemberOfClass:NSClassFromString(@"UIScrollViewPanGestureRecognizer")]) {
|
|||
|
|
CGFloat velocityX = [(UIPanGestureRecognizer *)gestureRecognizer velocityInView:gestureRecognizer.view].x;
|
|||
|
|
//x大于0就是往右滑
|
|||
|
|
if (velocityX > 0) {
|
|||
|
|
if (self.contentOffset.x == 0) {
|
|||
|
|
return NO;
|
|||
|
|
}
|
|||
|
|
}else if (velocityX < 0) {
|
|||
|
|
//x小于0就是往左滑
|
|||
|
|
if (self.contentOffset.x + self.bounds.size.width == self.contentSize.width) {
|
|||
|
|
return NO;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return YES;
|
|||
|
|
}
|
|||
|
|
@end
|
|||
|
|
|
|||
|
|
@interface JXPagerListContainerCollectionView: UICollectionView <UIGestureRecognizerDelegate>
|
|||
|
|
@property (nonatomic, assign, getter=isCategoryNestPagingEnabled) BOOL categoryNestPagingEnabled;
|
|||
|
|
@end
|
|||
|
|
@implementation JXPagerListContainerCollectionView
|
|||
|
|
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
|
|||
|
|
if (self.isCategoryNestPagingEnabled) {
|
|||
|
|
if ([gestureRecognizer isMemberOfClass:NSClassFromString(@"UIScrollViewPanGestureRecognizer")]) {
|
|||
|
|
CGFloat velocityX = [(UIPanGestureRecognizer *)gestureRecognizer velocityInView:gestureRecognizer.view].x;
|
|||
|
|
//x大于0就是往右滑
|
|||
|
|
if (velocityX > 0) {
|
|||
|
|
if (self.contentOffset.x == 0) {
|
|||
|
|
return NO;
|
|||
|
|
}
|
|||
|
|
}else if (velocityX < 0) {
|
|||
|
|
//x小于0就是往左滑
|
|||
|
|
if (self.contentOffset.x + self.bounds.size.width == self.contentSize.width) {
|
|||
|
|
return NO;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return YES;
|
|||
|
|
}
|
|||
|
|
@end
|
|||
|
|
|
|||
|
|
@interface JXPagerListContainerViewController : UIViewController
|
|||
|
|
@property (copy) void(^viewWillAppearBlock)(void);
|
|||
|
|
@property (copy) void(^viewDidAppearBlock)(void);
|
|||
|
|
@property (copy) void(^viewWillDisappearBlock)(void);
|
|||
|
|
@property (copy) void(^viewDidDisappearBlock)(void);
|
|||
|
|
@end
|
|||
|
|
|
|||
|
|
@implementation JXPagerListContainerViewController
|
|||
|
|
- (void)dealloc
|
|||
|
|
{
|
|||
|
|
self.viewWillAppearBlock = nil;
|
|||
|
|
self.viewDidAppearBlock = nil;
|
|||
|
|
self.viewWillDisappearBlock = nil;
|
|||
|
|
self.viewDidDisappearBlock = nil;
|
|||
|
|
}
|
|||
|
|
- (void)viewWillAppear:(BOOL)animated {
|
|||
|
|
[super viewWillAppear:animated];
|
|||
|
|
self.viewWillAppearBlock();
|
|||
|
|
}
|
|||
|
|
- (void)viewDidAppear:(BOOL)animated {
|
|||
|
|
[super viewDidAppear:animated];
|
|||
|
|
self.viewDidAppearBlock();
|
|||
|
|
}
|
|||
|
|
- (void)viewWillDisappear:(BOOL)animated {
|
|||
|
|
[super viewWillDisappear:animated];
|
|||
|
|
self.viewWillDisappearBlock();
|
|||
|
|
}
|
|||
|
|
- (void)viewDidDisappear:(BOOL)animated {
|
|||
|
|
[super viewDidDisappear:animated];
|
|||
|
|
self.viewDidDisappearBlock();
|
|||
|
|
}
|
|||
|
|
- (BOOL)shouldAutomaticallyForwardAppearanceMethods { return NO; }
|
|||
|
|
@end
|
|||
|
|
|
|||
|
|
@interface JXPagerListContainerView () <UIScrollViewDelegate, UICollectionViewDelegate, UICollectionViewDataSource>
|
|||
|
|
@property (nonatomic, weak) id<JXPagerListContainerViewDelegate> delegate;
|
|||
|
|
@property (nonatomic, strong) UIScrollView *scrollView;
|
|||
|
|
@property (nonatomic, assign) NSInteger currentIndex;
|
|||
|
|
@property (nonatomic, strong) NSMutableDictionary <NSNumber *, id<JXPagerViewListViewDelegate>> *validListDict;
|
|||
|
|
@property (nonatomic, assign) NSInteger willAppearIndex;
|
|||
|
|
@property (nonatomic, assign) NSInteger willDisappearIndex;
|
|||
|
|
@property (nonatomic, strong) UICollectionView *collectionView;
|
|||
|
|
@property (nonatomic, strong) JXPagerListContainerViewController *containerVC;
|
|||
|
|
@end
|
|||
|
|
|
|||
|
|
@implementation JXPagerListContainerView
|
|||
|
|
|
|||
|
|
- (instancetype)initWithType:(JXPagerListContainerType)type delegate:(id<JXPagerListContainerViewDelegate>)delegate{
|
|||
|
|
self = [super initWithFrame:CGRectZero];
|
|||
|
|
if (self) {
|
|||
|
|
_containerType = type;
|
|||
|
|
_delegate = delegate;
|
|||
|
|
_validListDict = [NSMutableDictionary dictionary];
|
|||
|
|
_willAppearIndex = -1;
|
|||
|
|
_willDisappearIndex = -1;
|
|||
|
|
_initListPercent = 0.01;
|
|||
|
|
[self initializeViews];
|
|||
|
|
}
|
|||
|
|
return self;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
- (void)initializeViews {
|
|||
|
|
_listCellBackgroundColor = [UIColor whiteColor];
|
|||
|
|
_containerVC = [[JXPagerListContainerViewController alloc] init];
|
|||
|
|
self.containerVC.view.backgroundColor = [UIColor clearColor];
|
|||
|
|
[self addSubview:self.containerVC.view];
|
|||
|
|
__weak typeof(self) weakSelf = self;
|
|||
|
|
self.containerVC.viewWillAppearBlock = ^{
|
|||
|
|
[weakSelf listWillAppear:weakSelf.currentIndex];
|
|||
|
|
};
|
|||
|
|
self.containerVC.viewDidAppearBlock = ^{
|
|||
|
|
[weakSelf listDidAppear:weakSelf.currentIndex];
|
|||
|
|
};
|
|||
|
|
self.containerVC.viewWillDisappearBlock = ^{
|
|||
|
|
[weakSelf listWillDisappear:weakSelf.currentIndex];
|
|||
|
|
};
|
|||
|
|
self.containerVC.viewDidDisappearBlock = ^{
|
|||
|
|
[weakSelf listDidDisappear:weakSelf.currentIndex];
|
|||
|
|
};
|
|||
|
|
if (self.containerType == JXPagerListContainerType_ScrollView) {
|
|||
|
|
if (self.delegate &&
|
|||
|
|
[self.delegate respondsToSelector:@selector(scrollViewClassInlistContainerView:)] &&
|
|||
|
|
[[self.delegate scrollViewClassInlistContainerView:self] isKindOfClass:object_getClass([UIScrollView class])]) {
|
|||
|
|
_scrollView = (UIScrollView *)[[[self.delegate scrollViewClassInlistContainerView:self] alloc] init];
|
|||
|
|
}else {
|
|||
|
|
_scrollView = [[JXPagerListContainerScrollView alloc] init];
|
|||
|
|
}
|
|||
|
|
self.scrollView.backgroundColor = [UIColor clearColor];
|
|||
|
|
self.scrollView.delegate = self;
|
|||
|
|
self.scrollView.pagingEnabled = YES;
|
|||
|
|
self.scrollView.showsHorizontalScrollIndicator = NO;
|
|||
|
|
self.scrollView.showsVerticalScrollIndicator = NO;
|
|||
|
|
self.scrollView.scrollsToTop = NO;
|
|||
|
|
self.scrollView.bounces = NO;
|
|||
|
|
if (@available(iOS 11.0, *)) {
|
|||
|
|
self.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
|
|||
|
|
}
|
|||
|
|
[self.containerVC.view addSubview:self.scrollView];
|
|||
|
|
}else {
|
|||
|
|
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
|
|||
|
|
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
|
|||
|
|
layout.minimumLineSpacing = 0;
|
|||
|
|
layout.minimumInteritemSpacing = 0;
|
|||
|
|
if (self.delegate &&
|
|||
|
|
[self.delegate respondsToSelector:@selector(scrollViewClassInlistContainerView:)] &&
|
|||
|
|
[[self.delegate scrollViewClassInlistContainerView:self] isKindOfClass:object_getClass([UICollectionView class])]) {
|
|||
|
|
_collectionView = (UICollectionView *)[[[self.delegate scrollViewClassInlistContainerView:self] alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
|
|||
|
|
}else {
|
|||
|
|
_collectionView = [[JXPagerListContainerCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
|
|||
|
|
}
|
|||
|
|
self.collectionView.backgroundColor = [UIColor clearColor];
|
|||
|
|
self.collectionView.pagingEnabled = YES;
|
|||
|
|
self.collectionView.showsHorizontalScrollIndicator = NO;
|
|||
|
|
self.collectionView.showsVerticalScrollIndicator = NO;
|
|||
|
|
self.collectionView.scrollsToTop = NO;
|
|||
|
|
self.collectionView.bounces = NO;
|
|||
|
|
self.collectionView.dataSource = self;
|
|||
|
|
self.collectionView.delegate = self;
|
|||
|
|
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cell"];
|
|||
|
|
if (@available(iOS 10.0, *)) {
|
|||
|
|
self.collectionView.prefetchingEnabled = NO;
|
|||
|
|
}
|
|||
|
|
if (@available(iOS 11.0, *)) {
|
|||
|
|
self.collectionView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
|
|||
|
|
}
|
|||
|
|
[self.containerVC.view addSubview:self.collectionView];
|
|||
|
|
//让外部统一访问scrollView
|
|||
|
|
_scrollView = _collectionView;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
- (void)willMoveToSuperview:(UIView *)newSuperview {
|
|||
|
|
[super willMoveToSuperview:newSuperview];
|
|||
|
|
|
|||
|
|
UIResponder *next = newSuperview;
|
|||
|
|
while (next != nil) {
|
|||
|
|
if ([next isKindOfClass:[UIViewController class]]) {
|
|||
|
|
[((UIViewController *)next) addChildViewController:self.containerVC];
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
next = next.nextResponder;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
- (void)layoutSubviews {
|
|||
|
|
[super layoutSubviews];
|
|||
|
|
|
|||
|
|
self.containerVC.view.frame = self.bounds;
|
|||
|
|
if (self.containerType == JXPagerListContainerType_ScrollView) {
|
|||
|
|
if (CGRectEqualToRect(self.scrollView.frame, CGRectZero) || !CGSizeEqualToSize(self.scrollView.bounds.size, self.bounds.size)) {
|
|||
|
|
self.scrollView.frame = self.bounds;
|
|||
|
|
self.scrollView.contentSize = CGSizeMake(self.scrollView.bounds.size.width*[self.delegate numberOfListsInlistContainerView:self], self.scrollView.bounds.size.height);
|
|||
|
|
[_validListDict enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull index, id<JXPagerViewListViewDelegate> _Nonnull list, BOOL * _Nonnull stop) {
|
|||
|
|
[list listView].frame = CGRectMake(index.intValue*self.scrollView.bounds.size.width, 0, self.scrollView.bounds.size.width, self.scrollView.bounds.size.height);
|
|||
|
|
}];
|
|||
|
|
self.scrollView.contentOffset = CGPointMake(self.currentIndex*self.scrollView.bounds.size.width, 0);
|
|||
|
|
}else {
|
|||
|
|
self.scrollView.frame = self.bounds;
|
|||
|
|
self.scrollView.contentSize = CGSizeMake(self.scrollView.bounds.size.width*[self.delegate numberOfListsInlistContainerView:self], self.scrollView.bounds.size.height);
|
|||
|
|
}
|
|||
|
|
}else {
|
|||
|
|
if (CGRectEqualToRect(self.collectionView.frame, CGRectZero) || !CGSizeEqualToSize(self.collectionView.bounds.size, self.bounds.size)) {
|
|||
|
|
self.collectionView.frame = self.bounds;
|
|||
|
|
[self.collectionView.collectionViewLayout invalidateLayout];
|
|||
|
|
[self.collectionView reloadData];
|
|||
|
|
[self.collectionView setContentOffset:CGPointMake(self.collectionView.bounds.size.width*self.currentIndex, 0) animated:NO];
|
|||
|
|
}else {
|
|||
|
|
self.collectionView.frame = self.bounds;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
- (void)setinitListPercent:(CGFloat)initListPercent {
|
|||
|
|
_initListPercent = initListPercent;
|
|||
|
|
if (initListPercent <= 0 || initListPercent >= 1) {
|
|||
|
|
NSAssert(NO, @"initListPercent值范围为开区间(0,1),即不包括0和1");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
- (void)setCategoryNestPagingEnabled:(BOOL)categoryNestPagingEnabled {
|
|||
|
|
_categoryNestPagingEnabled = categoryNestPagingEnabled;
|
|||
|
|
if ([self.scrollView isKindOfClass:[JXPagerListContainerScrollView class]]) {
|
|||
|
|
((JXPagerListContainerScrollView *)self.scrollView).categoryNestPagingEnabled = categoryNestPagingEnabled;
|
|||
|
|
}else if ([self.scrollView isKindOfClass:[JXPagerListContainerCollectionView class]]) {
|
|||
|
|
((JXPagerListContainerCollectionView *)self.scrollView).categoryNestPagingEnabled = categoryNestPagingEnabled;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#pragma mark - UICollectionViewDelegate, UICollectionViewDataSource
|
|||
|
|
|
|||
|
|
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
|
|||
|
|
return [self.delegate numberOfListsInlistContainerView:self];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
|
|||
|
|
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];
|
|||
|
|
cell.contentView.backgroundColor = self.listCellBackgroundColor;
|
|||
|
|
for (UIView *subview in cell.contentView.subviews) {
|
|||
|
|
[subview removeFromSuperview];
|
|||
|
|
}
|
|||
|
|
id<JXPagerViewListViewDelegate> list = _validListDict[@(indexPath.item)];
|
|||
|
|
if (list != nil) {
|
|||
|
|
//fixme:如果list是UIViewController,如果这里的frame修改是`[list listView].frame = cell.bounds;`。那么就必须给list vc添加如下代码:
|
|||
|
|
//- (void)loadView {
|
|||
|
|
// self.view = [[UIView alloc] init];
|
|||
|
|
//}
|
|||
|
|
//所以,总感觉是把UIViewController当做普通view使用,导致了系统内部的bug。所以,缓兵之计就是用下面的方法,暂时解决问题。
|
|||
|
|
if ([list isKindOfClass:[UIViewController class]]) {
|
|||
|
|
[list listView].frame = cell.contentView.bounds;
|
|||
|
|
} else {
|
|||
|
|
[list listView].frame = cell.bounds;
|
|||
|
|
}
|
|||
|
|
[cell.contentView addSubview:[list listView]];
|
|||
|
|
}
|
|||
|
|
return cell;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
|
|||
|
|
return self.bounds.size;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#pragma mark - UIScrollViewDelegate
|
|||
|
|
|
|||
|
|
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
|
|||
|
|
if (self.delegate && [self.delegate respondsToSelector:@selector(listContainerViewDidScroll:)]) {
|
|||
|
|
[self.delegate listContainerViewDidScroll:scrollView];
|
|||
|
|
}
|
|||
|
|
if (!scrollView.isDragging && !scrollView.isTracking && !scrollView.isDecelerating) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
CGFloat ratio = scrollView.contentOffset.x/scrollView.bounds.size.width;
|
|||
|
|
NSInteger maxCount = round(scrollView.contentSize.width/scrollView.bounds.size.width);
|
|||
|
|
NSInteger leftIndex = floorf(ratio);
|
|||
|
|
leftIndex = MAX(0, MIN(maxCount - 1, leftIndex));
|
|||
|
|
NSInteger rightIndex = leftIndex + 1;
|
|||
|
|
if (ratio < 0 || rightIndex >= maxCount) {
|
|||
|
|
[self listDidAppearOrDisappear:scrollView];
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
CGFloat remainderRatio = ratio - leftIndex;
|
|||
|
|
if (rightIndex == self.currentIndex) {
|
|||
|
|
//当前选中的在右边,用户正在从右边往左边滑动
|
|||
|
|
if (self.validListDict[@(leftIndex)] == nil && remainderRatio < (1 - self.initListPercent)) {
|
|||
|
|
[self initListIfNeededAtIndex:leftIndex];
|
|||
|
|
}else if (self.validListDict[@(leftIndex)] != nil) {
|
|||
|
|
if (self.willAppearIndex == -1) {
|
|||
|
|
self.willAppearIndex = leftIndex;
|
|||
|
|
[self listWillAppear:self.willAppearIndex];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (self.willDisappearIndex == -1) {
|
|||
|
|
self.willDisappearIndex = rightIndex;
|
|||
|
|
[self listWillDisappear:self.willDisappearIndex];
|
|||
|
|
}
|
|||
|
|
}else {
|
|||
|
|
//当前选中的在左边,用户正在从左边往右边滑动
|
|||
|
|
if (self.validListDict[@(rightIndex)] == nil && remainderRatio > self.initListPercent) {
|
|||
|
|
[self initListIfNeededAtIndex:rightIndex];
|
|||
|
|
}else if (self.validListDict[@(rightIndex)] != nil) {
|
|||
|
|
if (self.willAppearIndex == -1) {
|
|||
|
|
self.willAppearIndex = rightIndex;
|
|||
|
|
[self listWillAppear:self.willAppearIndex];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (self.willDisappearIndex == -1) {
|
|||
|
|
self.willDisappearIndex = leftIndex;
|
|||
|
|
[self listWillDisappear:self.willDisappearIndex];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
[self listDidAppearOrDisappear:scrollView];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
|
|||
|
|
if (self.willDisappearIndex != -1) {
|
|||
|
|
[self listWillAppear:self.willDisappearIndex];
|
|||
|
|
[self listWillDisappear:self.willAppearIndex];
|
|||
|
|
[self listDidAppear:self.willDisappearIndex];
|
|||
|
|
[self listDidDisappear:self.willAppearIndex];
|
|||
|
|
self.willDisappearIndex = -1;
|
|||
|
|
self.willAppearIndex = -1;
|
|||
|
|
}
|
|||
|
|
if (self.delegate && [self.delegate respondsToSelector:@selector(listContainerViewWDidEndScroll:)]) {
|
|||
|
|
[self.delegate listContainerViewWDidEndScroll:self];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
|
|||
|
|
if (self.delegate && [self.delegate respondsToSelector:@selector(listContainerViewWillBeginDragging:)]) {
|
|||
|
|
[self.delegate listContainerViewWillBeginDragging:self];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
|
|||
|
|
if (!decelerate) {
|
|||
|
|
if (self.delegate && [self.delegate respondsToSelector:@selector(listContainerViewWDidEndScroll:)]) {
|
|||
|
|
[self.delegate listContainerViewWDidEndScroll:self];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {
|
|||
|
|
if (self.delegate && [self.delegate respondsToSelector:@selector(listContainerViewWDidEndScroll:)]) {
|
|||
|
|
[self.delegate listContainerViewWDidEndScroll:self];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#pragma mark - JXCategoryViewListContainer
|
|||
|
|
|
|||
|
|
- (UIScrollView *)contentScrollView {
|
|||
|
|
return self.scrollView;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
- (void)setDefaultSelectedIndex:(NSInteger)index {
|
|||
|
|
self.currentIndex = index;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
- (void)scrollingFromLeftIndex:(NSInteger)leftIndex toRightIndex:(NSInteger)rightIndex ratio:(CGFloat)ratio selectedIndex:(NSInteger)selectedIndex {
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
- (void)didClickSelectedItemAtIndex:(NSInteger)index {
|
|||
|
|
if (![self checkIndexValid:index]) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
self.willAppearIndex = -1;
|
|||
|
|
self.willDisappearIndex = -1;
|
|||
|
|
if (self.currentIndex != index) {
|
|||
|
|
[self listWillDisappear:self.currentIndex];
|
|||
|
|
[self listDidDisappear:self.currentIndex];
|
|||
|
|
[self listWillAppear:index];
|
|||
|
|
[self listDidAppear:index];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
- (void)reloadData {
|
|||
|
|
for (id<JXPagerViewListViewDelegate> list in _validListDict.allValues) {
|
|||
|
|
[[list listView] removeFromSuperview];
|
|||
|
|
if ([list isKindOfClass:[UIViewController class]]) {
|
|||
|
|
[(UIViewController *)list removeFromParentViewController];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
[_validListDict removeAllObjects];
|
|||
|
|
|
|||
|
|
if (self.containerType == JXPagerListContainerType_ScrollView) {
|
|||
|
|
self.scrollView.contentSize = CGSizeMake(self.scrollView.bounds.size.width*[self.delegate numberOfListsInlistContainerView:self], self.scrollView.bounds.size.height);
|
|||
|
|
}else {
|
|||
|
|
[self.collectionView reloadData];
|
|||
|
|
}
|
|||
|
|
[self listWillAppear:self.currentIndex];
|
|||
|
|
[self listDidAppear:self.currentIndex];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#pragma mark - Private
|
|||
|
|
|
|||
|
|
- (void)initListIfNeededAtIndex:(NSInteger)index {
|
|||
|
|
if (self.delegate && [self.delegate respondsToSelector:@selector(listContainerView:canInitListAtIndex:)]) {
|
|||
|
|
BOOL canInitList = [self.delegate listContainerView:self canInitListAtIndex:index];
|
|||
|
|
if (!canInitList) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
id<JXPagerViewListViewDelegate> list = _validListDict[@(index)];
|
|||
|
|
if (list != nil) {
|
|||
|
|
//列表已经创建好了
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
list = [self.delegate listContainerView:self initListForIndex:index];
|
|||
|
|
if ([list isKindOfClass:[UIViewController class]]) {
|
|||
|
|
[self.containerVC addChildViewController:(UIViewController *)list];
|
|||
|
|
}
|
|||
|
|
_validListDict[@(index)] = list;
|
|||
|
|
|
|||
|
|
switch (self.containerType) {
|
|||
|
|
case JXPagerListContainerType_ScrollView: {
|
|||
|
|
[list listView].frame = CGRectMake(index*self.scrollView.bounds.size.width, 0, self.scrollView.bounds.size.width, self.scrollView.bounds.size.height);
|
|||
|
|
[self.scrollView addSubview:[list listView]];
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
case JXPagerListContainerType_CollectionView: {
|
|||
|
|
UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:index inSection:0]];
|
|||
|
|
if (cell != nil) {
|
|||
|
|
for (UIView *subview in cell.contentView.subviews) {
|
|||
|
|
[subview removeFromSuperview];
|
|||
|
|
}
|
|||
|
|
[list listView].frame = cell.contentView.bounds;
|
|||
|
|
[cell.contentView addSubview:[list listView]];
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
- (void)listWillAppear:(NSInteger)index {
|
|||
|
|
if (![self checkIndexValid:index]) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
id<JXPagerViewListViewDelegate> list = _validListDict[@(index)];
|
|||
|
|
if (list != nil) {
|
|||
|
|
if (list && [list respondsToSelector:@selector(listWillAppear)]) {
|
|||
|
|
[list listWillAppear];
|
|||
|
|
}
|
|||
|
|
if ([list isKindOfClass:[UIViewController class]]) {
|
|||
|
|
UIViewController *listVC = (UIViewController *)list;
|
|||
|
|
[listVC beginAppearanceTransition:YES animated:NO];
|
|||
|
|
}
|
|||
|
|
}else {
|
|||
|
|
//当前列表未被创建(页面初始化或通过点击触发的listWillAppear)
|
|||
|
|
BOOL canInitList = YES;
|
|||
|
|
if (self.delegate && [self.delegate respondsToSelector:@selector(listContainerView:canInitListAtIndex:)]) {
|
|||
|
|
canInitList = [self.delegate listContainerView:self canInitListAtIndex:index];
|
|||
|
|
}
|
|||
|
|
if (canInitList) {
|
|||
|
|
id<JXPagerViewListViewDelegate> list = _validListDict[@(index)];
|
|||
|
|
if (list == nil) {
|
|||
|
|
list = [self.delegate listContainerView:self initListForIndex:index];
|
|||
|
|
if ([list isKindOfClass:[UIViewController class]]) {
|
|||
|
|
[self.containerVC addChildViewController:(UIViewController *)list];
|
|||
|
|
}
|
|||
|
|
_validListDict[@(index)] = list;
|
|||
|
|
}
|
|||
|
|
if (self.containerType == JXPagerListContainerType_ScrollView) {
|
|||
|
|
if ([list listView].superview == nil) {
|
|||
|
|
[list listView].frame = CGRectMake(index*self.scrollView.bounds.size.width, 0, self.scrollView.bounds.size.width, self.scrollView.bounds.size.height);
|
|||
|
|
[self.scrollView addSubview:[list listView]];
|
|||
|
|
|
|||
|
|
if (list && [list respondsToSelector:@selector(listWillAppear)]) {
|
|||
|
|
[list listWillAppear];
|
|||
|
|
}
|
|||
|
|
if ([list isKindOfClass:[UIViewController class]]) {
|
|||
|
|
UIViewController *listVC = (UIViewController *)list;
|
|||
|
|
[listVC beginAppearanceTransition:YES animated:NO];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}else {
|
|||
|
|
UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:index inSection:0]];
|
|||
|
|
for (UIView *subview in cell.contentView.subviews) {
|
|||
|
|
[subview removeFromSuperview];
|
|||
|
|
}
|
|||
|
|
[list listView].frame = cell.contentView.bounds;
|
|||
|
|
[cell.contentView addSubview:[list listView]];
|
|||
|
|
|
|||
|
|
if (list && [list respondsToSelector:@selector(listWillAppear)]) {
|
|||
|
|
[list listWillAppear];
|
|||
|
|
}
|
|||
|
|
if ([list isKindOfClass:[UIViewController class]]) {
|
|||
|
|
UIViewController *listVC = (UIViewController *)list;
|
|||
|
|
[listVC beginAppearanceTransition:YES animated:NO];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
- (void)listDidAppear:(NSInteger)index {
|
|||
|
|
if (![self checkIndexValid:index]) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
self.currentIndex = index;
|
|||
|
|
id<JXPagerViewListViewDelegate> list = _validListDict[@(index)];
|
|||
|
|
if (list && [list respondsToSelector:@selector(listDidAppear)]) {
|
|||
|
|
[list listDidAppear];
|
|||
|
|
}
|
|||
|
|
if ([list isKindOfClass:[UIViewController class]]) {
|
|||
|
|
UIViewController *listVC = (UIViewController *)list;
|
|||
|
|
[listVC endAppearanceTransition];
|
|||
|
|
}
|
|||
|
|
if (self.delegate && [self.delegate respondsToSelector:@selector(listContainerView:listDidAppearAtIndex:)]) {
|
|||
|
|
[self.delegate listContainerView:self listDidAppearAtIndex:index];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
- (void)listWillDisappear:(NSInteger)index {
|
|||
|
|
if (![self checkIndexValid:index]) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
id<JXPagerViewListViewDelegate> list = _validListDict[@(index)];
|
|||
|
|
if (list && [list respondsToSelector:@selector(listWillDisappear)]) {
|
|||
|
|
[list listWillDisappear];
|
|||
|
|
}
|
|||
|
|
if ([list isKindOfClass:[UIViewController class]]) {
|
|||
|
|
UIViewController *listVC = (UIViewController *)list;
|
|||
|
|
[listVC beginAppearanceTransition:NO animated:NO];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
- (void)listDidDisappear:(NSInteger)index {
|
|||
|
|
if (![self checkIndexValid:index]) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
id<JXPagerViewListViewDelegate> list = _validListDict[@(index)];
|
|||
|
|
if (list && [list respondsToSelector:@selector(listDidDisappear)]) {
|
|||
|
|
[list listDidDisappear];
|
|||
|
|
}
|
|||
|
|
if ([list isKindOfClass:[UIViewController class]]) {
|
|||
|
|
UIViewController *listVC = (UIViewController *)list;
|
|||
|
|
[listVC endAppearanceTransition];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
- (BOOL)checkIndexValid:(NSInteger)index {
|
|||
|
|
NSUInteger count = [self.delegate numberOfListsInlistContainerView:self];
|
|||
|
|
if (count <= 0 || index >= count) {
|
|||
|
|
return NO;
|
|||
|
|
}
|
|||
|
|
return YES;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
- (void)listDidAppearOrDisappear:(UIScrollView *)scrollView {
|
|||
|
|
CGFloat currentIndexPercent = scrollView.contentOffset.x/scrollView.bounds.size.width;
|
|||
|
|
if (self.willAppearIndex != -1 || self.willDisappearIndex != -1) {
|
|||
|
|
NSInteger disappearIndex = self.willDisappearIndex;
|
|||
|
|
NSInteger appearIndex = self.willAppearIndex;
|
|||
|
|
if (self.willAppearIndex > self.willDisappearIndex) {
|
|||
|
|
//将要出现的列表在右边
|
|||
|
|
if (currentIndexPercent >= self.willAppearIndex) {
|
|||
|
|
self.willDisappearIndex = -1;
|
|||
|
|
self.willAppearIndex = -1;
|
|||
|
|
[self listDidDisappear:disappearIndex];
|
|||
|
|
[self listDidAppear:appearIndex];
|
|||
|
|
}
|
|||
|
|
}else {
|
|||
|
|
//将要出现的列表在左边
|
|||
|
|
if (currentIndexPercent <= self.willAppearIndex) {
|
|||
|
|
self.willDisappearIndex = -1;
|
|||
|
|
self.willAppearIndex = -1;
|
|||
|
|
[self listDidDisappear:disappearIndex];
|
|||
|
|
[self listDidAppear:appearIndex];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
@end
|
|||
|
|
|
|||
|
|
|