首先看下demo的实现效果
本框架也是实践了苹果的重用思想,支持不同样式的页面之间的
切换,(不同的页码展示不同的页面)
核心逻辑:使用三个视图实现下拉和上拉效果,
上拉(或者下拉)之后立即返回原位,并刷新数据
刷新三个视图
- (void)reloadTopView
{
[self.topView removeFromSuperview];
[self.reuseViews addObject:self.topView];
NSInteger count = [self.dataSource numberOfViewForVerticalPageContainerView:self];
NSInteger index = MAX(0, self.currentIndex - 1);
if (index >= count) {
return;
}
TPVerticalPageViewCell *cell = [self.dataSource verticalPageView:self viewAtIndex:index];
cell.frame = CGRectMake(0, 0, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds));
[self.contentScrollView addSubview:cell];
self.topView = cell;
[self.reuseViews removeObject:self.topView];
}
- (void)reloadMiddleView
{
[self.middleView removeFromSuperview];
[self.reuseViews addObject:self.middleView];
NSInteger count = [self.dataSource numberOfViewForVerticalPageContainerView:self];
if (self.currentIndex >= count) {
return;
}
TPVerticalPageViewCell *cell = [self.dataSource verticalPageView:self viewAtIndex:self.currentIndex];
cell.frame = CGRectMake(0, CGRectGetHeight(self.bounds), CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds));
[self.contentScrollView addSubview:cell];
self.middleView = cell;
[self.reuseViews removeObject:self.middleView];
}
- (void)reloadBottomView
{
[self.bottomView removeFromSuperview];
[self.reuseViews addObject:self.bottomView];
NSInteger count = [self.dataSource numberOfViewForVerticalPageContainerView:self];
if (self.currentIndex + 1 >= count) {
return;
}
TPVerticalPageViewCell *cell = [self.dataSource verticalPageView:self viewAtIndex:MIN(self.currentIndex + 1, count - 1)];
cell.frame = CGRectMake(0, CGRectGetHeight(self.bounds) * 2, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds));
[self.contentScrollView addSubview:cell];
self.bottomView = cell;
[self.reuseViews removeObject:self.bottomView];
}
进入到下一页,返回到上一页
- (void)gotoNext
{
NSInteger count = 0;
if (self.dataSource &&
[self.dataSource respondsToSelector:@selector(numberOfViewForVerticalPageContainerView:)]) {
count = [self.dataSource numberOfViewForVerticalPageContainerView:self];
}
if (self.currentIndex >= count - 1) {
return;
}
self.currentIndex ++;
self.currentIndex = MIN(count - 1, self.currentIndex);
[UIView animateWithDuration:0.5 animations:^{
[self.contentScrollView setContentOffset:CGPointMake(0, CGRectGetHeight(self.bounds) * 2)];
} completion:^(BOOL finished) {
[self reloadAfterTranslation];
}];
}
- (void)pullToLast
{
self.currentIndex --;
self.currentIndex = MAX(0, self.currentIndex);
/// 翻到下一页之前,需要将下一页偏移量设置为0
[self.bottomView configContentOffset:0];
[UIView animateWithDuration:0.5 animations:^{
[self.contentScrollView setContentOffset:CGPointMake(0, 0)];
} completion:^(BOOL finished) {
[self reloadAfterTranslation];
}];
}
///移动过之后要恢复到原位,并且要在中间视图刷新之后,返回原位,
保证无缝贴合,避免闪动
在这里插入代码片- (void)reloadAfterTranslation
{
NSInteger count = [self.dataSource numberOfViewForVerticalPageContainerView:self];
if (self.currentIndex < count) {
///需要先刷新中间视图,这样保证我们返回到中间的时候,和上一个状态无缝贴合
[self reloadMiddleView];
}
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self.contentScrollView setContentOffset:CGPointMake(0, CGRectGetHeight(self.bounds))];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if (self.currentIndex - 1 >= 0 && count > self.currentIndex - 1) {
[self reloadTopView];
}
if (self.currentIndex + 1 < count) {
[self reloadBottomView];
}
if (self.delegate &&
[self.delegate respondsToSelector:@selector(moveBackMiddleAfterTranslation:)]) {
[self.delegate moveBackMiddleAfterTranslation:self];
}
});
});
}
支持pod 导入
pod ‘LBVerticalPageView’
使用方法
自定义单页视图继承于 TPVerticalPageViewCell
如:
@interface TPAskanswerSinglePageView : TPVerticalPageViewCell
@end
- (TPVerticalPageContainerView *)containerView
{
if (!_containerView) {
_containerView = [[TPVerticalPageContainerView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), CGRectGetHeight(self.view.bounds))];
[_containerView registerClass:[TPAskanswerSinglePageView class] forViewReuseIdentifier:NSStringFromClass([TPAskanswerSinglePageView class])];
_containerView.delegate = self;
_containerView.dataSource = self;
}
return _containerView;;
}
遵守协议 <TPVerticalPageContainerViewDelegate, TPVerticalPageContainerViewDataSource>
实现代理方法
- (NSInteger)numberOfViewForVerticalPageContainerView:(TPVerticalPageContainerView *)rollingView
{
return self.array.count;
}
- (TPVerticalPageViewCell *)verticalPageView:(TPVerticalPageContainerView *)rollingView viewAtIndex:(NSUInteger)index
{
TPAskanswerSinglePageView *view = [rollingView dequeueReusableCellWithIdentifier:NSStringFromClass([TPAskanswerSinglePageView class])];
NSArray *array = self.array[index];
[view updateWithModel:array];
return view;
}
刷新
[self.containerView reloadData];