遇到了这个需求,恶心了自己一天,记录下来
嵌套模式
一个竖向滑动的scrollview1,嵌套一个横向滑动的scrollview2, 嵌套4个用controller控制的tableview
核心解决方案
- 手动控制contentOffset滚动的临界偏移量
- 打开手势穿透
控制临偏界偏移量
既然要控制临界偏移量,就首先要获取contentOffset才可以控制。
- 添加UIScrollviewDelegate
- tableview的contentoffset写一个代理返回回来,方便一起控制
手势穿透
我使用了一个分类,添加了一个属性,使得scrollview1允许穿透
/// .h文件
@interface UIScrollView (DDScrollView)
/// 手势穿透
@property (nonatomic, strong) NSString *shouldThrough;
@end
/// .m文件
#import "UIScrollView+DDScrollView.h"
#import <objc/runtime.h>
@implementation UIScrollView (DDScrollView)
- (void)setShouldThrough:(NSString *)shouldThrough {
objc_setAssociatedObject(self, "shouldThrough", shouldThrough, OBJC_ASSOCIATION_RETAIN);
}
- (NSString *)shouldThrough {
return objc_getAssociatedObject(self, "shouldThrough");
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
if ([self.shouldThrough isEqualToString:@"1"]) {
return true;
}
return false;
}
@end
核心代码
@interface ViewController ()<TBControllerDelegate,UIScrollViewDelegate>
@property (nonatomic, strong) UIScrollView *scrollview1;
@property (nonatomic, strong) UIScrollView *scrollview2;
/// 滚动标题
@property (nonatomic, strong) PageTitleView *titleView;
@property (nonatomic, strong) NSMutableArray *childVCArr;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_childVCArr = [NSMutableArray array];
_scrollview1 = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 88, self.view.frame.size.width, self.view.frame.size.height - 88)];
_scrollview1.contentSize = CGSizeMake(0, 1000);
_scrollview1.backgroundColor = [UIColor systemPinkColor];
_scrollview1.tag = 500;
_scrollview1.delegate = self;
_scrollview1.shouldThrough = @"1";
_titleView = [[PageTitleView alloc] initWithFrame:CGRectMake(0, 250, self.view.frame.size.width, 50) titles:@[@"标题1",@"标题2",@"标题3",@"标题4"]];
_titleView.backgroundColor = [UIColor whiteColor];
_scrollview2 = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 300, self.view.frame.size.width, 700)];
_scrollview2.contentSize = CGSizeMake(self.view.frame.size.width * 4, 0);
_scrollview2.backgroundColor = [UIColor blueColor];
_scrollview2.tag = 501;
_scrollview2.pagingEnabled = true;
_scrollview2.delegate = self;
[self.view addSubview:_scrollview1];
[_scrollview1 addSubview:_titleView];
[_scrollview1 addSubview:_scrollview2];
for (int i = 0; i < 4; i ++) {
TBController *tbvc = [[TBController alloc] init];
tbvc.delegate = self;
[self addChildViewController:tbvc];
UIView *view = tbvc.view;
CGRect rect = view.frame;
rect.origin.x = self.view.frame.size.width * i;
rect.size.height = _scrollview2.frame.size.height;
view.frame = rect;
[_scrollview2 addSubview:view];
[_childVCArr addObject:tbvc];
}
}
#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (scrollView.tag == 500) {
TBController *currentVc = self.childVCArr[_titleView.currentIndex];
// 临界偏移量 245 小于245的话不允许下方滚动
// 这个scrollview把属性穿透打开了,所以要自己控制一下偏移量
if (scrollView.contentOffset.y < 245) {
// 如果当前显示tablview的偏移量大于0, 则固定scrollview,让tableview滚动完再移动scrollview的
if (currentVc.tableView.contentOffset.y > 0) {
scrollView.contentOffset = CGPointMake(0, 245);
} else {
currentVc.tableView.contentOffset = CGPointMake(0, 0);
}
} else if (scrollView.contentOffset.y >= 245) {
//contentoffset-y 如果小于0 静止滚动
_scrollview1.contentOffset = CGPointMake(0, 245);
if (currentVc.tableView.contentOffset.y < 0) {
currentVc.tableView.contentOffset = CGPointMake(0, 0);
} else {
}
}
} else if (scrollView.tag == 501) {
[_titleView moveIndicatorViewWithOffset:_scrollview2.contentOffset.x];
}
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
if (scrollView.tag == 501) {
NSInteger index = scrollView.contentOffset.x / _scrollview2.frame.size.width;
[_titleView selectCurrentTitleViewWithIndex:index];
}
}
#pragma mark TaskListControllerDelegate
// 这里控制一下控制器内tableview返回的数值
- (void)controller:(UIViewController *)controller didScrollTableView:(UITableView *)tableView {
[self handleOutScrollView:_scrollview1 tableView:tableView];
}
- (void)handleOutScrollView:(UIScrollView *)scrollView tableView:(UITableView *)tableView {
if (scrollView.contentOffset.y < 245) {
// 禁止滚动 && 自动滚到最上
tableView.contentOffset = CGPointMake(0, 0);
} else if (scrollView.contentOffset.y >= 245) {
if (tableView.contentOffset.y < 0) {
tableView.contentOffset = CGPointMake(0, 0);
}
}
}
#pragma mark - PageTitleViewDelegate
- (void)pageTitleIndicatorViewSelected:(NSInteger)index {
//将scrollView滑动到指定地
[_scrollview2 setContentOffset:CGPointMake(_scrollview2.frame.size.width * index, 0) animated:NO];
}
@end






网友评论