最近先来有空,写了一个多页面滑动的框架,先上图:
思路: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];
}
-(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