iOS 多页面滑动

最近先来有空,写了一个多页面滑动的框架,先上图:

      

思路:1.标题使用UICollectionView实现,有两种模式,标题居中平均长度,另外一种模式是标题靠左

           2.下面的页面切换使用一个UIPageViewController


头文件

//
//  HRScrollPageController.h
//  多页滑动
//
//  Created by Chen Heren on 16/8/22.
//  Copyright (c) 2016年 Chen Heren. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface HRPageController : UIViewController

@property (nonatomic, strong) UIColor *titleBackgroundColor;  //标题栏背景颜色
@property (nonatomic, strong) UIColor *titleColor;  //标题颜色
@property (nonatomic, strong) UIColor *indicatorColor;  //标题选中指示器颜色
@property (nonatomic) BOOL isMiddle;    // 标题居中

-(instancetype)initWithControllers:(NSArray *)controllers andTitles:(NSArray *)titles;

-(instancetype)initWithControllers:(NSArray *)controllers andTitles:(NSArray *)titles isMiddle:(BOOL)isMiddle;

@end

私有属性:

#import "TitleViewCell.h"
#import "HRPageController.h"

#define kWidth [UIScreen mainScreen].bounds.size.width
#define kHeight [UIScreen mainScreen].bounds.size.height

static NSString *TitleCellIdentifier = @"TitleCell";

@interface HRPageController ()<UICollectionViewDataSource,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout,UIPageViewControllerDataSource,UIPageViewControllerDelegate>

@property (nonatomic, strong) NSArray *controllers; //子控制器
@property (nonatomic, strong) NSArray *titles;  //标题
@property (nonatomic) NSUInteger nextIndex; //即将切换到的页面序号
@property (nonatomic, strong) UICollectionView *titleCollectionView;    //标题列表
@property (nonatomic, strong) UIPageViewController *pageViewController; //实现多页面切换

@end


标题列表初始化

-(void)setupTitles{
    //设置状态栏view
    UIView *topView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, kWidth, 20)];
    topView.backgroundColor = self.titleBackgroundColor;
    [self.view addSubview:topView];
    
    //设置标题列表
    UICollectionViewFlowLayout *flow = [[UICollectionViewFlowLayout alloc]init];
    flow.scrollDirection = UICollectionViewScrollDirectionHorizontal;
    self.titleCollectionView.collectionViewLayout = flow;
    self.titleCollectionView =[[ UICollectionView alloc]initWithFrame:CGRectMake(0, 20, kWidth, 30) collectionViewLayout:flow];
    self.titleCollectionView.dataSource = self;
    self.titleCollectionView.delegate = self;
    self.titleCollectionView.allowsSelection = YES;
    self.titleCollectionView.backgroundColor = [UIColor whiteColor];
    [self.titleCollectionView registerNib:[UINib nibWithNibName:@"TitleViewCell" bundle:nil] forCellWithReuseIdentifier:TitleCellIdentifier];
    [self.view addSubview:self.titleCollectionView];
    
}
实现标题集合视图的先关代理

#pragma mark - UIColectionViewDataSource Delegate

-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
    return 1;
}

-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{

    return self.titles.count;
}

-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
    TitleViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:TitleCellIdentifier forIndexPath:indexPath];
    cell.titleLabel.text = self.titles[indexPath.item];
    cell.indicator.backgroundColor = self.indicatorColor;
    return cell;
}

#pragma mark - UICollectionViewLayout

-(CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section{
    return 0;
}

-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
    if (self.isMiddle == YES) { //标题居中模式
        return  CGSizeMake((kWidth-20)/(self.titles.count), self.titleCollectionView.frame.size.height);
    }else{  //靠左模式
        return CGSizeMake(40, self.titleCollectionView.frame.size.height);
    }
}


-(UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{
    return UIEdgeInsetsMake(0, 10, 0, 10);
}

#pragma mark - UICollectionView Deleaget

-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
    //清除标题选中状态,滑动切换时遗留的状态
    for (int i=0; i<self.titles.count; i++) {
        TitleViewCell *cell = (TitleViewCell *)[collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:i inSection:0]];
        cell.indicator.alpha = 0;
        
    }
    //设置选中cell状态
    TitleViewCell *cell = (TitleViewCell *)[collectionView cellForItemAtIndexPath:indexPath];
    cell.titleLabel.textColor = self.titleColor;
    cell.indicator.alpha = 1.0;
    //跳转到指定页面
    NSArray *initControllers = @[self.controllers[indexPath.item]];
    [self.pageViewController setViewControllers:initControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
    
}


