iOS开发(JXPagerView、JXCategoryView
一、 当listView内部持有的UIScrollView或UITableView或UICollectionView,滑动UIScrollView或UITableView或UICollectionView会瞬间置顶
这个主要是分页的子控制器里面的代理协议方法listViewDidScrollCallback没有把JXPagerViewListView的scrollView和UIScrollView或UITableView或UICollectionView的scrollView关联起来导致的,一般分页的子控制器都要实现如下三个方法
@protocol JXPagerViewListViewDelegate <NSObject>
/**
返回listView。如果是vc包裹的就是vc.view;如果是自定义view包裹的,就是自定义view自己。
@return UIView
*/
- (UIView *)listView;
/**
返回listView内部持有的UIScrollView或UITableView或UICollectionView
主要用于mainTableView已经显示了header,listView的contentOffset需要重置时,内部需要访问到外部传入进来的listView内的scrollView
@return listView内部持有的UIScrollView或UITableView或UICollectionView
*/
- (UIScrollView *)listScrollView;
/**
当listView内部持有的UIScrollView或UITableView或UICollectionView的代理方法`scrollViewDidScroll`回调时,需要调用该代理方法传入的callback
@param callback `scrollViewDidScroll`回调时调用的callback
*/
- (void)listViewDidScrollCallback:(void (^)(UIScrollView *scrollView))callback;
@protocol 协议方法必须实现,没写或没写全会直接崩溃的而想要解决上面的bug可以这样写
// 定义一个block回调
@property (nonatomic, copy) void(^scrollCallback)(UIScrollView *scrollView);
// 滑动的代理事件,滑动的时候就会调用这个回调,把scrollView传进去
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
self.scrollCallback(scrollView);
}
// 再把listViewDidScrollCallback的scrollView关联起来
- (void)listViewDidScrollCallback:(void (^)(UIScrollView *))callback {
self.scrollCallback = callback;
}
修改后的效果图
二、 当listView内部持有的UIScrollView或UITableView弹簧效果与下拉刷新冲突
在初始化JXPagerView的时候禁用了UIScrollView或UITableView弹簧效果(bounces)即可
_pagerView = [[JXPagerView alloc]initWithDelegate:self];
_pagerView.mainTableView.bounces = NO;
2022年1月15 更新
如果上面的方法没用可以将JXPagerView换成JXPagerListRefreshView, 作者的Demo就是用的JXPagerListRefreshView
_pagerView = [[JXPagerListRefreshView alloc]initWithDelegate:self];
三、 顶部的View高度改变不适配问题
- 一开始没改变之前的顶部View高度不对,可以在返回顶部View的代理方法里面这样写
// 我_headerView里面使用约束来布局的
- (NSUInteger)tableHeaderViewHeightInPagerView:(JXPagerView *)pagerView
{
CGFloat headerH = [_headerView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
return headerH;
}
- 点击改变_headerView高度就重新改变一下它的frame,最重要刷新一下JXPagerView
CGFloat headerViewH = [self.headerView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
self.headerView.frame = CGRectMake(0.f, 0.f, [UIScreen mainScreen].bounds.size.width, headerViewH);
[self.pagerView reloadData];
四、 如果滑上去顶部是一个导航栏,导航栏下面才是JXCategoryTitleView
像这样:
有两种方法
-
把这个JXPagerView的约束布局在导航栏之下,下图就是这样做的,导航栏放着个搜索框,然后JXPagerView放在它之下,无论怎么滑,都是顶着导航栏的
-
而下图JXPagerView是紧贴最顶部的,导航栏隐藏了起来
JXPagerView滑动的时候有个代理方法可以监听它滑动,相当于scrollView的scrollViewDidScroll方法,就是 - (void)mainTableViewDidScroll:(UIScrollView *)scrollView
,当然你要在分页子控制器里面写好那三个代理方法先
在mainTableViewDidScroll
里面判断如果self.pagerView.mainTableView.contentOffset.y
是否大于导航栏高度,小于就设置self.pagerView.mainTableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
,大于就设置self.pagerView.mainTableView.contentInset = UIEdgeInsetsMake(kNavBarHeight, 0, 0, 0);
(kNavBarHeight为导航栏高度),这样看下效果
这时又会出现一个bug,就是当你手离开屏幕,如果屏幕还在滑,那JXCategoryView又滑上去。这时可以用JXPagerView的一个属性
/**
顶部固定sectionHeader的垂直偏移量。数值越大越往下沉。
*/
@property (nonatomic, assign) NSInteger pinSectionHeaderVerticalOffset;
//y 轴 偏移量
CGFloat y = self.pagerView.mainTableView.contentOffset.y;
//需要计算的高度,kNavBarHeight为导航栏高度
CGFloat h = kNavBarHeight;
CGFloat alpha = 0;
//超出偏移量的返回
if (y < 0) {
return;
}else if (y < h) {
self.pagerView.mainTableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
self.pagerView.pinSectionHeaderVerticalOffset = 0;
}
else{
self.pagerView.pinSectionHeaderVerticalOffset = kNavBarHeight;
}
最好还是在小于导航栏高度的时候设置一下mainTableView的contentInset,要不然有时候会不顺畅和底部留空,效果如下(部分代码不展示)
五、 适配iOS15 JXPagerView顶部会留白
// 在定义JXPagerView的时候
if (@available(iOS 15.0, *)) {
_pagerView.mainTableView.sectionHeaderTopPadding = 0;
}