iOS development of multi-table view sliding switching example (imitating "Toutiao" client)

iOS development of multi-table view sliding switching example (imitating "Toutiao" client)

It's been a long time since I brought you some useful information about iOS development. Today, I'd like to share with you an example of switching between categories in a headline news client. In the demo, the required components are simply encapsulated, and the encapsulated components are in the form of pure code. If you want to use them in your project, you can just make some minor modifications.

Without further ado, let me introduce the functions first. The figure below shows the functions of the entire Demo. The TabBarButtonItem on the top left is used to reduce items. For example, there are three buttons in the figure below. Clicking the minus sign will reduce an item. The one on the right is to add an item. Clicking the corresponding button will switch to the corresponding table view. The red one below is the sliding indicator, which also supports gesture sliding. The specific effect of running is shown in the figure below.

1. Implementation plan

At the top is a View with some buttons instantiated on it, dividing the width of the screen equally. Below is a ScrollView with some table views placed on it. Click different buttons to slide to the corresponding representation. In addition to clicking buttons, you can also slide to switch. When switching, the red indicator will also slide.

The main technical point is to change the value of ScrollView's ContentOffset through the callback of ScrollView and the response of the event. In the callback, the offset of the red indicator is calculated according to the value of ContentOffset.

2. Core code

1. Main properties in the component

Encapsulate the entire view above and name it SlideTabBarView. The following code is the main properties:

  1. @interface SlideTabBarView() ///@brife The size of the entire view  
  2. @property (assign) CGRect mViewFrame;
  3. ///@brife ScrollView below  
  4. @property (strong, nonatomic) UIScrollView *scrollView;
  5. ///@brife Button array above  
  6. @property (strong, nonatomic) NSMutableArray *topViews;
  7. ///@brife The table array below  
  8. @property (strong, nonatomic) NSMutableArray *scrollTableViews;
  9. ///@brife TableViews data source  
  10. @property (strong, nonatomic) NSMutableArray *dataSource;
  11. ///@brife Current selected page number  
  12. @property (assign) NSInteger currentPage;
  13. ///@brife The sliding View below  
  14. @property (strong, nonatomic) UIView *slideView;
  15. @end  

2. The initialization method is as follows. When calling the initialization method, you need to pass in the frame of SlideTabBarView and the number of tabs. The initialization function will call a series of initialization methods to initialize the components. The code is as follows:

  1. -(instancetype)initWithFrame:(CGRect)frame WithCount: (NSInteger) count{
  2. self = [ super initWithFrame:frame];
  3.  
  4. if (self) {
  5. _mViewFrame = frame;
  6. _tabCount = count;
  7. _topViews = [[NSMutableArray alloc] init];
  8. _scrollTableViews = [[NSMutableArray alloc] init];
  9.  
  10. [self initDataSource];
  11.  
  12. [self initScrollView];
  13.  
  14. [self initTopTabs];
  15.  
  16. [self initDownTables];
  17.  
  18. [self initDataSource];
  19.  
  20. [self initSlideView];
  21.  
  22. }
  23.  
  24. return self;
  25. }

3. The initDataSource method is mainly responsible for simulating the generation of data to be displayed in the TableView below. The code is as follows:

  1. #pragma mark -- Initialize the data source of the table
  2. -( void ) initDataSource{
  3. _dataSource = [[NSMutableArray alloc] initWithCapacity:_tabCount];
  4.  
  5. for ( int i = 1 ; i <= _tabCount; i ++) {
  6.  
  7. NSMutableArray *tempArray = [[NSMutableArray alloc] initWithCapacity: 20 ];
  8.  
  9. for ( int j = 1 ; j <= 20 ; j ++) {
  10.  
  11. NSString *tempStr = [NSString stringWithFormat:@ "I am the %dth data in the %dth TableView." , i, j];
  12. [tempArray addObject:tempStr];
  13. }
  14.  
  15. [_dataSource addObject:tempArray];
  16. }
  17. }

4. The initialization code of the red sliding indicator is as follows:

  1. #pragma mark -- Initialize the sliding indication View
  2. -( void ) initSlideView{
  3. CGFloat width = _mViewFrame.size.width / _tabCount;
  4. _slideView = [[UIView alloc] initWithFrame:CGRectMake( 0 , TOPHEIGHT - 5 , width, 5 )];
  5. [_slideView setBackgroundColor:[UIColor redColor]];
  6. [self addSubview:_slideView];
  7. }

5. The initialization code of ScrollView is as follows, which specifies the size, position and background color of ScrollView, enables paging and adds a proxy.

  1. #pragma mark -- instantiate ScrollView
  2. -( void ) initScrollView{
  3. _scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake( 0 , _mViewFrame.origin.y, _mViewFrame.size.width, _mViewFrame.size.height - TOPHEIGHT)];
  4. _scrollView.contentSize = CGSizeMake(_mViewFrame.size.width * _tabCount, _mViewFrame.size.height - 60 );
  5. _scrollView.backgroundColor = [UIColor grayColor];
  6.  
  7. _scrollView.pagingEnabled = YES;
  8.  
  9. _scrollView.delegate = self;
  10. [self addSubview:_scrollView];
  11. }