视图切换初始化,也就是UIPageViewController的初始化

-(void)setupPageController{
    //
    self.pageViewController = [[UIPageViewController alloc]initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
    self.pageViewController.dataSource = self;
    self.pageViewController.delegate =self;
    self.pageViewController.view.frame = CGRectMake(0, 50, kWidth, kHeight-50);
    NSArray *initControllers = @[self.controllers[0]];
    [self.pageViewController setViewControllers:initControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
    [self addChildViewController:self.pageViewController];
    [self.view addSubview:self.pageViewController.view];
    
}
实现UIPageViewController相关代理

#pragma mark - UIPageViewConrtroller DatsSource delegate

-(UIViewController *)viewControllerAtIndex:(NSUInteger)index{
    if (index == NSNotFound || index >=self.controllers.count ) {
        return nil;
    }
    return self.controllers[index];
}

-(NSUInteger)indexOfViewController:(UIViewController *)viewController{
    return [self.controllers indexOfObject:viewController];
}

-(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController{
    
    NSUInteger index = [self indexOfViewController:viewController];
    
    if (index ==  NSNotFound ) {
        return nil;
    }
    
    //循环滑动
    if (index ==0 ) {
        return [self viewControllerAtIndex:(self.controllers.count-1)];
    }
    
    index --;
    
    return [self viewControllerAtIndex:index];
}

-(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController{
    
    NSUInteger index = [self indexOfViewController:viewController];
    
    if (index == NSNotFound ) {
        return nil;
    }
    
    index ++;
    
    //循环滑动
    if (index == self.controllers.count) {
        return [self viewControllerAtIndex:0];
    }
    
    if (index > self.controllers.count) {
        return nil;
    }
    
    return [self viewControllerAtIndex:index];
}


-(void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray *)pendingViewControllers{
    
    //纪录当前序号
    NSUInteger index = [self indexOfViewController:pendingViewControllers.firstObject];
    self.nextIndex = index;
    
}


-(void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed{
    if (completed) {
        
        //隐藏上次标题的指示器
        NSUInteger index = [self indexOfViewController:previousViewControllers.firstObject];
        [self deselectTitle:index];
        
        //显示当前标题指示器
        [self selectedTitle:self.nextIndex];
        

    }


}

编写两个方法:标题cell选中和取消的状态

//设置标题选中状态,一定要在视图加载之后设置
-(void)selectedTitle:(NSUInteger)index{
    NSIndexPath *selectedPath = [NSIndexPath indexPathForItem:index inSection:0];
    [self.titleCollectionView selectItemAtIndexPath:selectedPath animated:NO scrollPosition:UICollectionViewScrollPositionCenteredHorizontally];
    TitleViewCell *cell = (TitleViewCell *)[self.titleCollectionView cellForItemAtIndexPath:selectedPath];
    cell.indicator.alpha = 1.0;
    cell.titleLabel.textColor = self.titleColor;
    [cell setSelected:YES];
}

//标题取消选中
-(void)deselectTitle:(NSUInteger)index{
    NSIndexPath *deselectedPath = [NSIndexPath indexPathForItem:index inSection:0];
    [self.titleCollectionView deselectItemAtIndexPath:deselectedPath animated:NO];
    TitleViewCell *cell = (TitleViewCell *)[self.titleCollectionView cellForItemAtIndexPath:deselectedPath];
    cell.indicator.alpha = 0;
    cell.titleLabel.textColor = [UIColor grayColor];
    [cell setSelected:NO];
}

%%%最后实现初始化

-(instancetype)initWithControllers:(NSArray *)controllers andTitles:(NSArray *)titles{
    
    self = [super init];
    
    if (self) {
        
        self.controllers = [[NSArray alloc]initWithArray:controllers];
        self.titles = [[NSArray alloc]initWithArray:titles];
        
        self.isMiddle = YES;
        self.titleBackgroundColor = [UIColor whiteColor];
        self.titleColor = [UIColor blackColor];
        self.indicatorColor = [UIColor greenColor];
        
        [self setupPageController];
        [self setupTitles];
    }
    
    return self;
    
}

注:这算是第一个版本,因为加入childControllers较多的话,采取上文的写法是一下子全部加载,比较耗内存

打算第二个版本采用代理的方法  叫 :HRPageControllerDatasourceDelegate 哈哈!!!


demo传送门:

https://git.oschina.net/heren/HRPageController.git






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

机器人开发者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值