how to use flyout navigation in xamarin IOS - ios

I'm new to Xamarin IOS and I have a project which needs this flyout navigation.
var navigation = new FlyoutNavigationController {
// Create the navigation menu
NavigationRoot = new RootElement ("Navigation") {
new Section ("Menu") {
new StringElement ("Recipe"),
new StringElement ("Recipe Basket"),
new StringElement ("Meal Planner"),
new StringElement ("Grocery List"),
new StringElement ("Social"),
new StringElement ("Videos"),
new StringElement ("News Feed"),
new StringElement ("Partners"),
}
},
// Supply view controllers corresponding to menu items:
ViewControllers = new [] {
new UIViewController { View = new UILabel { Text = "Animals (drag right)" } },
new UIViewController { View = new UILabel { Text = "Vegetables (drag right)" } },
new UIViewController { View = new UILabel { Text = "Minerals (drag right)" } },
},
};
This code just presents the UILabel. How can I do this to send it to a specific view controller?
Please help.
Thanks in advance.

Do what vinaykumar said, but you also want to open the FlyoutNavigationController from those UIViewControllers, so you have to pass that initial one you created to those controllers.
Otherwise if you just open your view controller, you won't be able to get the menu again.
I'm opening navigation controllers like so:
MainViewController in ViewDidLoad:
UIStoryboard board = UIStoryboard.FromName("MainStoryboard_iPhone", null);
UINavigationController nav = (UINavigationController)board.InstantiateViewController("nav");
SearchViewController searchVC = (SearchViewController)nav.ViewControllers[0];
// Passing flyoutnavigation here
searchVC.navigation = navigation;
SettingsViewController settingsVC = (SettingsViewController)board.InstantiateViewController("settings");
UINavigationController navSettings = new UINavigationController(settingsVC);
// Passing flyoutnavigation here
settingsVC.navigation = navigation;
navigation.ViewControllers = new[]
{
nav,
navSettings
};
In the other view controllers, (Settings and Search in my example), I have a public variable to store the FlyoutNavigationController (set in MainViewController) then add a button to open the FlyoutNavigationController that was passed:
// Set in MainViewController
public FlyoutNavigationController navigation;
public override void ViewDidLoad()
{
base.ViewDidLoad();
// Add button to allow opening the FlyoutNavigationController
NavigationItem.LeftBarButtonItem = new UIBarButtonItem(UIBarButtonSystemItem.Action, delegate
{
navigation.ToggleMenu();
});
}

you have to add the FlyoutNavigationController's View to your View
// Show the navigation view
navigation.ToggleMenu ();
View.AddSubview (navigation.View);

This code just presents the UILabel.
because you are only providing UILable as a view to your new UIViewController.
View = new UILabel { Text = "Animals (drag right)" }
How can I do this to send it to a specific view controller?
Provide your UIViewController instead of new UIViewController
for instance change the following code
ViewControllers = new [] {
new UIViewController { View = new UILabel { Text = "Animals (drag right)" } },
new UIViewController { View = new UILabel { Text = "Vegetables (drag right)" } },
new UIViewController { View = new UILabel { Text = "Minerals (drag right)" } },
},
to
ViewControllers = new [] {
new <your_UIViewController>(),
new <your_UIViewController>(),
new <your_UIViewController>(),
},
Hope this helps you, let me know if you faced any issue while implementing the same.

Related

Xamarin iOS Back To Master Button Is not shown on detail view

