How To Use Multiple View Controller In Single Page In Xamarin iOS

How To Use Multiple View Controller In Single Page In Xamarin iOS
 

Introduction

 
In this blog, I will explain how to handle multiple view controllers on a single page in Xamarin iOS. If you're interested in learning this, just read the entire post. Since there is no default functionality for showing multiple view controllers in iOS, some of the application designs are complicated too. In such circumstances hiding & showing views in single ViewController is not the smart way. So, we need to separate the views. In this sample, I have created multiple ViewController's to present on a single page. Here, I will show you how to present multiple view controllers in a single page.
 
iOS output
 
How To Use Multiple View Controller In Single Page In Xamarin iOS
 
Prerequisites
  • Visual Studio 2019 
  • XCode 10.0 or above
  • Physical device or simulator 
  • This project is created in Visual Studio 2019 for Mac
Let's start.
 
Step 1
 
Create Xamarin iOS Single View Application by navigating to Visual Studio File Menu >> New Project >> In the dialog window >> select left plane App under iOS and center plane select Single View Application and click Next.
 
How To Use Multiple View Controller In Single Page In Xamarin iOS
 
Step 2
 
In the next window, give your application a name, target version & device type (tab or mobile), organize & bundle identifier and click OK.
 
How To Use Multiple View Controller In Single Page In Xamarin iOS
 
Step 3
 
After the project creation, you will get a folder structure like below.
 
How To Use Multiple View Controller In Single Page In Xamarin iOS
 
Now, open storyboard in your interface builder using the right click of Main.Storyboard >> in the context menu select Open with >> forwarded by XCode Interface Builder. 
 
How To Use Multiple View Controller In Single Page In Xamarin iOS
 
Step 4
 
It's time to design our interface. Default one view controller will be there. We should place Navigation Controller in-front of Initial View Controller. Drag and drop the UICollectionView and View. Here, collection view for creating a tabbed page and view for set another controller view to this view, because there is no default control for the tabbed page and set this collection view height and constraints as per your requirements. Create an outlet for CollectionView and View as collectionView and baseView.
 
How To Use Multiple View Controller In Single Page In Xamarin iOS

Next, select collection view and open properties plane and set the size is None.
 
How To Use Multiple View Controller In Single Page In Xamarin iOS
 

Add First View Controller

 
Next, drag and drop the new view controller and set the background color as red and add a label view in the center of the page. Create a new ViewController class named as FirstViewController to assign this ViewController.
 
How To Use Multiple View Controller In Single Page In Xamarin iOS
 

Add Second View Controller

 
Similarly, create another view controller and set the background color as yellow and place one label in the center of the page, as well as creating another view controller class named SecondViewController to assign to this View Controller.
 
How To Use Multiple View Controller In Single Page In Xamarin iOS
 
fFnally, your storyboard looks like below,
 
How To Use Multiple View Controller In Single Page In Xamarin iOS
 
Step 5
 
Now, add new Collection View Cell for tab design using right-click the solution >> add >> new File >> new dialog window will appear, in the left plane select iOS,>> center plane, select Collection View Cell and give the name as TabCollectionViewCell and then click Add.
 
How To Use Multiple View Controller In Single Page In Xamarin iOS
 

Design Collection View Cell

 
Next, open this Collection View Cell in an Interface builder. Add the following views in the collection view cell.
  • Label - Tab title
  • View - Active tab indicator
The label is in the center of the cell and view height is 5. Set the perfect constraint for this view. If the constraint is missing, no view will be present in the view controller. Create an outlet for this view to access from the code behind.
 
How To Use Multiple View Controller In Single Page In Xamarin iOS
 
There is one problem --  to apply data to view, you couldn't access this outlet's from any other class, so we can create one method to update data for views
  1. internal void UpdateCell(string title, bool visible)  
  2.         {  
  3.             titleLabel.Text = title;  
  4.             titleLabel.TextColor = UIColor.White;  
  5.   
  6.             if (visible)  
  7.                 indicatorline.Hidden = false;  
  8.             else  
  9.                 indicatorline.Hidden = true;  
  10.         }  
Step 6
 
Next moving into the coding part. First, we are going to write a code for the collection view. The view needs CollectionView needs collection view source and delegate class.
 
In the collection view there is no way to give input directly, so we need to write source class and pass your data to this class. The delegate class is for cell item sizing and handling the item click event. Afterward, apply these two classes to this collection view.
 

Add Collection View Source Class

 
First, create a source class named CollectionViewSource and this class should be inherited from UICollectionViewSource and pass the data through the contractor. This page code is given below.
  1. public class CollectionViewSource : UICollectionViewSource  
  2.     {  
  3.         private List<string> titles;  
  4.         public static int selectedIndex;  
  5.   
  6.         public CollectionViewSource(List<string> titles, int Index)  
  7.         {  
  8.             this.titles = titles;  
  9.             selectedIndex = Index;  
  10.         }  
  11.         public override UICollectionViewCell GetCell(UICollectionView collectionView, NSIndexPath indexPath)  
  12.         {  
  13.             var cell = collectionView.DequeueReusableCell("TabCollectionViewCell", indexPath) as TabCollectionViewCell;  
  14.   
  15.             if (indexPath.Row == selectedIndex)  
  16.                 cell.UpdateCell(this.titles[indexPath.Row], true);  
  17.             else  
  18.                 cell.UpdateCell(this.titles[indexPath.Row], false);  
  19.   
  20.             return cell;  
  21.         }  
  22.         public override nint GetItemsCount(UICollectionView collectionView, nint section)  
  23.         {  
  24.             return titles.Count;  
  25.         }  
  26.     }  

