横向滑动懒加载效果+升级版
2018-09-19 本文已影响43人
宙斯YY
一.基础版本
导航条置顶样式
1.jpeg
这里导航条和内容列表是分离的,所以在UI处理上也可以分离,只要实现懒加载效果就行。
思路:核心点是两个,UIViewController childViewController的使用;scrollview滑动结束后加载数据。
1.主控制器中添加子控制器
UIScrollView * scrollview=[[UIScrollView alloc]initWithFrame:CGRectMake(0, 50, SDScreenWidth, SDScreenHeight-50)];
int index=0;
NSMutableArray * vcnames=[NSMutableArray arrayWithObjects:@"1",@"2",nil];
scrollview.contentSize=CGSizeMake(SDScreenWidth*vcnames.count, scrollview.height);
for(int i=0;i<vcnames.count;i++)
{
NSString * vcname=vcnames[i];
UIViewController * vc=[[NSClassFromString(vcname) alloc]init];
[self addChildViewController:vc];
if(i==index)
{
vc.view.frame=CGRectMake(index*scrollview.width, 0, scrollview.width, scrollview.height);
[scrollview addSubview:vc.view];
scrollview.contentOffset=CGPointMake(index*scrollview.width, 0);
}
}
2.实现懒加载效果(滑动结束后加载页面+按钮点击结束后加载页面)
-(void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
CGFloat width=scrollView.width;
CGFloat height=scrollView.height;
index=scrollView.contentOffset.x/width;
UIViewController * vc=self.childViewControllers[index];
if(![vc isViewLoaded])
{
vc.view.frame=CGRectMake(width*index, 0, width, height);
[scrollView addSubview:vc.view];
}
}
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
[self scrollViewDidEndDecelerating:scrollView];
}
3.处理点击引导条处理
-(void)tap:(UIButton*)btn
{
index=btn.tag;
[scrollview setContentOffset:CGPointMake(index*scrollview.width, 0) animated:YES];
}
二.升级版本
导航条置顶样式
2.jpeg
这里导航条和内容列表是联动的,且上滑时导航条卡住不动。
思路:整体是一个主UITableView,每个栏目是子控制器的内部UITableView。
问题:当导航条不在顶部的时候,滑动列表时子列表跟随主列表滑动;当导航条到达顶部时,滑动列表时子列表滑动,主列表不滑动。
1.建立主容器类和子容器类ContainerNestViewController,ContainerNestSubViewController。
ContainerNestViewController.h
@interface ContainerNestMainTableView:UITableView<UIGestureRecognizerDelegate>
@end
@interface ContainerNestViewController : BaseViewController
@property(nonatomic,assign) NSInteger currentPage;
@property(nonatomic,assign) BOOL subcansc;
@property(nonatomic,assign) BOOL maincansc;
//主TableView
@property(nonatomic,weak) ContainerNestMainTableView * mainTableView;
//子控制器导航条
@property(nonatomic,weak) ContainerNestNavView * navsubControllerView;
//子控制器导航条-navView
@property(nonatomic,weak) UIScrollView * navView;
//子控制器导航条-sliderview
@property(nonatomic,weak) UIView * sliderview;
//子控制器TableViewCell
@property(nonatomic,weak) UITableViewCell * subContentView;
//子控制器TableViewCell-scrollview
@property(nonatomic,weak) UIScrollView * scrollview;
@property(nonatomic,strong)NSArray<ContainerNestSubViewController*> * controllers;
//刷新子控制器滑动
-(void)refreshScrollviewIndex;
//刷新子控制器导航条
-(void)refreshNavScrollviewIndex;
ContainerNestViewController.m
@implementation ContainerNestMainTableView
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
@end
@interface ContainerNestViewController ()<UIScrollViewDelegate,UIGestureRecognizerDelegate>
@end
@implementation ContainerNestViewController
#pragma mark - Setter and Getter
-(void)setControllers:(NSArray<ContainerNestSubViewController *> *)controllers
{
_controllers=controllers;
for(int i=0;i<controllers.count;i++)
{
ContainerNestSubViewController * subvc=controllers[i];
subvc.block = ^(UIScrollView *scrollview, BOOL isUpping) {
[self controlSubScrollView:scrollview];
self.mainTableView.bounces=isUpping;
};
subvc.block2 = ^(BOOL isDrag) {
self.scrollview.scrollEnabled=!isDrag;
};
[self addChildViewController:subvc];
}
}
-(void)setMainTableView:(ContainerNestMainTableView *)mainTableView
{
_mainTableView=mainTableView;
_mainTableView.bounces=NO;
_mainTableView.showsVerticalScrollIndicator=NO;
_mainTableView.showsHorizontalScrollIndicator=NO;
[self.mainTableView registerNib:[UINib nibWithNibName:@"ContainerNestContentTableViewCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"containerNestContentTableViewCell"];
}
-(ContainerNestNavView *)navsubControllerView
{
ContainerNestNavView * view=[ContainerNestNavView shareView];
view.currentPage=self.currentPage;
view.controllers=self.controllers;
view.block = ^(NSInteger btnTag) {
self.currentPage=btnTag;
[self refreshScrollviewIndex];
[self refreshNavScrollviewIndex];
};
self.navView=view.navView;
self.sliderview=view.sliderview;
return view;
}
-(UITableViewCell *)subContentView
{
ContainerNestContentTableViewCell * contentcell=[self.mainTableView dequeueReusableCellWithIdentifier:@"containerNestContentTableViewCell"];
contentcell.selectionStyle=UITableViewCellSelectionStyleNone;
contentcell.contentScrollView.delegate=self;
self.scrollview=contentcell.contentScrollView;
contentcell.contentScrollView.contentSize=CGSizeMake(SDScreenWidth*self.controllers.count,self.view.height);
return contentcell;
}
#pragma mark - 解决手势冲突+滑动处理
-(void)controlSubScrollView:(UIScrollView*)scrollview
{
if (self.maincansc) {
scrollview.contentOffset = CGPointZero;
}else
{
if (scrollview.contentOffset.y <= 0) {
self.maincansc = YES;
self.subcansc = NO;
}else if (scrollview.contentOffset.y > 0) {
self.maincansc = NO;
self.subcansc = YES;
}
}
}
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGRect navRect=[self.mainTableView rectForSection:1];
if(self.mainTableView.contentOffset.y>=navRect.origin.y)
{
if(self.maincansc)
{
self.maincansc = NO;
self.subcansc = YES;
self.mainTableView.contentOffset=CGPointMake(0, navRect.origin.y);
}
}else
{
if(self.maincansc ==NO&&self.subcansc ==YES)
{
self.subcansc = YES;
self.maincansc = NO;
self.mainTableView.contentOffset=CGPointMake(0, navRect.origin.y);
}else
{
self.subcansc = NO;
self.maincansc = YES;
}
}
}
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
if(scrollView==self.scrollview)
{
[self scrollViewDidEndScrollingAnimation:scrollView];
}
}
-(void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
if(scrollView==self.scrollview)
{
self.currentPage =(int)(self.scrollview.contentOffset.x/SDScreenWidth);
[self refreshScrollviewIndex];
}
}
-(void) refreshScrollviewIndex
{
UIViewController * vc = self.childViewControllers[self.currentPage];
if(![vc isViewLoaded])
{
vc.view.frame=CGRectMake(self.scrollview.width*self.currentPage, 0, self.scrollview.width, self.scrollview.height);
[self.scrollview addSubview:vc.view];
}
[self.scrollview setContentOffset:CGPointMake(self.currentPage*SDScreenWidth, 0) animated:YES];
[self refreshNavScrollviewIndex];
}
-(void)refreshNavScrollviewIndex
{
for(int i=0;i<self.navView.subviews.count;i++)
{
UIView * subview=self.navView.subviews[i];
if([subview isKindOfClass:UIButton.class])
{
UIButton * btn=(UIButton*)subview;
if(btn.tag==self.currentPage)
{
btn.selected=YES;
self.sliderview.centerX=btn.centerX;
[self.navView scrollRectToVisible:btn.frame animated:YES];
}else
{
btn.selected=NO;
}
}
}
}
ContainerNestSubViewController.h
//isUpping-滑动方向
typedef void(^ContainerNestSubViewControllerBlock)(UIScrollView*scrollview,BOOL isUpping);
typedef void(^ContainerNestSubViewControllerBlock2)(BOOL isDrag);
@interface ContainerNestSubViewController : BaseViewController
@property(nonatomic,copy) ContainerNestSubViewControllerBlock block;
@property(nonatomic,copy) ContainerNestSubViewControllerBlock2 block2;
@end
ContainerNestSubViewController.m
@interface ContainerNestSubViewController ()<UIScrollViewDelegate>
{
CGFloat oldY;
}
@end
@implementation ContainerNestSubViewController
-(void)addSubViews
{
[super addSubViews];
}
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
if(_block2&&self.baseTableview)
{
_block2(YES);
oldY = scrollView.contentOffset.y;
}
}
-(void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
{
if(_block2&&self.baseTableview)
{
_block2(NO);
}
}
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
//传递滑动方向,上拉无弹簧效果,下拉有弹簧效果(可下拉加载)
if(_block&&self.baseTableview)
{
if (scrollView.contentOffset.y>oldY) {
_block(scrollView,NO);
}
else{
_block(scrollView,YES);
}
}
}
2.建立导航条ContainerNestNavView和ContainerNestContentTableViewCell(ScrollView)
ContainerNestNavView.h
typedef void(^ContainerNestNavViewBlock)(NSInteger btnTag);
@interface ContainerNestNavView : UIView
@property(nonatomic,assign) NSInteger currentPage;
@property(nonatomic,weak) UIScrollView * navView;
@property(nonatomic,weak) UIView * sliderview;
@property(nonatomic,strong)NSArray<ContainerNestSubViewController*> * controllers;
@property(nonatomic,copy)ContainerNestNavViewBlock block;
+(instancetype)shareView;
ContainerNestNavView.m
@interface ContainerNestNavView()
@end
@implementation ContainerNestNavView
+(instancetype)shareView
{
return [[self alloc]initWithFrame:CGRectMake(0, 0, SDScreenWidth,ContainerNestNavViewHeight)];
}
-(instancetype)initWithFrame:(CGRect)frame
{
if(self=[super initWithFrame:frame])
{
self.backgroundColor=[UIColor whiteColor];
UIView * sepv=[[UIView alloc]initWithFrame:CGRectMake(0, 39, SDScreenWidth, 1)];
sepv.backgroundColor=SDColor(246, 246, 246);
[self addSubview:sepv];
UIScrollView * navs=[[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, SDScreenWidth, 39)];
navs.showsVerticalScrollIndicator=NO;
navs.showsHorizontalScrollIndicator=NO;
[self addSubview:navs];
UIView * sliderview=[[UIView alloc]initWithFrame:CGRectMake(0, 37, 20, 2)];
sliderview.backgroundColor=ThemeColor;
[navs addSubview:sliderview];
self.sliderview=sliderview;
self.navView=navs;
}
return self;
}
-(void)setControllers:(NSArray<ContainerNestSubViewController *> *)controllers
{
_controllers=controllers;
CGFloat sumTextWidth=0.0;
for(int i=0;i<self.controllers.count;i++)
{
ContainerNestSubViewController * subvc=self.controllers[i];
CGFloat textWidth=[subvc.title widthForText:SDFontOf14]+30;
UIButton * btn=[[UIButton alloc]initWithFrame:CGRectMake(sumTextWidth, 0, textWidth, 39)];
btn.tag=i;
btn.titleLabel.font=SDFontOf14;
[btn setTitleColor:SDColor(63, 63, 63) forState:UIControlStateNormal];
[btn setTitleColor:ThemeColor forState:UIControlStateSelected];
[btn setTitle:subvc.title forState:UIControlStateNormal];
[[btn rac_signalForControlEvents:UIControlEventTouchUpInside]subscribeNext:^(__kindof UIControl * _Nullable x) {
if(self.block)
{
self.block(x.tag);
}
}];
[self.navView addSubview:btn];
if(i==self.currentPage)
{
btn.selected=YES;
self.sliderview.centerX=btn.centerX;
}
sumTextWidth+=textWidth;
}
self.navView.contentSize=CGSizeMake(sumTextWidth, self.navView.height);
}
ContainerNestContentTableViewCell.h
@interface ContainerNestContentTableViewCell : UITableViewCell
@property (weak, nonatomic) IBOutlet UIScrollView *contentScrollView;
@end
ContainerNestContentTableViewCell.m
@interface ContainerNestContentTableViewCell()
@end
@implementation ContainerNestContentTableViewCell
- (void)awakeFromNib {
[super awakeFromNib];
self.contentScrollView.pagingEnabled=YES;
}
3.应用
主控制器
StoreViewController.h
@interface StoreViewController : ContainerNestViewController
@property(strong, nonatomic) ContainerNestMainTableView *tableview;
@end
StoreViewController.m
#pragma mark - UITableView数据源和代理
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 2;
}
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
if(section==0)
{
return 0;
}else
{
return 40;
}
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.section==0)
{
//自定义Cell高度
}else
{
return self.view.height;
}
return 0.0;
}
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
if(section==1)
{
return self.navsubControllerView;
}
return [[UIView alloc]init];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if(section==0)
{
//自定义Cell数目
}else if(section==1)
{
return 1;
}
return 0;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.section==0)
{
//自定义Cell
}
else if(indexPath.section==1)
{
return self.subContentView;
}
return nil;
}
子控制器就是继承ContainerNestSubViewController的普通控制器
StoreContentViewController_sub.h
@interface StoreContentViewController_sub : ContainerNestSubViewController
@end