iOS开发之多表视图滑动切换示例(仿"头条"客户端)
【大咖・来了 第7期】10月24日晚8点观看《智能导购对话机器人实践》 好长时间没为大家带来iOS开发干货的东西了,今天给大家分享一个头条新闻客户端各个类别进行切换的一个示例。在Demo中对所需的组件进行的简单封装,在封装的组件中使用的是纯代码的形式,如果想要在项目中进行使用,稍微进行修改即可。 废话少说,先介绍一下功能点,下图是整个Demo的功能点,最上面左边的TabBarButtonItem是用来减少条目的,比如下图有三个按钮,点击减号会减少一个条目。右边的为增加一个条目。点击相应的按钮是切换到对应的表视图上,下方红色的是滑动的指示器,同时支持手势滑动。运行具体效果如下图所示。 一:实现方案 最上方是一个View, View上面实例化了一些按钮,平分屏幕的宽度,下方是一个ScrollView, ScrollView上面放了一些表视图,点击不同的Button, 滑动到对应的表示图上。除了点击按钮,还可以进行滑动切换,切换时,红色的指示器也会随之滑动。 主要的技术点就是通过ScrollView的回调,通过事件的响应来改变ScrollView的ContentOffset的值。在回调中根据ContentOffset的值来计算红色指示器的偏移量。 二:核心代码 1.组件中的主要属性 把上面整个视图进行了封装,命名为SlideTabBarView,下面的代码是主要属性: @interfaceSlideTabBarView()///@brife整个视图的大小 @property(assign)CGRectmViewFrame; ///@brife下方的ScrollView @property(strong,nonatomic)UIScrollView*scrollView; ///@brife上方的按钮数组 @property(strong,nonatomic)NSMutableArray*topViews; ///@brife下方的表格数组 @property(strong,nonatomic)NSMutableArray*scrollTableViews; ///@brifeTableViews的数据源 @property(strong,nonatomic)NSMutableArray*dataSource; ///@brife当前选中页数 @property(assign)NSIntegercurrentPage; ///@brife下面滑动的View @property(strong,nonatomic)UIView*slideView; @end 2.初始化方法如下,在调用初始化方法时需要传入SlideTabBarView的frame和选项卡的个数,初始化函数会调用一系列的初始化方法对组件进行初始化,代码如下: -(instancetype)initWithFrame:(CGRect)frameWithCount:(NSInteger)count{ self=[superinitWithFrame:frame]; if(self){ _mViewFrame=frame; _tabCount=count; _topViews=[[NSMutableArrayalloc]init]; _scrollTableViews=[[NSMutableArrayalloc]init]; [selfinitDataSource]; [selfinitScrollView]; [selfinitTopTabs]; [selfinitDownTables]; [selfinitDataSource]; [selfinitSlideView]; } returnself; } 3.initDataSource方法主要负责模拟生成下方TableView要显示的数据。代码如下: #pragmamark--初始化表格的数据源 -(void)initDataSource{ _dataSource=[[NSMutableArrayalloc]initWithCapacity:_tabCount]; for(inti=1;i<=_tabCount;i++){ NSMutableArray*tempArray=[[NSMutableArrayalloc]initWithCapacity:20]; for(intj=1;j<=20;j++){ NSString*tempStr=[NSStringstringWithFormat:@"我是第%d个TableView的第%d条数据。",i,j]; [tempArrayaddObject:tempStr]; } [_dataSourceaddObject:tempArray]; } } 4.红色滑动指示器的初始化代码如下所示: #pragmamark--初始化滑动的指示View -(void)initSlideView{ CGFloatwidth=_mViewFrame.size.width/_tabCount; _slideView=[[UIViewalloc]initWithFrame:CGRectMake(0,TOPHEIGHT-5,width,5)]; [_slideViewsetBackgroundColor:[UIColorredColor]]; [selfaddSubview:_slideView]; } 5.ScrollView的初始化代码如下, 指定ScrollView的大小位置以及背景颜色,并且设置分页可用并添加代理。 #pragmamark--实例化ScrollView -(void)initScrollView{ _scrollView=[[UIScrollViewalloc]initWithFrame:CGRectMake(0,_mViewFrame.origin.y,_mViewFrame.size.width,_mViewFrame.size.height-TOPHEIGHT)]; _scrollView.contentSize=CGSizeMake(_mViewFrame.size.width*_tabCount,_mViewFrame.size.height-60); _scrollView.backgroundColor=[UIColorgrayColor]; _scrollView.pagingEnabled=YES; _scrollView.delegate=self; [selfaddSubview:_scrollView]; } 6.添加上方的按钮,根据传入的个数来实例化多个按钮。 #pragmamark--实例化顶部的tab -(void)initTopTabs{ CGFloatwidth=_mViewFrame.size.width/_tabCount; for(inti=0;i<_tabCount;i++){ UIView*view=[[UIViewalloc]initWithFrame:CGRectMake(i*width,0,width,TOPHEIGHT)]; view.backgroundColor=[UIColorlightGrayColor]; if(i%2){ view.backgroundColor=[UIColorgrayColor]; } UIButton*button=[[UIButtonalloc]initWithFrame:CGRectMake(0,0,width,TOPHEIGHT)]; button.tag=i; [buttonsetTitle:[NSStringstringWithFormat:@"按钮%d",i+1]forState:UIControlStateNormal]; [buttonaddTarget:selfaction:@selector(tabButton:)forControlEvents:UIControlEventTouchUpInside]; [viewaddSubview:button]; [_topViewsaddObject:view]; [selfaddSubview:view]; } } 7.点击按钮触发的方法如下: #pragmamark--点击顶部的按钮所触发的方法 -(void)tabButton:(id)sender{ UIButton*button=sender; [_scrollViewsetContentOffset:CGPointMake(button.tag*_mViewFrame.size.width,0)animated:YES]; } 8.初始化下方的多个表视图:实例化表视图,并指定委托回调。 #pragmamark--初始化下方的TableViews -(void)initDownTables{ for(inti=0;i<_tabCount;i++){ UITableView*tableView=[[UITableViewalloc]initWithFrame:CGRectMake(i*_mViewFrame.size.width,0,_mViewFrame.size.width,_mViewFrame.size.height-TOPHEIGHT)]; tableView.delegate=self; tableView.dataSource=self; [_scrollTableViewsaddObject:tableView]; [_scrollViewaddSubview:tableView]; } } 9.ScrollView的回调方法如下,下面***一个代理方法是根据ScrollView的偏移量来计算红色指示器的偏移量,第二个是滑动到哪个tableView,然后进行哪个TableView的数据加载。 #pragmamark--scrollView的代理方法 -(void)scrollViewDidEndScrollingAnimation:(UIScrollView*)scrollView{ [selfscrollViewDidEndDecelerating:scrollView]; } -(void)scrollViewDidEndDecelerating:(UIScrollView*)scrollView { _currentPage=_scrollView.contentOffset.x/_mViewFrame.size.width; UITableView*currentTable=_scrollTableViews[_currentPage]; [currentTablereloadData]; } -(void)scrollViewDidScroll:(UIScrollView*)scrollView{ if([_scrollViewisEqual:scrollView]){ CGRectframe=_slideView.frame; frame.origin.x=scrollView.contentOffset.x/_tabCount; _slideView.frame=frame; } } 10.TableView的代理方法如下,数据源就是我们刚才做的假数据,Cell是由Xib实现的,使用的时候注册一下就可用了。 pragmamark--talbeView的代理方法 -(NSInteger)numberOfSectionsInTableView:(UITableView*)tableView{ return1; } -(NSInteger)tableView:(UITableView*)tableViewnumberOfRowsInSection:(NSInteger)section{ NSMutableArray*tempArray=_dataSource[_currentPage]; returntempArray.count; } -(CGFloat)tableView:(UITableView*)tableViewheightForRowAtIndexPath:(NSIndexPath*)indexPath{ return60; } -(UITableViewCell*)tableView:tableViewcellForRowAtIndexPath:(NSIndexPath*)indexPath{ BOOLnibsRegistered=NO; if(!nibsRegistered){ UINib*nib=[UINibnibWithNibName:@"SlideBarCell"bundle:nil]; [tableViewregisterNib:nibforCellReuseIdentifier:@"SlideBarCell"]; nibsRegistered=YES; } SlideBarCell*cell=[tableViewdequeueReusableCellWithIdentifier:@"SlideBarCell"]; if([tableViewisEqual:_scrollTableViews[_currentPage]]){ cell.tipTitle.text=_dataSource[_currentPage][indexPath.row]; } returncell; } Demo在GitHub上的分享地址:https://github.com/lizelu/SliderTabBar 【责任编辑: chenqingxiang TEL:(010)68476606】