In short I have a SplitViewController as RootController.
And in constructor I've added master and detail controllers.
Detail Controller is wrapped into Navigation Controller.
{
_masterViewController = new MenuViewController();
_inventories = new InventoriesViewController();
_detailNavigationController = new UINavigationController(_inventories);
ViewControllers = new UIViewController[] {
_masterViewController,
_detailNavigationController
};
What are the ways I can show the Menu (show master) back button on details Navigation Bar?
We don't use storyboards
add the following code in the method ViewDidLoad()
UIButton backButton = new UIButton();
backButton.Frame = new CGRect(0,0,20,20);
backButton.SetTitle("Back", UIControlState.Normal);
backButton.SetTitleColor(UIColor.Gray, UIControlState.Normal);
backButton.SetImage(new UIImage("back"), UIControlState.Normal);
//backButton.SetImage(new UIImage("001.jpg"), UIControlState.Normal);
backButton.TouchUpInside += (sender, e) =>
{
NavigationController.PopViewController(true);
};
UIBarButtonItem backItem = new UIBarButtonItem(backButton);
NavigationItem.LeftBarButtonItem = backItem;
After some time I found the property on the UISplitViewController
DisplayModeButtonItem
So after creation of master and detail controller (detail controller is wrapped into UINavigationController) I added the DisplayModeButtonItem into NavigationBar LeftItem of detailed controller. It gave me the desired look and behaviour
{
_masterViewController = new MenuViewController();
_inventories = new InventoriesViewController();
_inventoriesNavigation = new UINavigationController(_inventories);
_inventories.NavigationItem.LeftBarButtonItem = DisplayModeButtonItem;
ViewControllers = new UIViewController[] {
_masterViewController,
_inventoriesNavigation
};
}

DialogViewController not showing navigationbar

I am instantiating a DialogViewController within a MvvmCross View like this
var myDialog = new MyDialogViewController();
var navController = new UINavigationController();
controller.NavigationBar.TintColor = UIColor.Black;
controller.PushViewController(myDialog, false);
Add(controller.View);
And this is how the MyDialogViewController looks like:
public class MyDialogViewController : DialogViewController
{
public MyDialogViewController()
: base(UITableViewStyle.Grouped, new RootElement("MyRoot"), true)
{
var root = new RootElement("MyRoot") {
new Section
{
new HtmlElement("MyWebsite", https://www.mywebsite.com")
}
};
Root.Add(root);
}
}
The dialog appears fine with the NavigationBar but if I select the Html element MyWebsite the Webview is displayed but without the NavigationBar and I am not able to navigate back.
The same thing occurs for elements that require to navigate to a new window, the navigationbar is not shown.
Any idea how to make the NavigationBar show after navigating to the WebView?
This worked for me:
var settings = new SettingsDialogViewController((SettingsViewModel)ViewModel, new RootElement("Settings"));
var window = UIApplication.SharedApplication.KeyWindow;
navigationController = window.RootViewController.ChildViewControllers[1].NavigationController;
navigationController.PushViewController(settings, true);
navigationController.NavigationBarHidden = false;

UITabBarController wait loading UIViewController until selected Xamarin

Is it possible to call a method when a new UIViewController is selected in a UITabBarController ? Or is it possible to wait loading the whole UIViewController until the view is selecte?
I have a UITabBarController that looks like:
public sealed class VisualizationViewController : UITabBarController
{
private UIViewController tabVand, tabVarme, tabEl;
private UIToolbar toolbar;
public VisualizationViewController()
{
toolbar = new UIToolbar(new RectangleF(0, 0, (float)View.Frame.Width, 60));
toolbar.AutoresizingMask = UIViewAutoresizing.FlexibleWidth;
View.AddSubview(toolbar);
tabVand = new WaterVisualizationViewController();
tabVand.Title = "Vand";
tabVand.TabBarItem = new UITabBarItem("Vand", UIImage.FromFile("Images/Water.png"), 0); // Tag == initial order
tabVand.TabBarItem.SetFinishedImages( UIImage.FromFile("Images/Water.png"), UIImage.FromFile("Images/Water.png"));
tabVand.View.BackgroundColor = UIColor.LightGray;
tabVarme = new TemperatureViewController();
tabVarme.Title = "Varme";
tabVarme.TabBarItem = new UITabBarItem("Varme", UIImage.FromFile("Images/Heat.png"), 1); // Tag == initial order
tabVarme.TabBarItem.SetFinishedImages(UIImage.FromFile("Images/Heat.png"), UIImage.FromFile("Images/Heat.png"));
tabVarme.View.BackgroundColor = UIColor.LightGray;
tabEl = new ElVisualizationViewController();
tabEl.Title = "EL";
tabEl.TabBarItem = new UITabBarItem("EL", UIImage.FromFile("Images/Power.png"), 2); // Tag == initial order
tabEl.TabBarItem.SetFinishedImages(UIImage.FromFile("Images/Power.png"), UIImage.FromFile("Images/Power.png"));
tabEl.View.BackgroundColor = UIColor.LightGray;
var tabs = new[]
{
tabVand, tabVarme, tabEl
};
ViewControllers = tabs;
SelectedViewController = tabVand;
}
And right now, it loads all the Views, which is going to be an expensive call, when I move from dummy data to the real data each view should load. So I want to only make a data call when the view is selected in the UITabBarController.
So what's happening is that your ViewDidLoad() method is firing (assuming you're calling your webservice there) for each tab view controller in your constructor. Each View Did Load is firing because you're calling View.Background, which will load the view into memory. You don't want to do that here, but in the ViewDidLoad() method of each individual tab View Controller:
public sealed class VisualizationViewController : UITabBarController
{
private UIViewController tabVand, tabVarme, tabEl;
private UIToolbar toolbar;
public VisualizationViewController()
{
base.ViewDidLoad();
toolbar = new UIToolbar(new RectangleF(0, 0, (float)View.Frame.Width, 60));
toolbar.AutoresizingMask = UIViewAutoresizing.FlexibleWidth;
View.AddSubview(toolbar);
tabVand = new WaterVisualizationViewController();
tabVand.Title = "Vand";
tabVand.TabBarItem = new UITabBarItem("Vand", UIImage.FromFile("Images/Water.png"), 0); // Tag == initial order
tabVand.TabBarItem.SetFinishedImages( UIImage.FromFile("Images/Water.png"), UIImage.FromFile("Images/Water.png"));
//Don't do this, it will make its ViewDidLoad fire
//and you don't want that.
//tabVand.View.BackgroundColor = UIColor.LightGray;
tabVarme = new TemperatureViewController();
tabVarme.Title = "Varme";
tabVarme.TabBarItem = new UITabBarItem("Varme", UIImage.FromFile("Images/Heat.png"), 1); // Tag == initial order
tabVarme.TabBarItem.SetFinishedImages(UIImage.FromFile("Images/Heat.png"), UIImage.FromFile("Images/Heat.png"));
//tabVarme.View.BackgroundColor = UIColor.LightGray;
tabEl = new ElVisualizationViewController();
tabEl.Title = "EL";
tabEl.TabBarItem = new UITabBarItem("EL", UIImage.FromFile("Images/Power.png"), 2); // Tag == initial order
tabEl.TabBarItem.SetFinishedImages(UIImage.FromFile("Images/Power.png"), UIImage.FromFile("Images/Power.png"));
//tabEl.View.BackgroundColor = UIColor.LightGray;
var tabs = new[]
{
tabVand, tabVarme, tabEl
};
ViewControllers = tabs;
SelectedViewController = tabVand;
}
Then in each individual tab (UIViewController) implementation, call your web service in it's ViewDidLoad() method, and not in the constructor. Example:
public class WaterVisualizationViewController : UIViewController
{
public WaterVisualizationViewController()
{
//Don't call your web service here
}
public override ViewDidLoad()
{
//Set your background color here
//Call your web service
//Populate your UI with data
}
}
Now if your web service calls are expensive, you might see a little lag when tapping the tabs. For that you should consider using UIActivityIndicatorView to display a "Loading Data" type of indicator so that the user has feedback your app is doing something and not frozen. Alternatively, you can use BTProgressHUD from the Xamarin Component Store, which is really easy to use

FlyoutNavigation sub viewcontroller can't perform segue on main controller?

Using flyout navigation on monotouch by James Clancey. Can't get a subview controller to elegantly perform a segue on the main containing controller?
NavigationRoot = new RootElement ("Navigation") {
new Section ("Menu") {
new StringElement ("Mapview Controller"),
new StringElement ("Another View Controller"),
}
},
ViewControllers = new [] {
// mapview is a view inside this viewcontroller and able to perform segues
new UIViewController { View = mapView },
// this is a seperate viewcontroller but is embedded inside the flyoutNavigation
// AnotherViewController cant seem to call the root navigation controller (<-- actually a uiNav inside a tab bar nav) so i can perform a segue movement just like the above mapViewController??
this.Storyboard.InstantiateViewController("AnotherViewController") as AnotherViewController,
},
// sub viewcontroller i.e. AnotherViewController trying to move mainViewController to perform a segue..
// throws error: Receiver (<FlyoutNavigation.FlyoutNavigationController: 0x14360600>) has no segue with identifier 'segueTest'
this.ParentViewController.PerformSegue("segueTest", this);
* Update:
I gave up on segue. Instead of using additional view controllers, I'm relying on views but one of my views is a static-celled tableview and not sure how to add it to above code liek so:
ViewControllers = new [] {
new UIViewController { View = mapView },
new UIViewController { View = myTableView } // doesnt work - tried with 'new UITableViewController' which also fails
What do I do?
You can use navigation for that..
ViewControllers = new [] {
new UINavigationController (this.Storyboard.InstantiateViewController("profileViewController") as ProfileViewController),
}

MonoTouch for IPad: How to show another UIViewController in a UIPopoverController?

As title said, I want to show another UIViewController from an existing UIViewController which is hosted in UIPopoverController. I tried the following method:
_secondViewController = new SecondViewController();
this.ModalPresentationStyle = UIModelPresentationStyle.CurrentContext;
this.ModelInPopover = true;
this.PresentModelViewController(_secondViewController, true);
However, the secondViewController is shown in the main view controller, instead of the popover controller.
In this post somebody mentions that it cannot be done and it violates the HIG. However, I have seen this in other apps (e.g. Yahoo! Email) if I'm not mistaken.
I'm also thinking about another approach: If I could create a UINavigationController within the popover context, it might work by just adding new ViewController to the NavigationController. But how?
Remember that UINavigationController derives from UIViewController.
So, you can use the controller contained within UIPopover just like any other container... in this case it's best to use UINavigationController inside UIPopover to display ViewControllers.
Usage:
var _NavController = new NavController();
Popover = new UIPopoverController(_NavController);
Popover.PopoverContentSize = new SizeF(..., ...);
Popover.PresentFromRect(...);
NavController:
public class NavController : UINavigationController
{
UIViewController _FirstViewController;
UIViewController _SecondViewController;
public NavController()
: base()
{
}
public override void LoadView()
{
base.LoadView();
_FirstViewController = new UIViewController();
// Initialize your originating View Controller here.
// Only view related init goes here, do everything else in ViewDidLoad()
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
// When a button inside the first ViewController is clicked
// The Second ViewController is shown in the stack.
_FirstViewController.NavButton.TouchUpInside += delegate {
PushSecondViewController();
};
this.PushViewController(_FirstViewController, true);
}
public void PushSecondViewController()
{
_SecondViewController = new UIViewController();
this.PushViewController(_SecondViewController, true);
}
}

Resources