Add the Collection View Delegate Class

 
Create another delegate class named CollectionViewSourceDelegate and this class should be inherited from UICollectionViewDelegateFlowLayout. In this class, a constructor is passing one ITab interface to the view controller.
  1. public class CollectionViewSourceDelegate : UICollectionViewDelegateFlowLayout  
  2.     {  
  3.         int listCount;  
  4.         ITab iTab;  
  5.         public CollectionViewSourceDelegate(int count, ITab iTab)  
  6.         {  
  7.             this.listCount = count;  
  8.             this.iTab = iTab;  
  9.         }  
  10.         public override nfloat GetMinimumInteritemSpacingForSection(UICollectionView collectionView, UICollectionViewLayout layout, nint section)  
  11.         {  
  12.             return 0;  
  13.         }  
  14.         public override CGSize GetSizeForItem(UICollectionView collectionView, UICollectionViewLayout layout, NSIndexPath indexPath)  
  15.         {  
  16.             var size = new CGSize();  
  17.             size.Width = collectionView.Frame.Width / 2;  
  18.             size.Height = collectionView.Frame.Height;  
  19.             return size;  
  20.         }  
  21.         public override void ItemSelected(UICollectionView collectionView, NSIndexPath indexPath)  
  22.         {  
  23.             iTab.OnTabChange(indexPath.Row);  
  24.             CollectionViewSource.selectedIndex = indexPath.Row;  
  25.             collectionView.ReloadData();  
  26.         }  
  27.     }  

Create ITab interface

 
Create a new Interface named ITab.cs by going to Solution Explorer >> Add new file >> select Interface and give the name as ITab and click Add. Add one method OntabChange and one integer parameter value.
  1. public interface ITab  
  2.     {  
  3.         void OnTabChange(int indexPath);  
  4.     }  
Next, open ViewController.cs file. First, we need to setup view controllers and present them into view. Add the FirstViewController and SecondViewController as Child View Controller of this class and set the bounds equal of baseView view. Load the view controller based on Index selection. In the OnTabMethod call the LoadViewMethod and pass the index. create a static string list and pass to collection view source class.
  1. using Foundation;  
  2. using System;  
  3. using System.Collections.Generic;  
  4. using UIKit;  
  5.   
  6. namespace ManageChildVC  
  7. {  
  8.     public partial class ViewController : UIViewController, ITab  
  9.     {  
  10.         private FirstChildViewController firstController;  
  11.         private SecondChildViewController secondController;  
  12.   
  13.         public ViewController(IntPtr handle) : base(handle)  
  14.         {  
  15.         }  
  16.   
  17.         public override void ViewDidLoad()  
  18.         {  
  19.             base.ViewDidLoad();  
  20.             // Perform any additional setup after loading the view, typically from a nib.  
  21.   
  22.             var tabTitles = new List<string>() { "Tab 1 💝""Tab 2 👨🏻‍💻" };  
  23.   
  24.             SetUpChildViewControllers();  
  25.   
  26.             collectionView.RegisterNibForCell(TabCollectionViewCell.Nib, "TabCollectionViewCell");  
  27.             collectionView.Source = new CollectionViewSource(tabTitles, 0);  
  28.             collectionView.Delegate = new CollectionViewSourceDelegate(tabTitles.Count, this);  
  29.             collectionView.ReloadData();  
  30.   
  31.             LoadController(0);  
  32.         }  
  33.   
  34.         private void SetUpChildViewControllers()  
  35.         {  
  36.             AddViewControllerAsChildViewController(FirstTabViewController());  
  37.             AddViewControllerAsChildViewController(SecondTabViewController());  
  38.         }  
  39.         public UIViewController FirstTabViewController()  
  40.         {  
  41.             firstController = this.Storyboard.InstantiateViewController("FirstChildViewController"as FirstChildViewController;  
  42.             return firstController;  
  43.         }  
  44.         public UIViewController SecondTabViewController()  
  45.         {  
  46.             secondController = this.Storyboard.InstantiateViewController("SecondChildViewController"as SecondChildViewController;  
  47.             return secondController;  
  48.         }  
  49.   
  50.         private void AddViewControllerAsChildViewController(UIViewController viewController)  
  51.         {  
  52.             this.AddChildViewController(viewController);  
  53.             View.AddSubview(viewController.View);  
  54.             viewController.View.Frame = ViewControllerSpace.Frame;  
  55.             viewController.DidMoveToParentViewController(this);  
  56.             viewController.View.Hidden = true;  
  57.         }  
  58.   
  59.         public override void DidReceiveMemoryWarning()  
  60.         {  
  61.             base.DidReceiveMemoryWarning();  
  62.             // Release any cached data, images, etc that aren't in use.  
  63.         }  
  64.   
  65.         public void OnTabChange(int indexPath)  
  66.         {  
  67.             LoadController(indexPath);  
  68.         }  
  69.   
  70.         private void LoadController(int indexPath)  
  71.         {  
  72.             collectionView.ReloadData();  
  73.   
  74.             if (indexPath == 0)  
  75.             {  
  76.                 firstController.View.Hidden = false;  
  77.                 secondController.View.Hidden = true;  
  78.             }  
  79.             else if (indexPath == 1)  
  80.             {  
  81.                 firstController.View.Hidden = true;  
  82.                 secondController.View.Hidden = false;  
  83.             }  
  84.         }  
  85.     }  
  86. }  
Step 7
 
Now, run the application, you will get a view like below, select the tabs, based on tab selection the view will change.
 
How To Use Multiple View Controller In Single Page In Xamarin iOS
 
The full source code is here 
 

Conclusion

 
In this blog, we learned to handle the view controllers in iOS. Thanks for reading, and please share your comments.