横向滑动懒加载效果+升级版

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
上一篇下一篇

猜你喜欢

热点阅读