PZPageListContainer使用手册

本文大约1300字,将会讲述PZPageListContainerView的一些用法。

PZPageListContainerView是一个能够支持上下左右滑入(类似SnapChat)或纵向/水平滑动(类似头条)的PageList基础框架。

!!!原创文章,转载请注明来源: pany.fun

#前言

PZPageListContainerView能够支持多方向的页面滑动,但是只是简单框架,没有一些为具体业务服务的功能。

这里简单实现两个基本结构以作示例 源码

  • 类似SnapChat首页的多方向滑入

    SnapChat风格

  • 类似头条的横向多页面滑动

头条风格

#接入

接入的方式有主要有两种

  • 直接使用PZPageContainerView
  • 使用PZPageListContainerViewController

PZPageListContainerViewController是对PZPageContainerView的Controller化包装,它为PZPageContainerView添加了一些Controller才有的特性,例如viewWillAppear等生命周期方法。

核心部分两者并无区别。

接入以后,两个方向的列表其实就已经都具有了,接下来就是通过相关的属性、方法、协议等来控制。

#属性与方法解析

属性部分

@property (nonatomic, weak) id<PZPageListContainerViewDataSource> dataSource; /**< 建议先设置数据源,避免一些异常 */
@property (nonatomic, weak) id<PZPageListContainerViewDelegate> delegate;

数据源和代理,这两个参数相对简单,数据源方法有两个必须实现,代理全为可选

@property (nonatomic, strong) __kindof UIViewController<PZPageListPageContentProtocol> *backgroundVC;
@property (nonatomic, strong) UIView *headerView;
@property (nonatomic) BOOL autoAdjustPageFitHeader;

headerView:如 头条效果中的灰色顶部。需要外部设置一个view。

autoAdjustPageFitHeader:当存在headerView时是否调整页面上其它部分的frame,默认是YES,如果设置为NO的话,需要自己在外部去处理如inset等。

backgroundVC:如 SnapChat风格中间白色固定的部分,它是一个单独的VC,独立于内部的collectionView之外。因为需要处理collectionView的滑动手势,这个vc不得已必须由外部传入,然后由内部插入到PZPageContainerView的subview中index为0的位置。

// 如果只是单项列表,设置无效
@property (nonatomic) NSUInteger horizontalScrollableIndex;  /**< default = NSUIntegerMax, 当垂直list处在该index时,水平list可以滑动,NSUIntegerMax表示不限制 */
@property (nonatomic) NSUInteger verticalScrollableIndex;    /**< default = NSUIntegerMax, 当水平list处在该index时,垂直list可以滑动,NSUIntegerMax表示不限制 */

这两个参数是对外的参数里比较难理解的

他们的主要作用是用来控制横纵列表交叉的时候的问题,比如SnapChat效果中,横纵列表只有在index为1的时候才能切换方向,而在其它页面,比如左右页面的时候,就只能横向滑动,上下页面的时候,就只能纵向滑动。他们是相互交叉限制的(横向限制纵向的滑动,纵向限制横向的滑动)

横向列表能够滑动的条件是 纵向列表的index == horizontalScrollableIndex

纵向列表能够滑动的条件是 横向列表的index == verticalScrollableIndex

方法部分

方法部分整体比较简单,得益于oc的命名风格,方法基本上看名字就知道干什么的

- (void)reloadData;

- (void)enableScroll:(BOOL)enable inDirection:(PZPageListDirection)direction;

- (void)scrollToIndex:(NSUInteger)index inDirection:(PZPageListDirection)direction animated:(BOOL)animated;

- (__kindof UIViewController<PZPageListPageContentProtocol> *)viewControllerAtIndex:(NSUInteger)index inDirection:(PZPageListDirection)direction;

- (__kindof UIViewController<PZPageListPageContentProtocol> *)currentVisibleViewController;

-enableScroll:inDirection: 是用来在有需要的时候限制某个方向的滑动的。比如SnapChat效果中,当我们点击中间白色页面的switch以后,为了让滑块能够滑动,需要把横纵的滑动都先禁掉,用的就是这个方法。

需要略微注意的是两个返回viewController的方法,需要被加载过以后才能够返回。

#数据源

- (NSInteger)pzPageList:(PZPageListContainerView *)containerView numOfItemsInDirection:(PZPageListDirection)direction;

/**
 @return 需要显示的控制器(请在外部自行保留及添加至子控制器),支持返回nil用于将该区间留空
 */
- (UIViewController<PZPageListPageContentProtocol> *)pzPageList:(PZPageListContainerView *)containerView itemForIndex:(NSInteger)index inDirection:(PZPageListDirection)direction;

-pzPageList:numOfItemsInDirection: 用来返回某方向上page的数量,类似collectionView的numberOfItemsInSection。

-pzPageList:itemForIndex:inDirection:用来返回某方向上某位置的控制器,类似collectionView的cellForItemAtIndexPath。这里设计成允许返回nil的,因为比如SnapChat效果中,为了把白色页面漏出来,需要在collectionView上留空。

#代理

代理除了常规的几个之外,有一个不常见的

/*
 内部collectionView的gesture的代理,用于解决某些手势冲突
 */
- (BOOL)pzPageList:(PZPageListContainerView *)containerView gestureRecognizer:(UIGestureRecognizer *)recognizer shouldSimultaneouslyWith:(UIGestureRecognizer *)otherRecognizer;

这个方法是UICollectionView的panGestureRecognizer的UIGestureRecognizerDelegate中的shouldRecognizeSimultaneouslyWithGestureRecognizer的延伸。

#pragma mark - <UIGestureRecognizerDelegate>
// note: returning YES is guaranteed to allow simultaneous recognition. 
// returning NO is not guaranteed to prevent simultaneous recognition, 
// as the other gesture's delegate may return YES
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer;

内部实现上其实就是collectionView的panGesture的代理方法直接回调了出来,让外部来处理一些手势冲突的问题。但是不用恐慌,这个方法是可选的,内部已经添加了对tableview的默认处理用来兼容tableView的删除手势。

#PZPageListPageContentProtocol

这个协议里目前主要是一套自己的生命周期,因为系统生命周期会乱掉。当UIViewController实现这个协议里的方法的时候,会在合适的时机得到回调。

#其它

开发教程:https://panyfun.github.io/post/PZPageListContainerView/

demo:https://github.com/panyfun/PZPageListContainerView

欢迎Issues:https://github.com/panyfun/PZPageListContainerView/issues

创作不易,转载请注明来源!pany.fun
本文链接:http://pany.fun/post/PZPageListContainer使用手册/