好長時間沒為大家帶來iOS開發乾貨的東西了,今天給大家分享一個頭條新聞客戶端各個類別進行切換的一個示例。在Demo中對所需的元件進行的簡單封裝,在封裝的元件中使用的是純程式碼的形式,如果想要在專案中進行使用,稍微進行修改即可。
廢話少說,先介紹一下功能點,下圖是整個Demo的功能點,最上面左邊的TabBarButtonItem是用來減少條目的,比如下圖有三個按鈕,點選減號會減少一個條目。右邊的為增加一個條目。點選相應的按鈕是切換到對應的表檢視上,下方紅色的是滑動的指示器,同時支援手勢滑動。執行具體效果如下圖所示。
一:實現方案
最上方是一個View, View上面例項化了一些按鈕,平分螢幕的寬度,下方是一個ScrollView, ScrollView上面放了一些表檢視,點選不同的Button, 滑動到對應的表示圖上。除了點選按鈕,還可以進行滑動切換,切換時,紅色的指示器也會隨之滑動。
主要的技術點就是通過ScrollView的回撥,通過事件的響應來改變ScrollView的ContentOffset的值。在回撥中根據ContentOffset的值來計算紅色指示器的偏移量。
二:核心程式碼
1.元件中的主要屬性
把上面整個檢視進行了封裝,命名為SlideTabBarView,下面的程式碼是主要屬性:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
@interface SlideTabBarView() 2 ///@brife 整個檢視的大小 @property (assign) CGRect mViewFrame; ///@brife 下方的ScrollView @property (strong, nonatomic) UIScrollView *scrollView; ///@brife 上方的按鈕陣列 @property (strong, nonatomic) NSMutableArray *topViews; ///@brife 下方的表格陣列 @property (strong, nonatomic) NSMutableArray *scrollTableViews; ///@brife TableViews的資料來源 @property (strong, nonatomic) NSMutableArray *dataSource; ///@brife 當前選中頁數 @property (assign) NSInteger currentPage; ///@brife 下面滑動的View @property (strong, nonatomic) UIView *slideView; @end |
2.初始化方法如下,在呼叫初始化方法時需要傳入SlideTabBarView的frame和選項卡的個數,初始化函式會呼叫一系列的初始化方法對元件進行初始化,程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
-(instancetype)initWithFrame:(CGRect)frame WithCount: (NSInteger) count{ self = [super initWithFrame:frame]; if (self) { _mViewFrame = frame; _tabCount = count; _topViews = [[NSMutableArray alloc] init]; _scrollTableViews = [[NSMutableArray alloc] init]; [self initDataSource]; [self initScrollView]; [self initTopTabs]; [self initDownTables]; [self initDataSource]; [self initSlideView]; } return self; } |
3.initDataSource方法主要負責模擬生成下方TableView要顯示的資料。程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#pragma mark -- 初始化表格的資料來源 -(void) initDataSource{ _dataSource = [[NSMutableArray alloc] initWithCapacity:_tabCount]; for (int i = 1; i ) { NSMutableArray *tempArray = [[NSMutableArray alloc] initWithCapacity:20]; for (int j = 1; j 20; j ++) { NSString *tempStr = [NSString stringWithFormat:@"我是第%d個TableView的第%d條資料。", i, j]; [tempArray addObject:tempStr]; } [_dataSource addObject:tempArray]; } } |
4.紅色滑動指示器的初始化程式碼如下所示:
1 2 3 4 5 6 7 |
#pragma mark -- 初始化滑動的指示View -(void) initSlideView{ CGFloat width = _mViewFrame.size.width / _tabCount; _slideView = [[UIView alloc] initWithFrame:CGRectMake(0, TOPHEIGHT - 5, width, 5)]; [_slideView setBackgroundColor:[UIColor redColor]]; [self addSubview:_slideView]; } |
5.ScrollView的初始化程式碼如下, 指定ScrollView的大小位置以及背景顏色,並且設定分頁可用並新增代理。
1 2 3 4 5 6 7 8 9 10 11 |
#pragma mark -- 例項化ScrollView -(void) initScrollView{ _scrollView = [[UIScrollView alloc] 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 = [UIColor grayColor]; _scrollView.pagingEnabled = YES; _scrollView.delegate = self; [self addSubview:_scrollView]; } |
6.新增上方的按鈕,根據傳入的個數來例項化多個按鈕。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
#pragma mark -- 例項化頂部的tab -(void) initTopTabs{ CGFloat width = _mViewFrame.size.width / _tabCount; for (int i = 0; i ) { UIView *view = [[UIView alloc] initWithFrame:CGRectMake(i * width, 0, width, TOPHEIGHT)]; view.backgroundColor = [UIColor lightGrayColor]; if (i % 2) { view.backgroundColor = [UIColor grayColor]; } UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, width, TOPHEIGHT)]; button.tag = i; [button setTitle:[NSString stringWithFormat:@"按鈕%d", i+1] forState:UIControlStateNormal]; [button addTarget:self action:@selector(tabButton:) forControlEvents:UIControlEventTouchUpInside]; [view addSubview:button]; [_topViews addObject:view]; [self addSubview:view]; } } |
7.點選按鈕觸發的方法如下:
1 2 3 4 5 |
#pragma mark --點選頂部的按鈕所觸發的方法 -(void) tabButton: (id) sender{ UIButton *button = sender; [_scrollView setContentOffset:CGPointMake(button.tag * _mViewFrame.size.width, 0) animated:YES]; } |
8.初始化下方的多個表檢視:例項化表檢視,並指定委託回撥。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#pragma mark --初始化下方的TableViews -(void) initDownTables{ for (int i = 0; i ) { UITableView *tableView = [[UITableView alloc] initWithFrame:CGRectMake(i * _mViewFrame.size.width, 0, _mViewFrame.size.width, _mViewFrame.size.height - TOPHEIGHT)]; tableView.delegate = self; tableView.dataSource = self; [_scrollTableViews addObject:tableView]; [_scrollView addSubview:tableView]; } } |
9.ScrollView的回撥方法如下,下面最後一個代理方法是根據ScrollView的偏移量來計算紅色指示器的偏移量,第二個是滑動到哪個tableView,然後進行哪個TableView的資料載入。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#pragma mark -- scrollView的代理方法 -(void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView{ [self scrollViewDidEndDecelerating:scrollView]; } - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { _currentPage = _scrollView.contentOffset.x/_mViewFrame.size.width; UITableView *currentTable = _scrollTableViews[_currentPage]; [currentTable reloadData]; } -(void)scrollViewDidScroll:(UIScrollView *)scrollView{ if ([_scrollView isEqual:scrollView]) { CGRect frame = _slideView.frame; frame.origin.x = scrollView.contentOffset.x/_tabCount; _slideView.frame = frame; } } |
10.TableView的代理方法如下,資料來源就是我們剛才做的假資料,Cell是由Xib實現的,使用的時候註冊一下就可用了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
#pragma mark -- talbeView的代理方法 -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ return 1; } -(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ NSMutableArray *tempArray = _dataSource[_currentPage]; return tempArray.count; } -(CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ return 60; } -(UITableViewCell *)tableView:tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ BOOL nibsRegistered=NO; if (!nibsRegistered) { UINib *nib=[UINib nibWithNibName:@"SlideBarCell" bundle:nil]; [tableView registerNib:nib forCellReuseIdentifier:@"SlideBarCell"]; nibsRegistered=YES; } SlideBarCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SlideBarCell"]; if ([tableView isEqual:_scrollTableViews[_currentPage]]) { cell.tipTitle.text = _dataSource[_currentPage][indexPath.row]; } return cell; } |
Demo在GitHub上的分享地址:https://github.com/lizelu/SliderTabBar
打賞支援我寫出更多好文章,謝謝!
打賞作者
打賞支援我寫出更多好文章,謝謝!