How to hide a TabBarItem in Xamarin iOS - xamarin

I have a Storyboard with a TabBarController and six subviews as Tabs. The TabBarController and each Tab has a Controller Class assigned.
The content of some tabs is loaded from a server. In some cases there is no content for a tab and for this case I want to hide the TabBarItem.
I've tried (just for testing)
this.TabBarController.TabBar.Items [0].Enabled = false;
but it doesn't work.
How can I hide a single TabBarItems? I've searched Google, StackOverflow and the Xamarin Forum but found no solution for my problem.
The only solution I've found was to remove the subview from the subviews-array, but in this case I cannot simply "reactivate" the tab if I want to show the tab again.

In case of UITabBar:
UITabBar sampleTabBar;
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
// Perform any additional setup after loading the view, typically from a nib.
sampleTabBar = new UITabBar ();
sampleTabBar.Frame = new CoreGraphics.CGRect (10f, 64f, this.View.Frame.Width - 10, 50f);
var tabBarItem = new UITabBarItem ("TAB BAR ITEM", null, 4);
sampleTabBar.Items = new UITabBarItem[]{ tabBarItem };
sampleTabBar.ItemSelected += (sender, e) => {
Console.WriteLine ("tab bar button item slected");
//Disable Tab Bar item here
tabBarItem.Enabled = false;
tabBarItem.Title = "Disabled now";
};
this.View.AddSubview (sampleTabBar);
}
tabBarItem.Image property also can be used for getting the result.
1) Set a placeholder image as default.
2) Populate images from array/source to uibarButtonItem.
3) Use placeholder image wherever need to hide uibarbuttonitem.

I think if you want to completely hide the UITabbarItem you will need to remove the UIViewController from the UITabbarController like so:
var tbViewControllers = new List<UIViewController> (TabBarController.ViewControllers);
tbViewControllers.RemoveAt (2); // remove whatever index you need.
TabBarController.ViewControllers = tbViewControllers.ToArray ();
but you will need to keep a reference to all the UIViewControllers you want and add it back in like so:
var tbViewControllers = new List<UIViewController> (TabBarController.ViewControllers);
tbViewControllers.Insert (2, new RemvoedViewController());
TabBarController.ViewControllers = tbViewControllers.ToArray ();

Related

Xamarin (Visual Studio), View mapped MKMapView, not a control on view, will not show navigation bars added to view

