一款优雅的竖直分页框架,含有下拉返回上一页,上拉进入下一页,有阻尼效果,支持pod导入

首先看下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];

demo

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值