升級版本 解決三大問題:1.多控制器時候 切換導(dǎo)致秩序問題 2.通知命名重復(fù)沖突問題3.優(yōu)化代碼
QQ20200601-143648-HD.gif
結(jié)構(gòu)
結(jié)構(gòu).png
- HomePageVC 的子控制器homeParentVC、homeParentVC管理多個子控制器HomeSonVC
- HomePageVC的scrollView必須允許多手勢
- HomeSonVC的scrollView可以不允許多手勢、HomeSonVC繼承BaseScrollViewVC即可
BaseScrollViewVC(直接繼承即可)
.h
/**
1.解決多個VC通知發(fā)送影響問題
1.1 接受 baseScrollNotiName + 通知名 + baseScrollIndex HomePageListsItemVC+kNSGoTop+1 接受都是子控制器 一對一 (以前是一對多 父類控制器發(fā)送 很多子類接受)
1.1 發(fā)送通知 發(fā)送是可以用同一個名字 HomePageListsItemVC+KNSLeaveTop+all (多對一 所以父類控制器不怕發(fā)送多)
*/
#import "BaseVC.h"
NS_ASSUME_NONNULL_BEGIN
@interface BaseScrollViewVC : BaseVC
@property(nonatomic,strong)NSString *baseScrollNotiName;//多VC下滑動標(biāo)記發(fā)通知
@property(nonatomic,assign)NSInteger baseScrollIndex;//多VC下滑動標(biāo)記發(fā)通知
@property(nonatomic,assign)BOOL canScroll;//是否可以滾動 默認(rèn)是不可滾動的 必須等父類控制器的通知
@property(strong,nonatomic)UIScrollView *currentScrollView;//通過scroll代理綁定當(dāng)前滑動視圖
@property(nonatomic,copy)void (^callBackScrollBlcok)(UIScrollView *scrollView);
@end
NS_ASSUME_NONNULL_END
.m
#import "BaseScrollViewVC.h"
@interface BaseScrollViewVC ()<UIGestureRecognizerDelegate,UIScrollViewDelegate>
@end
@implementation BaseScrollViewVC
- (void)viewDidLoad
{
[super viewDidLoad];
//子控制器視圖到達(dá)頂部的通知
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(acceptMsg:) name:[NSString stringWithFormat:@"%@+%@+%ld",self.baseScrollNotiName,kNestingScrollGoTopNoti,self.baseScrollIndex] object:nil];
//這個千萬不能加 要在主控制器先判斷主控制器(如果HomePageVC)滑動狀態(tài)
//self.canScroll = NO;
}
//接收信息未舟,處理通知
- (void)acceptMsg:(NSNotification *)notification
{
//NSLog(@"子控制器接受goTop通知,%@",notification.name);
NSString *notificationName = notification.name;
if ([notificationName isEqualToString:[NSString stringWithFormat:@"%@+%@+%ld",self.baseScrollNotiName,kNestingScrollGoTopNoti,self.baseScrollIndex]])
{
self.canScroll = YES;
self.currentScrollView.showsVerticalScrollIndicator = YES;
}
}
#pragma mark - ScrollView代理
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (!self.canScroll)
{
//不可以滑動 設(shè)置 CGPointZero 都很準(zhǔn)在0.0000 沒有因?yàn)樯舷禄瑒? [scrollView setContentOffset:CGPointZero];
}
CGFloat offsetY = scrollView.contentOffset.y;
if (offsetY < 0)
{
//這里發(fā)送離開通知...
//NSLog(@"子控制器發(fā)送leaveTop通知,%@",[NSString stringWithFormat:@"%@+%@+all",self.baseScrollNotiName,kNestingScrollLeaveTopNoti]);
[[NSNotificationCenter defaultCenter]postNotificationName:[NSString stringWithFormat:@"%@+%@+all",self.baseScrollNotiName,kNestingScrollLeaveTopNoti] object:nil];
[scrollView setContentOffset:CGPointZero];
self.canScroll = NO;
scrollView.showsVerticalScrollIndicator = NO;
}
_currentScrollView = scrollView;
//回調(diào)偏移量
!self.callBackScrollBlcok ?: self.callBackScrollBlcok (scrollView);
}
//處理左滑右滑,防止左滑返回上一界面
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
// 首先判斷otherGestureRecognizer是不是系統(tǒng)pop手勢
if ([otherGestureRecognizer.view isKindOfClass:NSClassFromString(@"UILayoutContainerView")])
{
// 再判斷系統(tǒng)手勢的state是began還是fail恢总,同時判斷scrollView的位置是不是正好在最左邊
if (otherGestureRecognizer.state == UIGestureRecognizerStateBegan && self.currentScrollView.contentOffset.x == 0)
{
return YES;
}
}
return NO;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
@end
- 為了解決通知名字不重復(fù)蚤蔓,所以需要.h傳入進(jìn)來參數(shù)
- 臨界點(diǎn)控制setContentOffset偏移量
- 一個block用于回調(diào)偏移量防止子類重寫scrollViewDidScroll
- 子類繼承控制器必須有UIScrollView子類并且設(shè)置代理不然.m里面scrollViewDidScroll不執(zhí)行了
- 子類endRefresh記得提醒主控制器
HomePageVC
.h
#import "BaseVC.h"
NS_ASSUME_NONNULL_BEGIN
@interface HomePageVC : BaseVC
@property(nonatomic,assign,readonly)BOOL canScroll;
@end
NS_ASSUME_NONNULL_END
.m
#import "HomePageVC.h"
#import "HomeParentVC.h"
@interface HomePageVC ()<UITableViewDelegate,UITableViewDataSource>
@property(nonatomic,strong)BaseTableView *mainView;
@property(nonatomic,strong)HomeParentVC *managerVC;
//滑動屬性
@property(nonatomic,assign)BOOL canScroll;
@property(nonatomic,assign)BOOL canMove;//臨界點(diǎn)(大于等于臨界點(diǎn)不能滑動NO,小于臨界點(diǎn)可以滑動)
@property(nonatomic,assign)BOOL canMovePrevious;
@end
@implementation HomePageVC
#pragma mark - life生命區(qū)
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[[Factory backAPPTabBarVC]changeSelectedIndex:0];
}
- (void)createProperty
{
self.canScroll = YES;
self.canMove = YES;
self.canMovePrevious = YES;
//監(jiān)聽
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(acceptMsg:) name:[NSString stringWithFormat:@"%@+%@+all",@"HomeSonVC",kNestingScrollLeaveTopNoti] object:nil];
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(endRefresh) name:kNestingScrollEndRefreshNoti object:nil];
}
- (void)createUI
{
//臨時頭部
UIImageView *tableHeaderView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, WIDTH, 206*ADAPTER_WIDTH)];
tableHeaderView.backgroundColor = RedColor;
[tableHeaderView sd_setImageWithURL:@"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1590987737591&di=e0e922dae7fd800750e17753efe9bc05&imgtype=0&src=http%3A%2F%2F5b0988e595225.cdn.sohucs.com%2Fimages%2F20190720%2F188eef713776424c933eaa2de61f9dbf.jpeg".wppURL];
tableHeaderView.clipsToBounds = YES;
self.mainView.tableHeaderView = tableHeaderView;
//添加刷新
WK(weakSelf)
self.mainView.mj_header = [BossHeaderView headerWithRefreshingBlock:^{
[weakSelf.managerVC refreshCurrentSonVC];
}];
}
- (void)endRefresh
{
[self.mainView.mj_header endRefreshing];
}
#pragma mark - UITableView代理方法
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.backgroundColor = kColorBGTinyBlue;
[cell.contentView addSubview:self.managerVC.view];
return cell;
}
#pragma mark - 滑動代碼
//接收信息茉继,處理通知
- (void)acceptMsg:(NSNotification *)notification
{
//NSLog(@"%@",notification.name);
if ([notification.name isEqualToString:[NSString stringWithFormat:@"%@+%@+all",@"HomeSonVC",kNestingScrollLeaveTopNoti]]) {
//NSLog(@"主控制器接受:leaveTop通知");
self.canScroll = YES;
//這里處理已經(jīng)創(chuàng)建的view 所有contentOffsetY 會0
[self.managerVC.childViewControllers enumerateObjectsUsingBlock:^(__kindof UIViewController * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
//HomePageListsItemVC
if ([obj isKindOfClass:[BaseScrollViewVC class]]) {
if (obj.viewLoaded) {
BaseScrollViewVC *scrollVC = (BaseScrollViewVC *)obj;
[scrollVC.currentScrollView setContentOffset:CGPointZero];
scrollVC.canScroll = NO;
}
}
}];
}
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
//NSLog(@"%f,%f",scrollView.contentOffset.y,ceil(scrollView.contentOffset.y));
//最重要的就是 子視圖滑動會影響主控制器視圖 比如:子視圖向下滑動 手勢傳遞 自然contentOffsetY 會變大 子視圖向上滑動 手勢傳遞 自然contentOffsetY 會變小 從而影響臨界點(diǎn)問題
CGFloat offset = scrollView.contentOffset.y + scrollView.contentInset.top;
CGFloat tableHeaderShowHeight = kStatusBarHeight + 30*ADAPTER_WIDTH;
CGFloat criticalPoint = self.mainView.tableHeaderView.height - tableHeaderShowHeight;
if (self.canScroll) {
self.canMovePrevious = self.canMove;
if (ceil(offset) >= ceil(criticalPoint)) {
[scrollView setContentOffset:CGPointMake(0, criticalPoint)];
self.canMove = NO;
} else {
self.canMove = YES;
//NSLog(@"向上移動");
}
if (self.canMove != self.canMovePrevious) {
if (self.canMove == NO && self.canMovePrevious == YES) {
//NSLog(@"不可以滑動 大于或等于臨界點(diǎn)");
//發(fā)送通知 必須針對 當(dāng)前的VC 不能一樣
[[NSNotificationCenter defaultCenter]postNotificationName:[NSString stringWithFormat:@"%@+%@+%ld",@"HomeSonVC",kNestingScrollGoTopNoti,self.managerVC.currentIndex] object:nil];
_canScroll = NO;
}
if (self.canMove == YES && self.canMovePrevious == NO) {
//NSLog(@"可以滑動 小于臨界點(diǎn)");
//[scrollView setContentOffset:CGPointMake(0, criticalPoint)];
}
}
} else {
[scrollView setContentOffset:CGPointMake(0, criticalPoint)];
}
}
#pragma mark - lazy懶加載
- (BaseTableView *)mainView
{
if (!_mainView) {
BaseTableView *tableView = [[BaseTableView alloc]initWithFrame:CGRectMake(0, 0, WIDTH, HEIGHT - kCustomTabBarHeight) style:UITableViewStylePlain];
[self.view addSubview:tableView];
tableView.delegate = self;
tableView.dataSource = self;
tableView.tableFooterView = [UIView new];
[tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"Cell"];
tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
tableView.backgroundColor = kColorBGTinyBlue;
if (@available(iOS 11.0, *))
{
tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
tableView.estimatedRowHeight = 0;
tableView.estimatedSectionFooterHeight = 0;
tableView.estimatedSectionHeaderHeight = 0;
}
else
{
self.automaticallyAdjustsScrollViewInsets = NO;
}
tableView.rowHeight = HEIGHT - kCustomTabBarHeight;
tableView.showsVerticalScrollIndicator = NO;
_mainView = tableView;
}
return _mainView;
}
- (HomeParentVC *)managerVC
{
if (!_managerVC) {
HomeParentVC *vc = [[HomeParentVC alloc]init];
CGFloat tableHeaderShowHeight = kStatusBarHeight + 30*ADAPTER_WIDTH;
vc.viewHeight = HEIGHT - kCustomTabBarHeight - tableHeaderShowHeight;
[self addChildViewController:vc];
_managerVC = vc;
}
return _managerVC;
}
- (UIStatusBarStyle)preferredStatusBarStyle
{
return UIStatusBarStyleLightContent;
}
@end
- 核心方法acceptMsg翼闹、scrollViewDidScroll
-
屬性canScroll丁寄、canMove、canMovePrevious
3)
1)默認(rèn)canScroll屈雄、canMove村视、canMovePrevious都是YES可以滑動
2)將canMove賦值給canMovePrevious
image.png
HomeParentVC
.h
#import "BaseVC.h"
NS_ASSUME_NONNULL_BEGIN
@interface HomeParentVC : BaseVC
@property(nonatomic,assign)CGFloat viewHeight;
@property(nonatomic,assign)NSInteger jumIndex;
@property(nonatomic,assign,readonly)NSInteger currentIndex;//提供給發(fā)通知的
/**
刷新當(dāng)前子控制器
*/
- (void)refreshCurrentSonVC;
@end
NS_ASSUME_NONNULL_END
.m
#import "HomeParentVC.h"
#import "HomeSonVC.h"
#import "BSTBitmapView.h"
#import "HomePageVC.h"
@interface HomeParentVC ()<UIScrollViewDelegate>
@property(nonatomic,strong)UIScrollView *titleBG;
@property(nonatomic,strong)UIScrollView *contentBG;
@property(nonatomic,strong)NSMutableArray<UILabel *> *titleBtnArrs;
@property(nonatomic,strong)UILabel *preLab;
@property(nonatomic,strong)UIView *selectedItemBottomLine;
//記錄當(dāng)前子控制器index
@property(nonatomic,assign)NSInteger currentIndex;
@end
@implementation HomeParentVC
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)createProperty
{
}
- (void)createUI
{
[self createContentBG];
[self createTitleBG];
}
#pragma mark - UI
- (void)createTitleBG
{
//準(zhǔn)備滑動標(biāo)題
NSMutableArray<NSString *> *nameArrs = [NSMutableArray array];
[nameArrs addObject:@"精選"];
[nameArrs addObject:@"排行榜"];
[nameArrs addObject:@"會逛超市"];
[nameArrs addObject:@"雞蛋禽類"];
[nameArrs addObject:@"水果蔬菜"];
//titleBG
UIScrollView *titleBG = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, WIDTH, 42)];
[self.view addSubview:titleBG];
titleBG.backgroundColor = [UIColor whiteColor];
titleBG.showsVerticalScrollIndicator = NO;
titleBG.showsHorizontalScrollIndicator = NO;
//titleBG.delegate = self;
//titleBG.bounces = NO;
self.titleBG = titleBG;
//滑動小按鈕下面的橫線 提前創(chuàng)建 比小按鈕早添加到titleBG
UIView *selectedItemBottomLine = [[UIView alloc]init];
[titleBG addSubview:selectedItemBottomLine];
selectedItemBottomLine.backgroundColor = RGB(252, 181, 111, 1);
self.selectedItemBottomLine = selectedItemBottomLine;
UITapGestureRecognizer *jumIndexTap;
CGFloat orinX = 13*ADAPTER_WIDTH,itemMargin = 25*ADAPTER_WIDTH;
//for循環(huán)布局
for (NSInteger index = 0; index < nameArrs.count; index ++) {
NSString *content = nameArrs[index];
CGFloat itemWidth = [content sizeWithFont:[UIFont systemFontOfSize:16*ADAPTER_WIDTH weight:UIFontWeightMedium]].width;
UILabel *lab = [[UILabel alloc]init];
[titleBG addSubview:lab];
lab.text = content;
lab.font = [UIFont systemFontOfSize:16*ADAPTER_WIDTH weight:UIFontWeightMedium];
lab.textColor = kColor48;
lab.frame = CGRectMake(orinX, 14, itemWidth, 17*ADAPTER_WIDTH);
orinX = index == (nameArrs.count - 1) ? (lab.right + 13*ADAPTER_WIDTH) : (lab.right + itemMargin);
//添加點(diǎn)擊事件
lab.tag = index;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(clickItem:)];
lab.userInteractionEnabled = YES;
[lab addGestureRecognizer:tap];
//加入數(shù)組中
[self.titleBtnArrs addObject:lab];
if (index == self.jumIndex)
{
self.preLab = lab;
selectedItemBottomLine.frame = CGRectMake(lab.left+2, lab.bottom-4, lab.width-4, 4);
jumIndexTap = tap;//綁定要跳轉(zhuǎn)的
}
}
titleBG.contentSize = CGSizeMake(orinX, 0);
//為什么在循環(huán)之外寫呢 因?yàn)?頭部沒有創(chuàng)建完整 進(jìn)行跳轉(zhuǎn) 頭部如果過長 會出現(xiàn) 標(biāo)題不能居中問題
[self clickItem:jumIndexTap];
}
- (void)createContentBG
{
UIScrollView *contentBG = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 42, WIDTH, self.viewHeight - 42)];
[self.view addSubview:contentBG];
contentBG.backgroundColor = [UIColor whiteColor];
contentBG.showsVerticalScrollIndicator = NO;
contentBG.showsHorizontalScrollIndicator = NO;
contentBG.pagingEnabled = YES;
contentBG.bounces = NO;
contentBG.delegate = self;
self.contentBG = contentBG;
//添加控制器
HomeSonVC *vc = [[HomeSonVC alloc]init];
[self addChildViewController:vc];
HomeSonVC *vc1 = [[HomeSonVC alloc]init];
[self addChildViewController:vc1];
HomeSonVC *vc2 = [[HomeSonVC alloc]init];
[self addChildViewController:vc2];
HomeSonVC *vc3 = [[HomeSonVC alloc]init];
[self addChildViewController:vc3];
HomeSonVC *vc4 = [[HomeSonVC alloc]init];
[self addChildViewController:vc4];
//這里可以添加VC的回調(diào)block之類的
//擴(kuò)大滑動范圍
contentBG.contentSize = CGSizeMake(WIDTH * self.childViewControllers.count, 0);
for (NSInteger index = 0; index < self.childViewControllers.count; index ++)
{
BSTBitmapView *bitmapView = [[BSTBitmapView alloc]initWithFrame:CGRectMake(index*WIDTH, 0, WIDTH, contentBG.height)];
[self.contentBG addSubview:bitmapView];
bitmapView.type = BitmapViewTypeLoading;
bitmapView.tag = 100+index;
}
}
#pragma mark - 點(diǎn)擊事件
- (void)clickItem:(UITapGestureRecognizer *)sender
{
//如果animated 是YES 會走scrollView 多次 2個界面會好看些
[self.contentBG setContentOffset:CGPointMake(sender.view.tag * WIDTH, 0) animated:NO];
//處理控制器
[self setUpSubController:sender.view.tag];
//處理頭部title
[self refreshTitleLab:self.titleBtnArrs[sender.view.tag]];
}
#pragma mark - SCrollView代理方法
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
NSInteger index = scrollView.contentOffset.x / WIDTH;
//處理控制器
[self setUpSubController:index];
//處理頭部title
[self refreshTitleLab:self.titleBtnArrs[index]];
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
NSInteger index = scrollView.contentOffset.x / WIDTH;
CGFloat tmpOffsetX = scrollView.contentOffset.x / WIDTH;
CGFloat scaleRight = tmpOffsetX - index;
CGFloat scaleLeft = 1 - scaleRight;
if (index + 1 <= self.titleBtnArrs.count - 1)
{
//NSLog(@"%ld,%f,%f",index,scaleRight,scaleLeft);
//self.selectedItemBottomLine.frame = CGRectMake(currentLab.left+2, self.selectedItemBottomLine.top, self.selectedItemBottomLine.width, self.selectedItemBottomLine.height);
UILabel *leftLab = self.titleBtnArrs[index];
UILabel *rightLab = self.titleBtnArrs[index+1];
if (scaleRight == 0)
{
//NSLog(@"到達(dá)臨界值...");
return;
}
if (self.currentIndex == index)
{
//NSLog(@"向右");
self.selectedItemBottomLine.frame = CGRectMake(leftLab.left+2, self.selectedItemBottomLine.top, leftLab.width-4+(scaleRight*(rightLab.left-leftLab.right)), self.selectedItemBottomLine.height);
}
else
{
//NSLog(@"向左");
self.selectedItemBottomLine.frame = CGRectMake(rightLab.left+2-(scaleLeft*(rightLab.left-leftLab.right)), self.selectedItemBottomLine.top, leftLab.width-4+(scaleLeft*(rightLab.left-leftLab.right)), self.selectedItemBottomLine.height);
}
}
}
#pragma mark - 添加子控制器視圖
- (void)setUpSubController:(NSInteger)index
{
self.currentIndex = index;
HomeSonVC *vc = self.childViewControllers[index];
//做一些 vc的初始化
vc.viewHeight = self.contentBG.height;
vc.baseScrollIndex = index;
vc.baseScrollNotiName = @"HomeSonVC";
//判斷父類控制器 是否可以滑動
if ([self.parentViewController isMemberOfClass:[HomePageVC class]]) {
HomePageVC *parentVC = (HomePageVC *)self.parentViewController;
vc.canScroll = !parentVC.canScroll;
}
if (vc.view.superview)
{
return;
}
vc.view.frame = CGRectMake(index *WIDTH, 0, WIDTH, self.contentBG.height);
[self.contentBG addSubview:vc.view];
//清除占位圖
BSTBitmapView *bitMapView = [self.contentBG viewWithTag:100+index];
if (bitMapView != nil)
{
[bitMapView removeFromSuperview];
}
}
#pragma mark - 矯正滑動標(biāo)題的居中問題
- (void)refreshTitleLab:(UILabel *)currentLab
{
self.preLab.textColor = kColor48;
self.preLab = currentLab;
[UIView animateWithDuration:0.2 delay:0 usingSpringWithDamping:0.6 initialSpringVelocity:1.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self.selectedItemBottomLine.frame = CGRectMake(currentLab.left+2, self.selectedItemBottomLine.top, currentLab.width-4, self.selectedItemBottomLine.height);
} completion:^(BOOL finished) {
}];
//標(biāo)題居中
//NSLog(@"設(shè)置居中...");
CGFloat offsetX = currentLab.center.x - (self.titleBG.width *0.5);
if (offsetX < 0)
{
offsetX = 0;
}
//如果針對 標(biāo)簽數(shù)量小 滑動范圍小則出現(xiàn)問題 所有判斷一下
if (self.titleBG.contentSize.width > self.titleBG.width) {
CGFloat maxOffsetX = self.titleBG.contentSize.width - self.titleBG.width;
if (offsetX > maxOffsetX)
{
offsetX = maxOffsetX;
}
}
//NSLog(@"offsetX:%f",offsetX);
[self.titleBG setContentOffset:CGPointMake(offsetX, 0) animated:YES];
}
#pragma mark - 公開方法
- (void)refreshCurrentSonVC
{
if (self.childViewControllers.count == 0) {
[[NSNotificationCenter defaultCenter]postNotificationName:kNestingScrollEndRefreshNoti object:nil];
return;
}
HomeSonVC *vc = self.childViewControllers[self.currentIndex];
[vc loadNewData];
}
#pragma mark - Lazy懶加載區(qū)域
- (NSMutableArray<UILabel *> *)titleBtnArrs
{
if (!_titleBtnArrs)
{
_titleBtnArrs = [NSMutableArray array];
}
return _titleBtnArrs;
}
@end
- @property(nonatomic,assign,readonly)NSInteger currentIndex;//提供給發(fā)通知的
- setUpSubController方法中 給VC傳入通知所需屬性
#pragma mark - 添加子控制器視圖
- (void)setUpSubController:(NSInteger)index
{
self.currentIndex = index;
HomeSonVC *vc = self.childViewControllers[index];
//做一些 vc的初始化
vc.viewHeight = self.contentBG.height;
vc.baseScrollIndex = index;
vc.baseScrollNotiName = @"HomeSonVC";
//判斷父類控制器 是否可以滑動
if ([self.parentViewController isMemberOfClass:[HomePageVC class]]) {
HomePageVC *parentVC = (HomePageVC *)self.parentViewController;
vc.canScroll = !parentVC.canScroll;
}
if (vc.view.superview)
{
return;
}
vc.view.frame = CGRectMake(index *WIDTH, 0, WIDTH, self.contentBG.height);
[self.contentBG addSubview:vc.view];
//清除占位圖
BSTBitmapView *bitMapView = [self.contentBG viewWithTag:100+index];
if (bitMapView != nil)
{
[bitMapView removeFromSuperview];
}
}
如果還有一個頭部伸縮在criticalPoint 進(jìn)行修改
QQ20200601-173204-HD.gif
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
//NSLog(@"%f,%f",scrollView.contentOffset.y,ceil(scrollView.contentOffset.y));
//最重要的就是 子視圖滑動會影響主控制器視圖 比如:子視圖向下滑動 手勢傳遞 自然contentOffsetY 會變大 子視圖向上滑動 手勢傳遞 自然contentOffsetY 會變小 從而影響臨界點(diǎn)問題
CGFloat offset = scrollView.contentOffset.y + scrollView.contentInset.top;
//伸縮
if (offset <= 0) {
self.flexView.top = 0;
self.flexView.height = fabs(offset) + kContentInsetTop;
CGFloat percent = self.flexView.height / kContentInsetTop;
//寬度整體擴(kuò)大
self.flexView.width = WIDTH * percent;
self.flexView.left = - (WIDTH * (percent - 1) * 0.5);
} else {
CGFloat flexShowHeight = kStatusBarHeight + 30*ADAPTER_WIDTH;
CGFloat flexCriticalPoint = kContentInsetTop - flexShowHeight;
CGFloat minOffset = MIN(offset, flexCriticalPoint);
self.flexView.top = -minOffset;
self.flexView.height = kContentInsetTop;
//寬度整體恢復(fù)
self.flexView.width = WIDTH;
self.flexView.left = 0;
}
//頭部
CGFloat tableHeaderShowHeight = kStatusBarHeight + 50*ADAPTER_WIDTH;
CGFloat criticalPoint = self.mainView.tableHeaderView.height - tableHeaderShowHeight + kContentInsetTop;
if (self.canScroll) {
self.canMovePrevious = self.canMove;
if (ceil(offset) >= ceil(criticalPoint)) {
[scrollView setContentOffset:CGPointMake(0, criticalPoint - kContentInsetTop)];
self.canMove = NO;
} else {
self.canMove = YES;
//NSLog(@"向上移動");
}
if (self.canMove != self.canMovePrevious) {
if (self.canMove == NO && self.canMovePrevious == YES) {
//NSLog(@"不可以滑動 大于或等于臨界點(diǎn)");
//發(fā)送通知 必須針對 當(dāng)前的VC 不能一樣
[[NSNotificationCenter defaultCenter]postNotificationName:[NSString stringWithFormat:@"%@+%@+%ld",@"HomeSonVC",kNestingScrollGoTopNoti,self.managerVC.currentIndex] object:nil];
_canScroll = NO;
}
if (self.canMove == YES && self.canMovePrevious == NO) {
//NSLog(@"可以滑動 小于臨界點(diǎn)");
//[scrollView setContentOffset:CGPointMake(0, criticalPoint)];
}
}
} else {
[scrollView setContentOffset:CGPointMake(0, criticalPoint - kContentInsetTop)];
}
}
bug匯總
如果懸停和managerVC的子控制器都是靠著網(wǎng)絡(luò)請求獲取 需要cell代理方法中添加判斷是否網(wǎng)絡(luò)請求成功 還有就是rowHeight在懶加載是0 需要重新賦值
崩潰閃退-滑動問題.png
-
防止一直轉(zhuǎn)
防止一直轉(zhuǎn).png