6. Add the buttons above and instantiate multiple buttons according to the number passed in.

  1. #pragma mark -- instantiate the top tab
  2. -( void ) initTopTabs{
  3. CGFloat width = _mViewFrame.size.width / _tabCount;
  4.  
  5. for ( int i = 0 ; i < _tabCount; i ++) {
  6.  
  7. UIView *view = [[UIView alloc] initWithFrame:CGRectMake(i * width, 0 , width, TOPHEIGHT)];
  8.  
  9. view.backgroundColor = [UIColor lightGrayColor];
  10.  
  11. if (i % 2 ) {
  12. view.backgroundColor = [UIColor grayColor];
  13. }
  14.  
  15. UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake( 0 , 0 , width, TOPHEIGHT)];
  16. button.tag = i;
  17. [button setTitle:[NSString stringWithFormat:@ "Button%d" , i+ 1 ] forState:UIControlStateNormal];
  18. [button addTarget:self action: @selector (tabButton:) forControlEvents:UIControlEventTouchUpInside];
  19. [view addSubview:button];
  20.  
  21.  
  22. [_topViews addObject:view];
  23. [self addSubview:view];
  24. }
  25. }

7. Click the button to trigger the method as follows:

  1. #pragma mark --The method triggered by clicking the top button
  2. -( void ) tabButton: (id) sender{
  3. UIButton *button = sender;
  4. [_scrollView setContentOffset:CGPointMake(button.tag * _mViewFrame.size.width, 0 ) animated:YES];
  5. }

8. Initialize the multiple table views below: Instantiate the table views and specify the delegate callback.

  1. #pragma mark -- Initialize the TableViews below
  2. -( void ) initDownTables{
  3.  
  4. for ( int i = 0 ; i < _tabCount; i ++) {
  5.  
  6. UITableView *tableView = [[UITableView alloc] initWithFrame:CGRectMake(i * _mViewFrame.size.width, 0 , _mViewFrame.size.width, _mViewFrame.size.height - TOPHEIGHT)];
  7. tableView.delegate = self;
  8. tableView.dataSource = self;
  9.  
  10. [_scrollTableViews addObject:tableView];
  11. [_scrollView addSubview:tableView];
  12. }
  13. }

9. The callback method of ScrollView is as follows. The first proxy method below calculates the offset of the red indicator based on the offset of ScrollView. The second one is to slide to which tableView and then load the data of which TableView.

  1. #pragma mark -- scrollView proxy method
  2. -( void )scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView{
  3. [self scrollViewDidEndDecelerating:scrollView];
  4. }
  5. - ( void )scrollViewDidEndDecelerating:(UIScrollView *)scrollView
  6. {
  7. _currentPage = _scrollView.contentOffset.x/_mViewFrame.size.width;
  8.  
  9. UITableView *currentTable = _scrollTableViews[_currentPage];
  10. [currentTable reloadData];
  11.  
  12. }
  13. -( void )scrollViewDidScroll:(UIScrollView *)scrollView{
  14. if ([_scrollView isEqual:scrollView]) {
  15. CGRect frame = _slideView.frame;
  16. frame.origin.x = scrollView.contentOffset.x/_tabCount;
  17. _slideView.frame = frame;
  18. }
  19. }

10. The proxy method of TableView is as follows. The data source is the fake data we just made. Cell is implemented by Xib. It can be used by registering it when using it.

  1. Pragma mark -- talbeView's proxy method
  2. -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
  3. return   1 ;
  4. }
  5. -(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
  6. NSMutableArray *tempArray = _dataSource[_currentPage];
  7. return tempArray.count;
  8. }
  9. -(CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
  10. return   60 ;
  11. }
  12. -(UITableViewCell *)tableView:tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
  13.  
  14. BOOL nibsRegistered=NO;
  15. if (!nibsRegistered) {
  16. UINib *nib=[UINib nibWithNibName:@ "SlideBarCell" bundle:nil];
  17. [tableView registerNib:nib forCellReuseIdentifier:@ "SlideBarCell" ];
  18. nibsRegistered=YES;
  19. }
  20.  
  21.  
  22. SlideBarCell *cell = [tableView dequeueReusableCellWithIdentifier:@ "SlideBarCell" ];
  23. if ([tableView isEqual:_scrollTableViews[_currentPage]]) {
  24. cell.tipTitle.text = _dataSource[_currentPage][indexPath.row];
  25. }
  26.  
  27. return cell;
  28. }
  29.  
  30. Demo sharing address on GitHub: https://github.com/lizelu/SliderTabBar  

<<:  You should use Node.js for your side projects

>>:  Tutorials can make or break a game: A brief analysis of the design of a tutorial for new players

Recommend

3 steps to event planning and promotion!

The author summarizes the "three-part theory...

Breadth-first search algorithm applied to Swift mobile game development

[51CTO.com Quick Translation] Swift Algorithm Clu...

2021 Beauty and Skin Care Marketing Strategy

This may be the most comprehensive beauty and ski...

General Bradley's 2021 Trading Strategy Lecture

General Bradley's 2021 Trading Strategy Lectur...

Only 3 tricks are needed to attract traffic and promote Xiaohongshu!

Xiaohongshu App is hailed as a magic tool for you...

Can wood be worth a fortune? How to identify wood at a glance?

Not long ago, the water level of the Jialing Rive...

No offline business: Can Internet TV escape being a niche?

After experiencing a wave of Internet development...

28 classic programming algorithms you must read

The first ten are the top ten algorithms from the...

What player can be used to turn files into short videos?

What kind of video player should be installed if ...

Should I choose Blocks or Delegates during development?

[[150507]] Someone asked me a great question, whi...