最近遇到一个需求页面,上下滚动吸顶,支持列表左右滚动,如图:
根据需求,我写的页面布局如下:
简单描述布局逻辑:最底层使用tableView_1 - 主要是想使用其
section-head
吸顶效果,tableView_1
的tableViewHeadView
是大文字标题,tableView_1
的tableViewfootView
为scrollView
,scrollView
添加两个tableView_2
。完成布局,任务就已完成80%,现在剩下一个最重要问题要解决:嵌套导致的
tableView
上下滚动冲突问题。相关代码如下:
-
外部
tableView_1
,重写手势方法,目的是tableView_1
接收在tableView_2
区域的滚动手势
HDBaseTableView.h
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface HDBaseTableView : UITableView<UIGestureRecognizerDelegate>
@end
NS_ASSUME_NONNULL_END
HDBaseTableView.m
@implementation HDBaseTableView
/**
同时识别多个手势
@param gestureRecognizer gestureRecognizer description
@param otherGestureRecognizer otherGestureRecognizer description
@return return value description
*/
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
return YES;
}
@end
-
外
tableView
:tableView_1
不能滚动时,吸顶;滚动时,重置tableView_2
偏移量。
HDFormViewController.m
@interface HDFormViewController ()<HDFormListViewDelegate, UITableViewDelegate, UIScrollViewDelegate>
/// 外部tableview
@property (nonatomic, strong) HDBaseTableView *formTableView;
/// 是否滚动
@property (nonatomic, assign) BOOL isCanScroll;
@end
#pragma mark - setter、getter
- (HDBaseTableView *)formTableView{
if (!_formTableView) {
_formTableView = [HDBaseTableView new];
_formTableView.bounces = NO;
_formTableView.delegate = self;
_formTableView.showsVerticalScrollIndicator = NO;
_formTableView.showsHorizontalScrollIndicator = NO;
_formTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
if (@available(iOS 11.0, *)) {
_formTableView.estimatedRowHeight = 0;
_formTableView.estimatedSectionHeaderHeight = 0;
_formTableView.estimatedSectionFooterHeight = 0;
_formTableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
[_formTableView registerClass:[UITableViewCell class] forCellReuseIdentifier:NSStringFromClass([UITableViewCell class])];
_formTableView.tableHeaderView = self.downloadTipView;
_formTableView.tableFooterView = self.horScrollView;
}
return _formTableView;
}
#pragma mark - UIScrollViewDelegate
static CGFloat const headerHeight = 105;
static CGFloat const kCanHideHeaderHeight = 93;
static CGFloat const kHeaderHeight = 105;
static CGFloat const kCanHideHeaderHeight = 93;
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
if (scrollView == self.formTableView) {
self.titleLabel.hidden = !(self.formTableView.contentOffset.y > 45);
// 外tableview滚动max-offsetY
if (scrollView.contentOffset.y >= kCanHideHeaderHeight) {
// 上划吸顶
scrollView.contentOffset = CGPointMake(0, kCanHideHeaderHeight);
if (_isCanScroll) {
// 禁止滚动
_isCanScroll = NO;
}
}else{
if (!_isCanScroll) {// 外tableView不能滚动时,需要保持吸顶状态
scrollView.contentOffset = CGPointMake(0, kCanHideHeaderHeight);
}else{// 外tableView滚动时,内tableView不能滚动
self.formListView.listTableView.contentOffset = CGPointZero;
}
}
}
}
#pragma mark - NSNotification
- (void)addNotification{
_isCanScroll = YES;
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(changeScrollStatus) name:kHDChangeScrollStatus object:nil];
}
- (void)changeScrollStatus{
_isCanScroll = YES;
// 非0保证下拉刷新
if (self.formTableView.contentOffset.y != 0) {
self.formListView.listTableView.contentOffset = CGPointZero;
}
}
- (void)dealloc{
[[NSNotificationCenter defaultCenter]removeObserver:self name:kHDChangeScrollStatus object:nil];
}
-
tableView_2
:不能滚动时,通知tableView_1
滚动,重置tableView_2
偏移量。
HDFormListView.m
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
//到顶通知父视图改变状态
if (scrollView.contentOffset.y <= 0) {
[[NSNotificationCenter defaultCenter] postNotificationName:kHDChangeScrollStatus object:nil];
}
}