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.
Related
Need to have transparent navigation bar
https://developer.xamarin.com/recipes/ios/content_controls/navigation_controller/change_the_nav_bar_transparency/
tried with this but not working.
Any Suggestion ?
Although, your question is not fully descriptive and not sure what exactly you want to achieve by saying "Not Working" from the given link.
Write following code in respective override methods of the ViewController in which you want to achieve the Transperent NavigationBar for that specific ViewController only.
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
if (NavigationController != null)
{
NavigationController.NavigationBar.SetBackgroundImage(new UIImage(), UIBarMetrics.Default);
NavigationController.NavigationBar.ShadowImage = new UIImage();
NavigationController.NavigationBar.Translucent = true;
NavigationController.View.BackgroundColor = UIColor.Clear;
NavigationController.NavigationBar.BackgroundColor = UIColor.Clear;
}
}
public override void ViewWillDisappear(bool animated)
{
base.ViewWillDisappear(animated);
if (NavigationController != null)
{
NavigationController.NavigationBar.SetBackgroundImage(null, UIBarMetrics.Default);
NavigationController.NavigationBar.ShadowImage = null;
NavigationController.NavigationBar.BarTintColor = UIColor.Red; //Provide your specific color here
}
}
If you want to set this Globally, Try it in AppDelegate's FinishedLaunching method :
UINavigationBar.Appearance.SetBackgroundImage(new UIImage(), UIBarMetrics.Default);
UINavigationBar.Appearance.ShadowImage = new UIImage();
UINavigationBar.Appearance.BackgroundColor = UIColor.Clear;
UINavigationBar.Appearance.Translucent = true;
Hope this helps!.
A single navigation bar is used for a particular navigation controller in iOS. So if you want to make it transparent for a single VC then you have to make it transparent when you navigate to that VC. And then change it back when you coming back from that VC in viewWillDisappear (or viewDidDisappear) methods.
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!