How to use Multiple View Controller in Single Page in Xamarin iOS
Logesh Palani
Posted on February 2, 2020
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 really not the smart way. So, we need to separate the views. This sample, I have created multiple _ViewController'_s and to present on a single page. Here, I will show you to present multiple view controllers in a single page.
iOS output
Prerequisites
- Visual Studio 2019
- XCode 10.0 or above
- Physical device or simulator
- This project 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.
Step 2:
In the next window, give your application a name, target version & device type (tab or mobile), organize & bundle identifier and click OK.
Step 3:
After the project creation, you will get a folder structure like below.
Now, open storyboard in you interface builder using the right click of Main.Storyboard >> in the context menu select Open with >> forwarded by XCode Interface Builder.
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
Next, select collection view and open properties plane and set the size is None.
Add First View Controller
Next, drag and drop the new view controller and set the background color as red and add label view in the center of the page. Create a new ViewController class named as FirstViewController to assign this ViewController.
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 create another view controller class named SecondViewController to assign to this View Controller.
finally, your storyboard looks like below
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.
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 in the center of the cell and view height 5. Set the perfect constraint for this view. If the constraint are missing, no view will be present in the view controller. Create an outlet for this view to access from the code behind.
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
internal void UpdateCell(string title, bool visible)
{
titleLabel.Text = title;
titleLabel.TextColor = UIColor.White;
if (visible)
indicatorline.Hidden = false;
else
indicatorline.Hidden = true;
}
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. 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 for cell item sizing and handle 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.
public class CollectionViewSource : UICollectionViewSource
{
private List<string> titles;
public static int selectedIndex;
public CollectionViewSource(List<string> titles, int Index)
{
this.titles = titles;
selectedIndex = Index;
}
public override UICollectionViewCell GetCell(UICollectionView collectionView, NSIndexPath indexPath)
{
var cell = collectionView.DequeueReusableCell("TabCollectionViewCell", indexPath) as TabCollectionViewCell;
if (indexPath.Row == selectedIndex)
cell.UpdateCell(this.titles[indexPath.Row], true);
else
cell.UpdateCell(this.titles[indexPath.Row], false);
return cell;
}
public override nint GetItemsCount(UICollectionView collectionView, nint section)
{
return titles.Count;
}
}
Add the Collection View Delegate Class
Create another delegate class named CollectionViewSourceDelegate and this class should be inherited from UICollectionViewDelegateFlowLayout. In this class, constructor is passing one ITab interface to the view controller.
public class CollectionViewSourceDelegate : UICollectionViewDelegateFlowLayout
{
int listCount;
ITab iTab;
public CollectionViewSourceDelegate(int count, ITab iTab)
{
this.listCount = count;
this.iTab = iTab;
}
public override nfloat GetMinimumInteritemSpacingForSection(UICollectionView collectionView, UICollectionViewLayout layout, nint section)
{
return 0;
}
public override CGSize GetSizeForItem(UICollectionView collectionView, UICollectionViewLayout layout, NSIndexPath indexPath)
{
var size = new CGSize();
size.Width = collectionView.Frame.Width / 2;
size.Height = collectionView.Frame.Height;
return size;
}
public override void ItemSelected(UICollectionView collectionView, NSIndexPath indexPath)
{
iTab.OnTabChange(indexPath.Row);
CollectionViewSource.selectedIndex = indexPath.Row;
collectionView.ReloadData();
}
}
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.
public interface ITab
{
void OnTabChange(int indexPath);
}
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.
using Foundation;
using System;
using System.Collections.Generic;
using UIKit;
namespace ManageChildVC
{
public partial class ViewController : UIViewController, ITab
{
private FirstChildViewController firstController;
private SecondChildViewController secondController;
public ViewController(IntPtr handle) : base(handle)
{
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
// Perform any additional setup after loading the view, typically from a nib.
var tabTitles = new List<string>() { "Tab 1 💝", "Tab 2 👨🏻💻" };
SetUpChildViewControllers();
collectionView.RegisterNibForCell(TabCollectionViewCell.Nib, "TabCollectionViewCell");
collectionView.Source = new CollectionViewSource(tabTitles, 0);
collectionView.Delegate = new CollectionViewSourceDelegate(tabTitles.Count, this);
collectionView.ReloadData();
LoadController(0);
}
private void SetUpChildViewControllers()
{
AddViewControllerAsChildViewController(FirstTabViewController());
AddViewControllerAsChildViewController(SecondTabViewController());
}
public UIViewController FirstTabViewController()
{
firstController = this.Storyboard.InstantiateViewController("FirstChildViewController") as FirstChildViewController;
return firstController;
}
public UIViewController SecondTabViewController()
{
secondController = this.Storyboard.InstantiateViewController("SecondChildViewController") as SecondChildViewController;
return secondController;
}
private void AddViewControllerAsChildViewController(UIViewController viewController)
{
this.AddChildViewController(viewController);
View.AddSubview(viewController.View);
viewController.View.Frame = ViewControllerSpace.Frame;
viewController.DidMoveToParentViewController(this);
viewController.View.Hidden = true;
}
public override void DidReceiveMemoryWarning()
{
base.DidReceiveMemoryWarning();
// Release any cached data, images, etc that aren't in use.
}
public void OnTabChange(int indexPath)
{
LoadController(indexPath);
}
private void LoadController(int indexPath)
{
collectionView.ReloadData();
if (indexPath == 0)
{
firstController.View.Hidden = false;
secondController.View.Hidden = true;
}
else if (indexPath == 1)
{
firstController.View.Hidden = true;
secondController.View.Hidden = false;
}
}
}
}
Step 7:
Now, run the application, you will get a view like below, select the tabs, based on tab selection the view will change.
The full source code is here -
Conclusion
In this blog, we learned to handle the view controllers in iOS. Thanks for reading and share your comments.
Posted on February 2, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.