I created a View and mapped it to a MKMapView via code, but I cannot seem to have the Navigation Bar show up (it's the 2nd view in the stack, so it should have some ability to show the bar).
The map creates well with all functionality I want, BUT, it takes up the entire view space on the View
public override void LoadView()
{
CoreGraphics.CGRect r = new Rectangle(0, 40, (int)UIScreen.MainScreen.Bounds.Right, (int)UIScreen.MainScreen.Bounds.Bottom);
map = new MKMapView(r);
View = map;
}
any ideas?
To show Navigation Bar , you need make sure that the RootViewController of the Application is an UINavigationController (not an UIViewController) .
in Appdeledate.cs
public bool FinishedLaunching (UIApplication application, NSDictionary launchOptions)
{
// Override point for customization after application launch.
// If not required for your application you can safely delete this method
Window = new UIWindow(UIScreen.MainScreen.Bounds);
Window.RootViewController = new UINavigationController(new YourViewController());
Window.MakeKeyAndVisible();
return true;
}
in SceneDelegate (if your app contains it)
public void WillConnect (UIScene scene, UISceneSession session, UISceneConnectionOptions connectionOptions)
{
Window = new UIWindow(scene as UIWindowScene);
Window.RootViewController = new UINavigationController(new YourViewController()) ;
Window.MakeKeyAndVisible();
}
And when you navigate from the first page to the map page
NavigationController.PushViewController(new YourMapController(),true);

How to identify user tapped on Editor field in Xamarin forms?

First thing, I have an Editor.I can Identify if the user entered any text in that Edior.But i need to return something when the user tapped on the Editor. How to achieve this?
var msgEditor = new Editor
{
Margin = new Thickness(10, 0, 10, 0),
HeightRequest = App.ScreenHeight,
};
Secong thing, Editor is inside the scrollview.When i tapped on the Editor scrollview scrolls down.I need to manually pull down to see the cursor.How to set content offset when i tapped on Editor?
ScrollView scroll = new ScrollView
{
Content = msgEditor,
};
Content = scroll;
On the editor, you have the focus event that notifies you that the user tapped the editor. You can do as follow :
{
var editor = new Editor();
editor.Focused += EditorOnFocused;
}
private void EditorOnFocused(object sender, FocusEventArgs focusEventArgs)
{
//do your stuff
}

How to have dynamic image on Xamarin Form Header?

I am working on Xamarin form in which header title will have weather temperature and weather icon on its right side.
For example
New York 60' F SunnyIcon
I am using openweather api to fetch the data.
Problem is, I am not able to create a dynamic image holder on the Xamarin Form Header.
How to have a dynamic image on the Xamarin Form Header?
Attached is a sample app which i am working on based on source code which i downloaded from github ...
I'm not sure what you mean by "Header," but if you're trying to add an icon to the Navigation Bar, you can do that by calling ToolbarItems.add() in the constructor of your page like this:
public myPage()
{
InitializeComponent();
ToolbarItems.Add(new ToolbarItem("Weather", "WeatherIcon.png", async () =>
{
//Code to Execute when Icon is tapped
}));
}
When adding the ToolbarItem, the first parameter is the name of the item, the second is the name of the image that will be displayed at the end of the Navigation bar, and the last one is optional which creates a method that is executed when the icon is tapped.
If you need the icon to be different depending on the current weather, you can do that like this:
public myPage()
{
InitializeComponent();
string weatherIconString = "";
if(weather.isSunny) // Edit contition however you need
weatherIconString = "SunnyIcon.png";
else
weatherIconString = "CloudyIcon.png";
ToolbarItems.Add(new ToolbarItem("Weather", weatherIconString));
}
You have to write a custom renderer like this: and the result:
public class CustomNavigationPageRenderer : NavigationRenderer
{
public override void ViewDidLoad()
{
//I'm getting width and height so i can rescale the image
nfloat navigationBarWidth = NavigationBar.Frame.Width;
nfloat navigationBarHeight = NavigationBar.Frame.Height;
//you can load image from your bundle,so you can add your weather icons on bundle -> under Resources folder
var img = UIImage.FromBundle("navigationbarbackground.jpg");
//create image context to draw image
UIGraphics.BeginImageContextWithOptions(new CGSize(navigationBarWidth, navigationBarHeight), true, 0);
//I'm filling the background with a color so it is the same as with my background image color
UIColor.FromRGB(54, 60, 65).SetFill();
UIGraphics.RectFill(new CGRect(0, 0, navigationBarWidth, navigationBarHeight));
//draw your image according to the coordinates of the navigation bar, i put it to the right top with a small right padding,
//you have to play with coordinates according to your needs
img.Draw(new CGRect(navigationBarWidth - navigationBarHeight - 30,//move 30px to the left (do not paste to right border :))
0, navigationBarHeight, navigationBarHeight));
UIImage backgroundImage = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
NavigationBar.SetBackgroundImage(backgroundImage, UIBarMetrics.Default);
//bonus :) change your title color
UINavigationBar.Appearance.SetTitleTextAttributes(new UITextAttributes()
{
TextColor = UIColor.White,
});
base.ViewDidLoad();
}
}

Valid way to hide QLPreviewController RightBarButtonItem/RightBarButtonItems Xamarin iOS

My app supports iOS8+ devices. I want to hide right Action button from navigation bar. By research I found following few workarounds:
1. Create Sub class of QLPreviewController and in ViewDidAppear SetRightBarButtonItems to zero.
public class PdfViewController : QLPreviewController
{
public override void ViewDidAppear (bool animated)
{
base.ViewDidAppear (animated);
NavigationItem.SetRightBarButtonItems (new UIKit.UIBarButtonItem[0], false);
}
}
In this case problem is RightBarButtonItem appears and then disappears. In mean while user is able to click on that RightBarButtonItem button. I don't want this behavior.
2. Create UIViewController and add QLPreviewController as child ViewController.
void BtnShowPdf_Clicked (object sender, EventArgs e) {
var dummyVC = new UIViewController ();
var pdfVC = new PdfViewController ();
dummyVC.AddChildViewController (pdfVC);
dummyVC.View.AddSubview (pdfVC.View);
dummyVC.NavigationItem.SetRightBarButtonItems (new UIBarButtonItem[0], false);
dummyVC.EdgesForExtendedLayout = UIRectEdge.None;
dummyVC.AutomaticallyAdjustsScrollViewInsets = false;
dummyVC.View.BackgroundColor = UIColor.Clear;
pdfVC.EdgesForExtendedLayout = UIRectEdge.None;
pdfVC.AutomaticallyAdjustsScrollViewInsets = false;
pdfVC.View.BackgroundColor = UIColor.Clear;
}
In this case If I set QLPreviewController it works as expected. But NavigationBar becomes more darker than default ViewController background color.
Dark Bar:
http://screencast.com/t/bqVMv5qqGz
Needed clear background bar like:
http://screencast.com/t/MUwE2VnxJ7
My questions are:
A) I would like to know which is the correct way to hide right
navigation bar button as per Apple guidelines ? If you have correct
solution then those are also appreciated.
B) Also Can you please suggest solution(s) for #1 Or #2 ?
Pretty sure you can do this:
override func viewWillAppear(_ animated: Bool)
{
super.viewWillAppear(animated)
self.navigationItem.rightBarButtonItems = nil
}

