分页控制器加载工具XXPageMenuController

很久不写简书了,除了懒之外也肯定不能说项目很紧工作很忙.

今天更新一个很久之前写过的分页加载控制器,为什么要更新这个分页加载这么常见的多如牛毛的轮子...主要是现在几个主流 APP 都有关于这个分页滑动效果的实现,我见过的有:京东,微博,还有爱奇艺,其他的暂时没发现哈.

基本效果:

更新后的主要滑动效果如下:


donghua.gif

donghua1.gif

传送门: Github
(Github上的 readme 并没有更新,看简书这里就行.)

对于实现以及更多的样式感兴趣的话可以继续往下看.

主要实现:

以上是一些基本效果的实现.大体就是分页条的下划线随着滑动手势的执行所实现的一个稍微有点酷的动画效果.其实实现起来也不麻烦.只要注意切分滑动状态,就可以根据不同状态下的滑动现象很容易分析出实现思路.

最主要的过程就是,将滑动的过程切分为:左滑和右滑 两个部分,再分别将左滑和右滑两个部分切分为:前半部分下划线长度↑(增加)和后半部分下划线长度↓(减少). 总共四中状态,分别针对四中状态监听 - scrollViewDidScroll:做不同的长度处理,同时在这个过程中,动态的去修改下划线的 center.x 位置就能够实现这个效果.

上一下实现这个过程的核心代码:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
              CGFloat changedW = _pageCellW*2*fabs(x-ScreenW*index) / ScreenW;

                _line.frame = CGRectMake(0, _pageBarHeight-_lineHeight,  _lineWidth+changedW, _lineHeight);
                
                CGFloat centerX;
                if (toLeft) {
                    if ((x-ScreenW*index) > 0) { //未过半屏: 过半屏之后因为index = (x + ScreenW*0.5) / ScreenW;  所以 index 值会+1
                        centerX = index * _pageCellW + _pageCellW/2 + changedW/2;
                    }else{ //划过半屏
                        centerX = index * _pageCellW + _pageCellW/2 - changedW/2;
                    }
                }else{
                    if ((x-ScreenW*index) < 0) { //未过半屏
                        centerX = index * _pageCellW + _pageCellW/2 - changedW/2;
                    }else{  //划过半屏
                        centerX = index * _pageCellW + _pageCellW/2 + changedW/2;
                    }
                }
                _line.center = CGPointMake(centerX, _pageBarHeight-_lineHeight/2);
            }
}

扩展了非常多的实用性的功能,调用方式有以下几种都可以实现:

/**
 创建分页控制器 : 自动创建全部控制器(方式一)
 
 @param titlesArray 标题数组
 @param controllers 控制器数组
 @param onNavigationBar 分页栏是否放在控制器导航栏上
 @return 栈顶控制管理器
 */
- (instancetype)initWithTitles:(NSArray *)titlesArray controllers:(NSArray *)controllers onNavigationBar:(BOOL)onNavigationBar;

/**
 *  创建分页控制器 : 滑动到相应 index 位置时才去创建相应控制器,此方式不太好传参(方式二)
 *
 *  @param titlesArray      标题数组
 *  @param controllersClass 要创建的控制器类名数组
 *  @param onNavigationBar 分页栏是否放在控制器导航栏上
 *  @return 栈顶控制管理器
 */
- (instancetype)initWithTitles:(NSArray *)titlesArray controllersClass:(NSArray *)controllersClass onNavigationBar:(BOOL)onNavigationBar;

使用:

可以用方式1初始化,传进去实例化好的控制器对象集合,也可以用方式2初始化,传进去未实例化的控制器类集合,等滑动到相应位置时再去动态实例化,可以自由选择实例化方式,选择是否将分页条加载于导航条上,并且已经做了关于 iPhone X 的适配.

同时,实际调用的时候,可以直接push-->XXPageMenuController, 或者将PageMenu添加到 parentViewController/view, 套一层parentViewController以实现导航条上更全面的设置,如果项目有需求的话.

