Unable to update the text of a RootElement when used with a modal RadioGroup Section with MonoTouch Dialog - xamarin.ios

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.

Related

Xamarin.ios: Search bar displays in every tab bar view

I'm building an iOS app with Xamarin.ios MvvmCross. In this app I use a tabbed view. on one tab view I wan't to display a search bar, but this search bar displays in every tab view. Anyone know how to resolve this so that I can hide the search bar in the other tab views?
Search bar Tab view:
public override void ViewWillAppear(Boolean animated)
{
base.ViewWillAppear(animated);
var searchController = new UISearchController(searchResultsController: null);
searchController.SearchBar.SizeToFit();
searchController.SearchBar.SearchBarStyle = UISearchBarStyle.Prominent;
TabBarController.NavigationItem.HidesSearchBarWhenScrolling = false;
TabBarController.NavigationItem.SearchController = searchController;
NavigationController.NavigationBar.PrefersLargeTitles = true;
this.Title = "Search";
_searchBar = searchController.SearchBar;
_searchBar.SearchButtonClicked += SearchBar_SearchButtonClicked;
_searchBar.TextChanged += SearchBarOnTextChanged;
_searchBar.CancelButtonClicked += SearchBarOnCancelButtonClicked;
TabBarController.NavigationItem.RightBarButtonItem = null;
}
Picture of tab view with search bar:
Search
Other tab views where I want to hide the search bar but can't get it done:
public override void ViewWillAppear(Boolean animated)
{
base.ViewWillAppear(animated);
//var searchController = new UISearchController(searchResultsController: null);
//searchController.SearchBar.Hidden = true;
var search = new UISearchController(searchResultsController: null);
TabBarController.NavigationItem.HidesSearchBarWhenScrolling = true;
search.SearchBar.Hidden = true;
NavigationController.NavigationBar.PrefersLargeTitles = true;
TabBarController.NavigationItem.RightBarButtonItem = null;
}
Picture of tab view where I don't want to show the search bar:
Home
This issue occurs because you just use one Navigation Controller wrapping your TabbarController. When user enter the second tabbar item(Search), you initialize a UISearchController and set it to the NavigationItem's SearchController. So this search bar appears as you want.
But when you return to the Home controller, this UISearchController will be still there since you just use one UINavigationController. Add the code below in your Home Controller's ViewWillAppear() event will fix your issue:
TabBarController.NavigationItem.SearchController = null;
I really recommend you to separate your one UINavigationController to four in your situation. Then each tabbar item controller has its own NavigationItem and will not affect each other. UITabbarController should be your app's root ViewController. Your app's hierarchy can be like this:
I use storyboard to draw two tabbar items helping you understand what I mean.
In this way in the Home controller, there's no need to add any code. You can just add the search bar in your Search controller with the code:
public override void ViewDidLoad()
{
base.ViewDidLoad();
var searchController = new UISearchController(searchResultsController: null);
searchController.SearchBar.SizeToFit();
searchController.SearchBar.SearchBarStyle = UISearchBarStyle.Prominent;
this.NavigationItem.HidesSearchBarWhenScrolling = false;
this.NavigationItem.SearchController = searchController;
NavigationController.NavigationBar.PrefersLargeTitles = true;
this.Title = "Search";
_searchBar = searchController.SearchBar;
_searchBar.SearchButtonClicked += _searchBar_SearchButtonClicked; ;
_searchBar.TextChanged += _searchBar_TextChanged; ;
_searchBar.CancelButtonClicked += _searchBar_CancelButtonClicked; ;
this.NavigationItem.RightBarButtonItem = null;
}
I move your code to ViewDidLoad() event and modify TabBarController.NavigationItem to this.NavigationItem.

MonoTouch DialogViewController - why must it be in the first place of a UINavigationController?

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.

Add button to EntryElement

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;
}
}

Monotouch Dialog Datepicker and RadioGroup Navigationitem

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!

MonoTouch.Dialog: Title Bar color with reflection api

I'm using the MonoTouch.Dialog reflection API to create a new DialogViewController:
var dashBoard = new RootElement (""){
new Section("My Dashboard", "All alerts, follow-ups, and tasks are automatically synced each time you launch the app") {
new StringElement ("Alerts"),
new StringElement ("Follow-ups"),
new StringElement ("Tasks")
}
};
var dvc = new DialogViewController (dashBoard) {
Autorotate = true
};
navigation.PushViewController (dvc, true);
If I supply the RootElement with a string value I get a nice title bar with text. I want to control the color of that title bar. I'm not seeing any properties that allow me to do this. Do I need to subclass DialogViewController and build my own title bar?
For me, the easiest way to do this is indeed subclassing the DialogViewController, like this:
public class CustomDialogViewController : DialogViewController {
// add constructors here as necessary, dont forget to call base()
public override void ViewWillAppear (bool animated)
{
base.ViewWillAppear (animated);
this.NavigationController.NavigationBar.TintColor = UIColor.FromRGB(0, 115, 176);
}
}

Resources