As I'm new in Xamarin.IOS, I'd like to ask a question.
I've followed this example for adding UITabBarController in a Xamarin.IOS project.
When I initialized RootViewController by an instance of TabController, it works fine and I have all tabs.
BUT my NavigationController set null ! it means that :
NavigationItem will disappear
navigating between viewControllers are not possible by this code :
this.NavigationController.PushViewController(new ProfileViewController(), true);
because the NavigationController is null !
Here is my code in AppDelegate:
_tabController = new TabController();
_window.RootViewController = _tabController;
and my TabController :
public class TabController : UITabBarController
{
UIViewController tab1, tab2, tab3, tab4;
public TabController()
{
tab1 = new HomeViewController();
tab1.TabBarItem.Image = UIImage.FromFile("Icons/Home.png");
tab2 = new TagCategoryViewController(null, null, 1, null);
tab2.TabBarItem.Image = UIImage.FromFile("Icons/Tag.png");
tab3 = new SearchViewController();
tab3.TabBarItem.Image = UIImage.FromFile("Icons/Search.png");
tab4 = new ProfileViewController();
tab4.TabBarItem.Image = UIImage.FromFile("Icons/Home.png");
var tabs = new UIViewController[] {
tab1, tab2, tab3,tab4
};
ViewControllers = tabs;
}
}
In additional, I have lots of UIViewControllers and I do all of them programmatically and I dont use StoryBoard !
By wrapping your TabController in a UINavigationController.
_tabController = new TabController();
_window.RootViewController = new UINavigationController(_tabController);
This way NavigationController property won't be null and navigation can be done.
Related
In continue of my question in this post, I want to post a complete question which will be a question lots of xamarin.ios developers.
My request is having TabBar in ALL UIViewControllers. So, as I know, there are two ways to realize it.
First :
appDelegate -> set RootViewController : TabController -> UVC1
in this case, I have NULL NavigationController and I'll have no navigationItem. and in
this.NavigationController.PushViewController(new
SearchViewController(), true);
It makes error that NavigationController is null.
Here is my code in AppDelegate:
_tabController = new TabController();
_window.RootViewController = _tabController;
and my TabController :
public class TabController : UITabBarController
{
UIViewController tab1, tab2, tab3, tab4;
public TabController()
{
tab1 = new HomeViewController();
tab1.TabBarItem.Image = UIImage.FromFile("Icons/Home.png");
tab2 = new TagCategoryViewController(null, null, 1, null);
tab2.TabBarItem.Image = UIImage.FromFile("Icons/Tag.png");
tab3 = new SearchViewController();
tab3.TabBarItem.Image = UIImage.FromFile("Icons/Search.png");
tab4 = new ProfileViewController();
tab4.TabBarItem.Image = UIImage.FromFile("Icons/Home.png");
var tabs = new UIViewController[] {
tab1, tab2, tab3,tab4
};
ViewControllers = tabs;
}
}
And the second way :
RootViewController -> navigationController -> TabController -> UVC1 ->
new UVC2 -> no tab bar !!
Here, everything sounds good, but when I navigate to new UIViewController which is not present in Tabs, the TabBar will diappear !
And the code is :
_tabController = new TabController();
var navigationController = new UINavigationController(viewController);
_window.RootViewController = new UINavigationController(_tabController);
What can I do ? Any idea?
I don't use StoryBoard !
By wrapping all your UIViewController with UINavigationController you can enable the behaviour you want, but make sure that you remove TabBarController since the NavigationBar will overlap the NavigationBar from your Views.
_window.RootViewController = _tabController;
And your views:
tab1 = new UINavigationController(new HomeViewController());
tab1.TabBarItem.Image = UIImage.FromFile("Icons/Home.png");
I want to use a DialogViewController inside of a UITabViewController.
Problem: Nested elements don't show a navigation bar, and so it is not possible to go back.
When I push my class (inherited from DialogViewController) to a UINavigationController, then the behavior is correct. If I use the same class in a tab of a UITabViewController (even with an underlying UINavigationController), then the behaviour is wrong.
Can anyone help me out?
Although the question is not assisted with some code sample, I made a small example hoping to solve your question. For this example I used the Tabbed Application template which comes with Xamarin.iOS and named it TabbingTest.
The following code goes in the AppDelegate. Change the FinishedLaunching method to contain:
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
window = new UIWindow (UIScreen.MainScreen.Bounds);
var viewControllers = new UIViewController[]
{
CreateTabFor("Test", "first", new TestDialogController ()),
CreateTabFor("Second", "second", new SecondViewController ()),
};
tabBarController = new UITabBarController ();
tabBarController.ViewControllers = viewControllers;
tabBarController.SelectedViewController = tabBarController.ViewControllers[0];
window.RootViewController = tabBarController;
window.MakeKeyAndVisible ();
return true;
}
Then add the following methods:
private int _createdSoFarCount = 0;
private UIViewController CreateTabFor(string title, string imageName, UIViewController view)
{
var controller = new UINavigationController();
controller.NavigationBar.TintColor = UIColor.Black;
var screen = view;
SetTitleAndTabBarItem(screen, title, imageName);
controller.PushViewController(screen, false);
return controller;
}
private void SetTitleAndTabBarItem(UIViewController screen, string title, string imageName)
{
screen.Title = NSBundle.MainBundle.LocalizedString (title, title);
screen.TabBarItem = new UITabBarItem(title, UIImage.FromBundle(imageName),
_createdSoFarCount);
_createdSoFarCount++;
}
Create a class named TestDialogController and paste the following code inside.
using System;
using MonoTouch.Dialog;
using MonoTouch.UIKit;
namespace TabbingTest
{
public class TestDialogController : DialogViewController
{
public TestDialogController (): base(UITableViewStyle.Plain,null,false)
{
var root = new RootElement ("Tabbing test"){
new Section (){
new RootElement ("First level", 0, 0) {
new Section (null, "This is the first level."){
new RootElement ("Second level", 0, 0) {
new Section (null, "This is the second level."){
new BooleanElement ("Flipflops", false)
}
}
}
}}
};
this.Root = root;
}
}
}
Now run the application.
You can see that even the nested elements show up nicely in the navigation bar. Even with multilevel nesting.
I am creating an iPad app using MonoTouch 2.10.11 and I want to MonoTouch.Dialog to create some of the editable fields on a form. One of the fields will use a RadioGroup to allow the user to select from a list of options. The default behavior of M.T.D is display the selection list table over the existing table. This works great for the iPhone layout, but on this iPad form, the table is only on a small area of the form and the navigation bar looks odd on the middle of the form. I want to display the selection as a full screen modal and the user will hit a "back" button to go back the previous form with the selected item.
I created a new RootElement descendant class like this:
public class ModalRootElement : RootElement
{
public override void Selected (DialogViewController dvc, UITableView tableView, NSIndexPath path)
{
tableView.DeselectRow (path, false);
UIViewController uIViewController = this.MakeViewController ();
this.PrepareDialogViewController (uIViewController);
dvc.PresentViewController (uIViewController, true, null);
}
protected override void PrepareDialogViewController(UIViewController dvc)
{
base.PrepareDialogViewController(dvc);
UIButton button = UIButton.FromType (UIButtonType.RoundedRect);
button.Frame = new RectangleF (5, 5, 80, 20);
button.SetTitle ("back", UIControlState.Normal);
button.TouchUpInside += delegate {
DialogViewController d = dvc as DialogViewController;
(d.Root as ModalRootElement).TableView.ReloadData ();
d.DeactivateController(true);
};
dvc.View.AddSubview (button);
}
}
The table is implemented with the following code:
var _status = new ModalRootElement("Status", new RadioGroup("status", -1)) {
(new Section() {
new RadioElement("New", "status"),
new RadioElement("In process", "status"),
new RadioElement("Rejected", "status"),
new RadioElement("Deferred", "status"),
new RadioElement("Transferred", "status"),
new RadioElement("Unknown", "status"),
new RadioElement("Complete", "status")
})
};
var _odom = new EntryElement ("Odometer", "current odom", "");
_odom.KeyboardType = UIKeyboardType.DecimalPad;
_odom.TextAlignment = UITextAlignment.Right;
var root = new RootElement ("back") {
new Section("") {
_status,
_odom
}
};
_dvc = new DialogViewController(root);
_nav = new UINavigationController (_dvc);
_nav.SetNavigationBarHidden (true, false);
When I run the app, I can drill into the RadioGroup and make a selection. When I click the back button that I added to the view, the modal view closes and the RadioSelected properted of the ModalRootElement object is set correctly, but the text is not displayed.
If I change Selected() method to call dvc.ActivateController instead of PresentViewController, the ModalRootElement displays the correct text, but the RadioGroup table has the wrong size. Is there a way to get the RootElement to display the correct text when you use PresentViewController instead of ActivateController?
I think you need a Root.Reload() call.
I have created an EntryElement in which the user enters a phone number.How can I add a button at the end of the element so that the user can press the button and make a call?
You need to create a new element that is a subclass of an EntryElement, override the get cell method and add to the accessoryView the button .
I know this doesn't exactly answer the question but I struggled for quite a while until I found the answer by #Janub which put me on the right track. Here is the code that I currently have working.
public class NextNumericCell : EntryElement
{
readonly EventHandler handler;
public NextNumericCell (string caption, string placeholder, string value, EventHandler onClick ) : base(caption,placeholder,value)
{
handler = onClick;
}
protected override UITextField CreateTextField (CGRect frame)
{
var textField = base.CreateTextField (frame);
var toolBar = new UIToolbar (new CGRect (0, 0, frame.Width, 35));
var spacerButton = new UIBarButtonItem (UIBarButtonSystemItem.FlexibleSpace);
var buttonTitle = ReturnKeyType == null ? "SetButtonTitle" : ReturnKeyType.ToString ();
var nextButton = new UIBarButtonItem (buttonTitle, UIBarButtonItemStyle.Plain, handler);
toolBar.Items = new UIBarButtonItem [] { spacerButton, nextButton };
textField.InputAccessoryView = toolBar;
return textField;
}
}
I can´t figure out how to correctly design the pushed viewcontrollers navigation back item of a RadioGroup.
So in the follow up screen where the languages are selectable the back Button says "Settings" and is blue. But I want to make it say back and change its design which mechanisms exists and I´m already using in other screens.
I build it up like this:
var rootSettings = new RootElement ("Settings");
var sectionNotificationSettings = new Section ("Notification settings");
BooleanElement pushEnabled = new BooleanElement("Push notifications", settings.PushEnabled);
sectionNotificationSettings.Add(pushEnabled);
var sectionCountrySettings = new Section("Country settings");
var rootRadioGroup = new TransparentRootElement ("Language", new RadioGroup("languages", 0));
var sectionRadioElements = new Section("");
foreach(var language in settings.Languages)
{
RadioElement selectableLanguage = new RadioElement(language.Key, "languages");
sectionRadioElements.Add(selectableLanguage);
}
rootRadioGroup.Add(sectionRadioElements);
sectionCountrySettings.Add(rootRadioGroup);
rootSettings.Add (sectionNotificationSettings);
rootSettings.Add(sectionCountrySettings);
And here I define the TransparentRootElement where I thought I can edit the navigation Item:
public class TransparentRootElement : RootElement {
public TransparentRootElement (string caption) : base (caption)
{
}
public TransparentRootElement (string caption, Group radioGroup ) : base (caption, radioGroup)
{
}
public override void Selected (DialogViewController dvc, UITableView tableView, NSIndexPath path)
{
base.Selected (dvc, tableView, path, true);
}
void HandleMenuButtonTouchUpInside (object sender, EventArgs e)
{
_dvc.NavigationController.PopViewControllerAnimated(true);
}
public override UITableViewCell GetCell (UITableView tv)
{
var cell = base.GetCell (tv);
//cell.BackgroundColor = UIColor.White;
return cell;
}
}
I tried many edit approaches but none of the worked. I also began editing the Elements.cs in Monotouch Dialog but this also did not helped me alot.
Anyone who has a suggestion?
Thank you very much!
I believe to change the navigation's back button, you have to hide the default back button and then assign your own. (Right before you push the new view controller, I believe in your case, it would be before you push the Language screen) Something like this:
toPushscreen.NavigationItem.SetHidesBackButton(true, true);
toPushscreen.NavigationItem.LeftBarButtonItem = new UIBarButtonItem("Back", UIBarButtonItemStyle.Plain, myHandler);
currentScreen.NavigationController.PushViewController(toPushscreen, true);
Hope this helps!