if (indexPath.section == 0) {
        
        XXPageMenuController *pageMenuController = nil;
        
        switch (indexPath.row) {
            case 0:
            {
                NSMutableArray *controllersClass = [NSMutableArray array];
                [titles enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                    [controllersClass addObject:[PageCell2Controller class]];
                }];
                pageMenuController = [[XXPageMenuController alloc] initWithTitles:titles controllersClass:controllersClass onNavigationBar:YES];
            }
                break;
            case 1:
            {
                NSMutableArray *controllers = [NSMutableArray array];
                [titles enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                    [controllers addObject:[PageCell1Controller new]];
                }];
                pageMenuController = [[XXPageMenuController alloc] initWithTitles:titles controllers:controllers onNavigationBar:NO];
                pageMenuController.titleColor = [UIColor whiteColor];
                pageMenuController.pageBarBgColor = [UIColor grayColor];
                pageMenuController.pageBarHeight = 44;
                pageMenuController.lineColor = [UIColor orangeColor];
            }
                break;
            case 2:
            {
                pageMenuController = [[XXPageMenuController alloc] initWithTitles:titles2 controllersClass:@[[PageCell2Controller class],[PageCell2Controller class],[PageCell2Controller class],[PageCell2Controller class]] onNavigationBar:YES];
            }
                break;
            default:
            {
                pageMenuController = [[XXPageMenuController alloc] initWithTitles:titles2 controllersClass:@[[PageCell1Controller class],[PageCell1Controller class],[PageCell1Controller class],[PageCell2Controller class]] onNavigationBar:NO];
            }
                break;
        }
        
        [self.navigationController pushViewController:pageMenuController animated:YES];
        
    }else{
        switch (indexPath.row) {
            case 0:
                [self.navigationController pushViewController:[Parent1Controller new] animated:YES];
                break;
            case 1:
                [self.navigationController pushViewController:[Parent2Controller new] animated:YES];
                break;
            case 2:
                [self.navigationController pushViewController:[Parent3Controller new] animated:YES];
                break;
            default:
                [self.navigationController pushViewController:[Parent4Controller new] animated:YES];
                break;
        }
    }

基本效果实现以后,除了原有的一些可设置的属性:

/** 分页条高度 */
@property(nonatomic, assign) CGFloat pageBarHeight;
/** 分页条背景色 */
@property (nonatomic,strong) UIColor *pageBarBgColor;
/** 下滑线颜色 */
@property (nonatomic,strong) UIColor *lineColor;
/** 下滑线高度 */
@property (nonatomic,assign) CGFloat lineHeight;
/** 标题颜色 */
@property (nonatomic,strong) UIColor *titleColor;
/** 标题字体 */
@property (nonatomic,strong) UIFont *titleFont;

之外,还对这个小工具做了一些新的,在项目中可能会用到的优化:

/** 标题选中颜色(可不设置) */
@property (nonatomic,strong) UIColor *titleSelectedColor;
/** 下划线长度取值类型 */
@property (nonatomic,assign) LineWidthType lineWidthType;
/** 下划线在条目切换时的动态表现类型 */
@property (nonatomic,assign) LineScrollType lineScrollType;

/**
 下划线长度取值类型
 
 - LineWidthTypeStaticShort: 静态短长度,取个固定短值
 - LineWidthTypeStaticLong: 静态长度,根据总长度/数量
 - LineWidthTypeDynamic: 动态长度,根据文字长度
 */
typedef NS_ENUM(NSInteger, LineWidthType) {
    LineWidthTypeStaticShort = 0,
    LineWidthTypeStaticLong,
    LineWidthTypeDynamic,
};

/**
 下划线在条目切换时的动态表现类型

 - LineScrollTypeDynamicAnimation: 即时的下划线动态动画
 - LineScrollTypeFinishedAnimation: 完成后的下划线动态动画
 - LineScrollTypeFinishedLinear: 完成后的下划线线性动画
 - LineScrollTypeDynamicLinear: 即时的下划线线性动画(先不做了,实用性完全被LineScrollTypeDynamicAnimation替代了...)
 */
typedef NS_ENUM(NSInteger, LineScrollType) {
    LineScrollTypeDynamicAnimation = 0,
    LineScrollTypeFinishedAnimation,
    LineScrollTypeFinishedLinear,
};

增加了默认选中位置的设置:

/** 默认选择的 index 位置 ,默认值为0*/
- (void)moveToDefaultIndex:(NSInteger)index;
donghua1.gif

同时也保留了原有的常用的下划线滑动方式:


donghua1.gif

增加了在滑动即将结束时- scrollViewDidEndDecelerating: 处理的新动画效果(这里用了随机数0/1去 push 的这一条):

donghua1.gif

实际的使用方式 demo 里都写的很详细,这里是最后留下的传送门,如果您有兴趣使用这个分页条,欢迎使用并感谢您留个赞.

传送门: Github
(Github上的 readme 并没有更新,看简书这里就行.)

未完待续:

*下一版计划在分页条上增加一个按钮的显示方式,一个图标一个标题这样子.

结尾:

  • 如果发现bug和什么任何问题,请与我联系。
  • 有好的意见或建议,可以联系我。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容

  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    X先生_未知数的X阅读 15,937评论 3 118
  • 闪电 一次又一次地穿透了 合拢的眼帘, 随后的雷声 震聋了 有些迟钝的耳膜, 如注的夜雨啊 没完没了 还是没完没了...
    SS中阅读 604评论 0 5
  • 今天这一天就丰富了,搞的我在作业关门之前是写不完的。现在已经是零点了。 昨天晚上交完作业以后一直没睡着,到...
    闲度阅读 186评论 2 1
  • CPU 224编址范围SM0.0 ~SM179.7,共180个字节。其中SM0.0~SM29.7的30个字节为只读...
    王博超0321阅读 1,033评论 0 0