多标签分页滑动控制的封装

     项目经常用到一个页面加载多个控制器,分页滑动并且不同控制器对应不同的标签内容,类似今日头条的效果。之前在多个项目中都有用到过,并且有作简单的封装,鉴于这种功能比较常用,想着这次把封装来得更彻底点,让调用更加方便快捷。类似的效果如下:


       对于要实现这样分页加载的效果,常用的方法有两种,一是用UIScrollView作容器,再把相应的控制器的view加载到UIScrollView上。二是利用UIPageViewController,实现翻页的效果。两种方法我都有写过,针对第一种,比较难控制分页控制器的生命周期,即加载过一次之后,如果不把对应的view移除,下次再出现时,不走- (void)viewWillAppear:(BOOL)animated等方法,要通过滑动距离来实现移除和添加,计算复杂,考虑的要比较弱 多,比较繁琐,所以采用了第二种用UIPageViewController的方式来实现,这种方式不用关心生命周期,内部已经实现好了。

用UIPageViewController来实现分页效果非常方便,只要实现它相关的代理即可,我采用了新建LNPageCotainerViewController继承于UIPageViewController,把它的代理设置为自己来实现,头文件定义如下

其中LNPageContainerDelegate是自己定义的协议,主要是为了通知外部当前处于哪一页,- (void)scrollCompleWithIndex:(NSInteger)index currentController:(UIViewController *)controller; 并且滑动的时候的当前距离是多少,供外部选择性地参考计算- (void)pageViewDidScrollOffset:(CGFloat)offset;

LNPageCotainerViewController有两个方法,一个是手动控制滑动到指定的页- (void)scrollToPage:(NSInteger)page animated:(BOOL)animated; 一个是设置默认显示页- (void)makeDefualtPage:(NSInteger)page;

内部实现如下 :


       通过遍历LNPageCotainerViewController的子视图,找到底层滑动视图设置代理为自己,再通过代理计算出当前滑动的距离。滑动距离与普通的UIScrollView有点不一样,它每次滑动一页之后,offset都会变,所以这里要记录当前下标来计算,再传出正确的滑动距离。

      至此,分页控制的容器功能已经实现了,接下来实现顶部标签滑动页。

     新建LNPageTitleView继承于UIView,内部用一个UIScrollView来装载标签按钮。定义如下 :


    其中PageTitleModel是配置类,实现对标签按钮的显示样式配置;内部实现就是加载按钮,计算距离和位置,详情看LNPageScrollDemo

    接下来,把这两个类组合一下就可以实现了,代码如下:

    其中titles是配置类PageTitleModel的集合,controllers是UIViewcontroller的集合。还有代理的实现,这里就不贴出来了,但这样加载一个分页控制器,实现这样一个功能,似乎代码还是有点多,少说也有几十行。思考一下,针对这种功能的实现,会动态变的也就是标签的不一样和加载控制器的不一样,而容器,标签基类都已经完全封装好,只要把动态变的东西参数化,其它不变的再次封装即可,新建一个类再次封装也可以实现,但这里采用了更加无侵入感的类别的方式来实现,新建UIViewController的类别UIViewController+PageScroll,定义如下:


定义了一个顶部标签视图和容器控制器,由于ios类别不能添加属性,所以采用了runtime来实现,把需要手动控制页的方便暴露出来外面,加载时只要传动态相关的参数即可,内部实现如下:


    这样用类别封装了之后,在调起方只要加载需要的标签和相对应的控制器并传入

- (void)loadPageControllerWithTitles:(NSArray*)titles pageControllers:(NSArray *)controllers defaultPage:(NSInteger)page;这个方法即可加载一个带滑动功能的分页控制。如下:


    这样几行代码就可以搞定了,简化了很多,但也并不是可以满足全部需求,只是针对普通常用的场合,如果特殊需要,需要扩展才能实现现多的效果。写了个demo在github上,LNPageScrollDemo

你可能感兴趣的:(多标签分页滑动控制的封装)