How to show ActivityIndicator in the middle of the screen?

I've created an activity indicator and added it to StackLayout and when I make it running, in the emulator it shows in the top right corner Android 4.4 and in iOS no show and in Android 6 phone, it don't show.
var indicator = new ActivityIndicator()
{
Color = Color.Blue,
};
indicator.SetBinding(ActivityIndicator.IsVisibleProperty, "IsBusy", BindingMode.OneWay);
indicator.SetBinding(ActivityIndicator.IsRunningProperty, "IsBusy", BindingMode.OneWay);
AbsoluteLayout.SetLayoutFlags(indicator, AbsoluteLayoutFlags.PositionProportional);
AbsoluteLayout.SetLayoutBounds(indicator, new Rectangle(0.5, 0.5, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize));
mainLayout.Children.Add(indicator);
I want to show the activity indicator to the center of the screen because the operation takes time to complete.
The indicator that you are seeing in the status bar is the default behavior of the IsBusy property of the base page class. The reason your code isn't working is because you are attempting to bind visibility of your ActivityIndicator to that property - but you aren't specifying a binding source. If you look in your debugger's application output log then you will probably see messages along the lines of "Property 'IsBusy' not found on type 'Object'".
To fix it, you simply need to point the Binding Context of each binding to the form. Give this a try:
public partial class App : Application
{
public App ()
{
var mainLayout = new AbsoluteLayout ();
MainPage = new ContentPage {
Content = mainLayout
};
var containerPage = Application.Current.MainPage;
var indicator = new ActivityIndicator() {
Color = Color.Blue,
};
indicator.SetBinding(VisualElement.IsVisibleProperty, new Binding("IsBusy", BindingMode.OneWay, source: containerPage));
indicator.SetBinding(ActivityIndicator.IsRunningProperty, new Binding("IsBusy", BindingMode.OneWay, source: containerPage));
AbsoluteLayout.SetLayoutFlags(indicator, AbsoluteLayoutFlags.PositionProportional);
AbsoluteLayout.SetLayoutBounds(indicator, new Rectangle(0.5, 0.5, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize));
mainLayout.Children.Add(indicator);
containerPage.IsBusy = true;
}
}
You add your activity indicator to stack layout, but you are setting Absolute layout LayoutFlags, they won't work.
to be able to achieve what you want, you need suck structure
AbsoluteLayout
StackLayout
ActivityIndicator
mainLayout should be AbsoluteLayout, all content should be contained in nested StackLayout.

Resources