Change hamburger icon in master detail navigation xamarin forms - xamarin.forms

I am working on Xamarin forms where I need to show master detail navigation after successful login screen. I want to change default hamburger icon but not able to change it.
Please see below code I am using.
Since my app have login screen so I don't want to show any navigation on Login screen. I am just setting main page in app.xaml.cs
public App()
{
InitializeComponent();
MainPage = new Login();
}
Now after login clicked I tried following approach to change icon but didn't work
var dashboard = new Dashboard(){Icon = "Menuicon.png" };
Application.Current.MainPage = dashboard;
Dashbaord is masterdetail page and on its ctor, I am setting detail page like below
Detail = new NavigationPage((Page)Activator.CreateInstance(typeof(DashbaordDetail))) { Icon = "Menuicon.png" };
Its not reflecting new icon

You should use a custom renderer.
In your Android project, like this:
[assembly: ExportRenderer(typeof(CustomIcon.Views.MainPage), typeof(IconNavigationPageRenderer))]
namespace CustomIcon.Droid
{
public class IconNavigationPageRenderer : MasterDetailPageRenderer
{
private static Android.Support.V7.Widget.Toolbar GetToolbar() => (CrossCurrentActivity.Current?.Activity as MainActivity)?.FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
protected override void OnLayout(bool changed, int l, int t, int r, int b)
{
base.OnLayout(changed, l, t, r, b);
var toolbar = GetToolbar();
if (toolbar != null)
{
for (var i = 0; i < toolbar.ChildCount; i++)
{
var imageButton = toolbar.GetChildAt(i) as ImageButton;
var drawerArrow = imageButton?.Drawable as DrawerArrowDrawable;
if (drawerArrow == null)
continue;
imageButton.SetImageDrawable(Forms.Context.GetDrawable(Resource.Drawable.newIcon));
}
}
}
}
}
In your iOS project only use the same icon from you xaml file in your PCL project, like this:
<?xml version="1.0" encoding="utf-8" ?>
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:CustomIcon.Views;assembly=CustomIcon"
Title="MainPage"
Icon="newIcon.png"
x:Class="CustomIcon.Views.MainPage">
<MasterDetailPage.Master>
<local:MasterPage x:Name="masterPage" />
</MasterDetailPage.Master>
<MasterDetailPage.Detail>
<NavigationPage>
<x:Arguments>
<local:Page1 />
</x:Arguments>
</NavigationPage>
</MasterDetailPage.Detail>
For more information see my repo on github: https://github.com/wilsonvargas/CustomIconNavigationPage

i applied this tweak and it helped me. now i can see back button also after navigation
protected override void OnLayout(bool changed, int l, int t, int r, int b)
{
base.OnLayout(changed, l, t, r, b);
var toolbar = FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
if (toolbar != null)
{
for (var i = 0; i < toolbar.ChildCount; i++)
{
var imageButton = toolbar.GetChildAt(i) as ImageButton;
var drawerArrow = imageButton?.Drawable as DrawerArrowDrawable;
if (drawerArrow == null)
continue;
bool displayBack = false;
var app = Xamarin.Forms.Application.Current;
var detailPage = (app.MainPage as MasterDetailPage).Detail;
var navPageLevel = detailPage.Navigation.NavigationStack.Count;
if (navPageLevel > 1)
displayBack = true;
if (!displayBack)
ChangeIcon(imageButton, Resource.Drawable.iconMenu2);
if (displayBack)
ChangeIcon(imageButton, Resource.Drawable.back1);
}
}
}
private void ChangeIcon(ImageButton imageButton, int id)
{
if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.Lollipop)
imageButton.SetImageDrawable(Context.GetDrawable(id));
imageButton.SetImageResource(id);
}

Related

Run a background process to change backgroundimage of another page using timer in Xamarin.forms

Hi StackOverflow Team,
I am trying to run a background process in my App. This background process should update just Background image on one of the pages in the App every 15 seconds. So far, I tried to create a timer in the App OnStart() method and update the backgroundimage of the page in the BeginInvokeOnMainThread() method but with no success. Can anyone help me with this?
My Code -
{
private static Stopwatch stopWatch = new Stopwatch();
private const int defaultTimespan = 20;
private readonly HomePage homePage;
public App()
{
InitializeComponent();
try
{
MainPage = new MainPage();
homePage = new HomePage();
}
catch(Exception ex)
{
string str = ex.Message;
}
}
protected override void OnStart()
{
if (!stopWatch.IsRunning)
{
stopWatch.Start();
}
Device.StartTimer(new TimeSpan(0, 0, 10), () =>
{
// Logic for logging out if the device is inactive for a period of time.
if (stopWatch.IsRunning && stopWatch.Elapsed.Seconds >= defaultTimespan)
{
//prepare to perform your data pull here as we have hit the 1 minute mark
// Perform your long running operations here.
Device.BeginInvokeOnMainThread(() =>
{
// If you need to do anything with your UI, you need to wrap it in this.
// homePage.BackgroundImageSource = "goldengate.jpg";
homePage.ChangeBackgroundImage();
});
stopWatch.Restart();
}
// Always return true as to keep our device timer running.
return true;
});
}
protected override void OnSleep()
{
//stopWatch.Reset();
}
protected override void OnResume()
{
//stopWatch.Start();
}
//void ChangeHomePageImage()
//{
// Navigation.PushAsync(new HomePage(appBackground));
// Navigation.RemovePage(this);
//}
}
MainPage -
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:local="clr-namespace:Excercise.Views"
x:Class="Excercise.MainPage" IsPresented="False">
<MasterDetailPage.Master>
<local:MenuPage x:Name="menuPage"></local:MenuPage>
</MasterDetailPage.Master>
<MasterDetailPage.Detail>
<NavigationPage>
<x:Arguments>
<local:HomePage x:Name="homePage"></local:HomePage>
</x:Arguments>
</NavigationPage>
</MasterDetailPage.Detail>
</MasterDetailPage>
HomePage -
public partial class HomePage : ContentPage
{
private SQLiteAsyncConnection _connection;
public HomePage()
{
InitializeComponent();
// BindingContext = new HomePageViewModel();
_connection = DependencyService.Get<ISQLiteDb>().GetConnection();
loadData("");
}
public HomePage(string BackgroundimgPath)
{
InitializeComponent();
// BindingContext = new HomePageViewModel();
_connection = DependencyService.Get<ISQLiteDb>().GetConnection();
loadData(BackgroundimgPath);
}
public HomePage(string City, string LocationKey, string StateID)
{
InitializeComponent();
_connection = DependencyService.Get<ISQLiteDb>().GetConnection();
// BindingContext = new HomePageViewModel();
try
{
// Method Calls
}
catch (Exception)
{
DisplayAlert("Error", "There was an error loading this page.", "OK");
}
}
protected override void OnAppearing()
{
this.Title = App.AppTitle;
this.firstStacklayout.Margin = new Thickness(0, (Application.Current.MainPage.Height * 0.25), 0, 0);
base.OnAppearing();
}
you are creating an instance of HomePage and trying to update it, but it is NOT the same instance that is being displayed in your MasterDetail
try something like this
var md = (MasterDetailPage)MainPage;
var nav = (NavigationPage)md.DetailPage;
var home = (HomePage)nav.CurrentPage;
home.ChangeBackgroundImage();
alternately, you could use MessagingCenter to send a message to HomePage requesting that it udpate

How to make multiline text on tab items in iOS

I got 5 tabs on TabbedPage & last 2 tabs have long title name, on Android, it shows 3dots as ... when there is no more room space remaining for text.
eg.
tab 1 title - Title 1 for Tab1
tab 2 title - Title 2 for Tab2
tab 3 title - Title 3 for Tab3
Android - Title 1 f... | Title 2 f... | Title 3 f...
But on iOS it doesn't show 3dots, it shows complete text which can even override the title of another tab. Kind of text overlapping.
Basically I want my title of TabbedPage on multi-line, I use different content pages as tabs for my TabbedPage.
I can create MultiLine ContentPage n its working fine on its own. But when I set the MultiLine title content page as a tab for my TabbedPage, it only shows the first-line title.
Any solution for MultiLine TabbedPage Title on iOS like below
My Current renderer code
[assembly: ExportRenderer( typeof( TabbedPage ), typeof(ExtendedTabbedPageRenderer ) )]
namespace testBlu.iOS.Renderers
{
public class ExtendedTabbedPageRenderer : TabbedRenderer
{
public override void ViewDidAppear( bool animated )
{
base.ViewDidAppear( animated );
if( TabBar.Items != null )
{
UITabBarItem[] tabs = TabBar.Items;
foreach( UITabBarItem tab in tabs )
{
UITextAttributes selectedColor = new UITextAttributes { TextColor = UIColor.Black };
UITextAttributes fontSize = new UITextAttributes { Font = UIFont.SystemFontOfSize( 12 )};
tab.SetTitleTextAttributes( selectedColor, UIControlState.Normal );
tab.SetTitleTextAttributes( fontSize, UIControlState.Normal );
}
}
}
}
}
If need to show three dots the same with Android , here is a solution for you . Later if have solution for multi-lines will update here .
You can use Custom TabbedRenderer to implement it .
[assembly: ExportRenderer(typeof(MainPage), typeof(ExtendedTabbedPageRenderer))]
namespace AppTab3.iOS
{
public class ExtendedTabbedPageRenderer : TabbedRenderer
{
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
var tabs = Element as TabbedPage;
if(tabs != null)
{
for( int i = 0;i < TabBar.Items.Length;i++)
{
if (TabBar.Items[i] == null) return;
if(TabBar.Items[i].Title.Length > 6)
{
string showText = TabBar.Items[i].Title;
TabBar.Items[i].Title = showText.Substring(0, 5) + "...";
}
}
}
}
}
}
Here MainPage inside code is a TabbedPage :public partial class MainPage : TabbedPage
And here I set the limited length of TabBar Text is 6 . The Xaml is as follow :
<?xml version="1.0" encoding="utf-8" ?>
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:views="clr-namespace:AppTab3.Views"
x:Class="AppTab3.Views.MainPage">
<TabbedPage.Children>
<NavigationPage Title="Browse">
<NavigationPage.Icon>
<OnPlatform x:TypeArguments="FileImageSource">
<On Platform="iOS" Value="tab_feed.png"/>
</OnPlatform>
</NavigationPage.Icon>
<x:Arguments>
<views:ItemsPage />
</x:Arguments>
</NavigationPage>
...
<NavigationPage Title="Page Five Long Title Page Five Long Title">
<NavigationPage.TitleView>
<Label Text="About Five Long Title" MaxLines="4"/>
</NavigationPage.TitleView>
<NavigationPage.Icon>
<OnPlatform x:TypeArguments="FileImageSource">
<On Platform="iOS"
Value="tab_about.png" />
</OnPlatform>
</NavigationPage.Icon>
<x:Arguments>
<views:AboutPage />
</x:Arguments>
</NavigationPage>
</TabbedPage.Children>
</TabbedPage>
The effect :
================================Update=============================
I have found the way to implement multiline title in tabbar item , need to modify code in TabbedRenderer as follow :
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
var tabs = Element as TabbedPage;
if (tabs != null)
{
for (int i = 0; i < TabBar.Items.Length; i++)
{
if (TabBar.Items[i] == null) continue;
if (TabBar.Items[i].Title.Length > 6)
{
string[] splitTitle = TabBar.Items[i].Title.Split(" ");
TabBar.Items[i].Title = splitTitle[0] + "\n" + splitTitle[1];
UITabBarItem item = TabBar.Items[i] as UITabBarItem;
UIView view = item.ValueForKey(new Foundation.NSString("view")) as UIView;
UILabel label = view.Subviews[1] as UILabel;
//label.Text = "Hello\nWorld!";
label.Lines = 2;
label.LineBreakMode = UILineBreakMode.WordWrap;
//var frame = label.Frame;
//label.Frame = CGRect.FromLTRB(frame.Location.X, frame.Location.Y, frame.Size.Width, frame.Size.Height + 20);
}
}
}
}
The effect:
Note : Althouh this way can implement it , however Apple not recommands to do this . It will affect the beauty of interface ,and make the frame of Tabbar item's shape distortion .
=============================Update with shared code=======================
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
var tabs = Element as TabbedPage;
if (tabs != null)
{
for (int i = 0; i < TabBar.Items.Length; i++)
{
if (TabBar.Items[i] == null) continue;
if (TabBar.Items[i].Title.Length > 6)
{
string[] splitTitle = TabBar.Items[i].Title.Split(" ");
if (null != splitTitle[1])
{
if (splitTitle[1].Length > 4)
{
string showText = splitTitle[1];
splitTitle[1] = showText.Substring(0, 3) + "...";
}
}
TabBar.Items[i].Title = splitTitle[0] + "\n" + splitTitle[1];
UITabBarItem item = TabBar.Items[i] as UITabBarItem;
UITextAttributes selectedColor = new UITextAttributes { TextColor = UIColor.Black };
UITextAttributes fontSize = new UITextAttributes { Font = UIFont.SystemFontOfSize(12) };
item.SetTitleTextAttributes(selectedColor, UIControlState.Selected);
item.SetTitleTextAttributes(fontSize, UIControlState.Selected);
UIView view = item.ValueForKey(new Foundation.NSString("view")) as UIView;
UILabel label = view.Subviews[1] as UILabel;
//label.Text = "Hello\nWorld!";
label.Lines = 2;
label.LineBreakMode = UILineBreakMode.WordWrap;
//var frame = label.Frame;
//label.Frame = CGRect.FromLTRB(frame.Location.X, frame.Location.Y, frame.Size.Width, frame.Size.Height + 10);
}
}
}
}
I think the most simple way (i.e, avoiding a custom renderer) would be to use a TitleView
Here's the official Microsoft sample.
https://learn.microsoft.com/en-us/samples/xamarin/xamarin-forms-samples/navigation-titleview/
Here's a blog post.
https://www.andrewhoefling.com/Blog/Post/xamarin-forms-title-view-a-powerful-navigation-view
In that TitleView you can use a Label and set the LineBreakMode property.

CustomPicker Ok and Cancel buttons' color

I have this custompicker class in android project:
public class CustomPickerRenderer : PickerRenderer
{
private Context context;
private IElementController ElementController => Element as IElementController;
private AlertDialog _dialog;
public CustomPickerRenderer(Context context) : base(context)
{
this.context = context;
}
protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
{
base.OnElementChanged(e);
if (Control == null || e.NewElement == null) return;
Control.Click += Control_Click1;
}
protected override void Dispose(bool disposing)
{
Control.Click -= Control_Click1;
base.Dispose(disposing);
}
private void Control_Click1(object sender, EventArgs e)
{
Picker model = Element;
var picker = new NumberPicker(Context);
if (model.Items != null && model.Items.Any())
{
picker.MaxValue = model.Items.Count - 1;
picker.MinValue = 0;
picker.SetDisplayedValues(model.Items.ToArray());
picker.WrapSelectorWheel = false;
picker.DescendantFocusability = DescendantFocusability.BlockDescendants;
picker.Value = model.SelectedIndex;
}
var layout = new LinearLayout(Context) { Orientation = Orientation.Vertical };
layout.AddView(picker);
ElementController.SetValueFromRenderer(VisualElement.IsFocusedProperty, true);
var builder = new AlertDialog.Builder(Context);
builder.SetView(layout);
builder.SetTitle(model.Title ?? "");
//change the text or color here
builder.SetNegativeButton(Html.FromHtml("<font color='#039BE5'>Cancel</font>"), (s, a) =>
{
ElementController.SetValueFromRenderer(VisualElement.IsFocusedProperty, false);
// It is possible for the Content of the Page to be changed when Focus is changed.
// In this case, we'll lose our Control.
Control?.ClearFocus();
_dialog = null;
});
//change the text or color here
builder.SetPositiveButton(Html.FromHtml("<font color='#039BE5'>OK</font>"), (s, a) =>
{
ElementController.SetValueFromRenderer(Picker.SelectedIndexProperty, picker.Value);
// It is possible for the Content of the Page to be changed on SelectedIndexChanged.
// In this case, the Element & Control will no longer exist.
if (Element != null)
{
if (model.Items.Count > 0 && Element.SelectedIndex >= 0)
Control.Text = model.Items[Element.SelectedIndex];
ElementController.SetValueFromRenderer(VisualElement.IsFocusedProperty, false);
// It is also possible for the Content of the Page to be changed when Focus is changed.
// In this case, we'll lose our Control.
Control?.ClearFocus();
}
_dialog = null;
});
_dialog = builder.Create();
_dialog.DismissEvent += (ssender, args) =>
{
ElementController?.SetValueFromRenderer(VisualElement.IsFocusedProperty, false);
};
_dialog.Show();
}
}
I tried running my project on my phone Xiaomi POCOPHONE F1 (Android 9) and 2 emulators (Android 8.1) and the colors of cancel and ok buttons are designed Perfectly. But when I tried running the project on Huawei PLE-701L and SAMSUNG SM-T365 (Android 5.1) the color of the buttons didn't changed.
Any suggestions?
Get the button object through the API of dialog and set the text color of the button. This method can be personalized. One point needs to be noted: it must be called after show
in your custom renderer,below _dialog.Show();
....
_dialog.Show();
Button btnOk = _dialog.GetButton((int)DialogInterface.ButtonPositive);
btnOk .SetTextColor(Color.Red);
Button btnCancel= _dialog.GetButton((int)DialogInterface.ButtonNegative);
btnCancel.SetTextColor(Color.Red);
add this style in style.xml
<style name="SpinnerDialog" parent="Theme.AppCompat.Light.Dialog">
<item name="android:popupBackground">#ff00ff</item>
<item name="colorPrimary">#ff00ff</item>
<item name="colorPrimaryDark">#ffff00</item>
<item name="colorAccent">#ff0000</item>
</style>
you can change allthe color including buttons.
and you can also use
<style name="AlertDialogCustom" parent="android:Theme.Material.Light.Dialog.Alert">
<item name="android:colorPrimary">#1e87f0</item>
<item name="android:colorAccent">#1e87f0</item>
</style>
<style name="AppCompatDialogStyle" parent="Theme.AppCompat.Light.Dialog">
<item name="colorAccent">#1e87f0</item>
</style>
The Question is answered here: Picker button's color not changing on android 5.1
I added the styles code in the correct answer in the link, and it worked!

Xamarin Forms Xlabs

I want to add a button which should be above the listView as same as how the whatsapp people have done and i want the same thing by using Xamarin Forms, i have tried doing with the xlab PopupLayout but i was unable to fix the position of the button as shown in the image the problem is with the different screen sizes and orientations..
So can any1 help me how to fix the location of the popup by using xlab popuplayout in xamarin forms and it should handle all the screen sizes and orientations.
Have a look at this great post by Alex Dunn. He implements a Floating Action Button (as it is called) on Android and iOS through Xamarin.Forms. It is basic, but you can extend on it yourself.
The gist is you create a control in your shared code, like this:
public partial class FloatingActionButton : Button
{
public static BindableProperty ButtonColorProperty = BindableProperty.Create(nameof(ButtonColor), typeof(Color), typeof(FloatingActionButton), Color.Accent);
public Color ButtonColor
{
get
{
return (Color)GetValue(ButtonColorProperty);
}
set
{
SetValue(ButtonColorProperty, value);
}
}
public FloatingActionButton()
{
InitializeComponent();
}
}
Now on Android implement a custom renderer, like this:
using FAB = Android.Support.Design.Widget.FloatingActionButton;
[assembly: ExportRenderer(typeof(SuaveControls.Views.FloatingActionButton), typeof(FloatingActionButtonRenderer))]
namespace SuaveControls.FloatingActionButton.Droid.Renderers
{
public class FloatingActionButtonRenderer : Xamarin.Forms.Platform.Android.AppCompat.ViewRenderer<SuaveControls.Views.FloatingActionButton, FAB>
{
protected override void OnElementChanged(ElementChangedEventArgs<SuaveControls.Views.FloatingActionButton> e)
{
base.OnElementChanged(e);
if (e.NewElement == null)
return;
var fab = new FAB(Context);
// set the bg
fab.BackgroundTintList = ColorStateList.ValueOf(Element.ButtonColor.ToAndroid());
// set the icon
var elementImage = Element.Image;
var imageFile = elementImage?.File;
if (imageFile != null)
{
fab.SetImageDrawable(Context.Resources.GetDrawable(imageFile));
}
fab.Click += Fab_Click;
SetNativeControl(fab);
}
protected override void OnLayout(bool changed, int l, int t, int r, int b)
{
base.OnLayout(changed, l, t, r, b);
Control.BringToFront();
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
var fab = (FAB)Control;
if (e.PropertyName == nameof(Element.ButtonColor))
{
fab.BackgroundTintList = ColorStateList.ValueOf(Element.ButtonColor.ToAndroid());
}
if (e.PropertyName == nameof(Element.Image))
{
var elementImage = Element.Image;
var imageFile = elementImage?.File;
if (imageFile != null)
{
fab.SetImageDrawable(Context.Resources.GetDrawable(imageFile));
}
}
base.OnElementPropertyChanged(sender, e);
}
private void Fab_Click(object sender, EventArgs e)
{
// proxy the click to the element
((IButtonController)Element).SendClicked();
}
}
}
And on iOS, like this:
[assembly: ExportRenderer(typeof(SuaveControls.Views.FloatingActionButton), typeof(FloatingActionButtonRenderer))]
namespace SuaveControls.FloatingActionButton.iOS.Renderers
{
[Preserve]
public class FloatingActionButtonRenderer : ButtonRenderer
{
public static void InitRenderer()
{
}
public FloatingActionButtonRenderer()
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
{
base.OnElementChanged(e);
if (e.NewElement == null)
return;
// remove text from button and set the width/height/radius
Element.WidthRequest = 50;
Element.HeightRequest = 50;
Element.BorderRadius = 25;
Element.BorderWidth = 0;
Element.Text = null;
// set background
Control.BackgroundColor = ((SuaveControls.Views.FloatingActionButton)Element).ButtonColor.ToUIColor();
}
public override void Draw(CGRect rect)
{
base.Draw(rect);
// add shadow
Layer.ShadowRadius = 2.0f;
Layer.ShadowColor = UIColor.Black.CGColor;
Layer.ShadowOffset = new CGSize(1, 1);
Layer.ShadowOpacity = 0.80f;
Layer.ShadowPath = UIBezierPath.FromOval(Layer.Bounds).CGPath;
Layer.MasksToBounds = false;
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == "ButtonColor")
{
Control.BackgroundColor = ((SuaveControls.Views.FloatingActionButton)Element).ButtonColor.ToUIColor();
}
}
}
}
You should now be able to use your button from XAML and code as you like.
Here is the XAML sample:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:SuaveControls.FabExample" xmlns:controls="clr-namespace:SuaveControls.Views;assembly=SuaveControls.FloatingActionButton" x:Class="SuaveControls.FabExample.MainPage">
<StackLayout Margin="32">
<Label Text="This is a Floating Action Button!" VerticalOptions="Center" HorizontalOptions="Center"/>
<controls:FloatingActionButton x:Name="FAB" HorizontalOptions="CenterAndExpand" WidthRequest="50" HeightRequest="50" VerticalOptions="CenterAndExpand" Image="ic_add_white.png" ButtonColor="#03A9F4" Clicked="Button_Clicked"/>
</StackLayout>
</ContentPage>
Please note that all credits for this go out to Alex. All his code for this is up here. In the past I have also used the NControls code code to create something like this. And I'm sure there are more awesome libraries out there. However, have a good look at the support for libraries. If I'm not mistake the XLabs packages aren't supported anymore.

Xamarin forms MasterDetailPage navigation

So ive been working on an app that uses a MasterDetail page and its going fine but Im just a little bit confused on how its suppose to navigate through pages.
At the moment i have the menu items opening some pages in the app and that parts working great, the side menu stays. The thing im confused with is how to handle having buttons on the main page being displayed. My buttons at the moment just open up a new page but the side menu of the MasterDetail page just disappears into the regular NavigationPage.
I will give my button code below.
btnSocial.GestureRecognizers.Add(new TapGestureRecognizer
{
Command = new Command(() =>
{
Navigation.PushAsync(new SocialPage());
})
});
Is this just how a MasterDetail page navigates or do you think im doing something wrong?
** EDITED **
Just incase this helps, i will attach my menuopage and launchpage code:
MenuPage.cs
public class MenuPage : ContentPage
{
public Action<ContentPage> OnMenuSelect { get; set; }
public MenuPage()
{
Title = "Menu";
Icon = "ic_menu.png";
BackgroundColor = ProjectVariables.PRIMARY_COLOR;
var items = new List<MenuItems>()
{
new MenuItems("Social", () => new SocialPage()),
new MenuItems("Career", () => null),
new MenuItems("MySchedule", () => null),
new MenuItems("Videos", () => null),
new MenuItems("Contact", () => null),
new MenuItems("Sign in", () => null)
};
var dataTemplate = new DataTemplate(typeof(TextCell));
dataTemplate.SetValue(TextCell.TextColorProperty, Color.White);
dataTemplate.SetBinding(TextCell.TextProperty, "Name");
var listview = new ListView()
{
ItemsSource = items,
ItemTemplate = dataTemplate
};
listview.BackgroundColor = ProjectVariables.PRIMARY_COLOR;
listview.ItemSelected += (object sender, SelectedItemChangedEventArgs e) =>
{
if(OnMenuSelect != null)
{
var item = (MenuItems)e.SelectedItem;
var itemPage = item.PageFn();
OnMenuSelect(itemPage);
}
};
Content = new StackLayout
{
Orientation = StackOrientation.Vertical,
Children =
{
listview
}
};
}
}
LaunchPage.cs
public class LaunchPage : MasterDetailPage
{
public LaunchPage()
{
var menuPage = new MenuPage();
menuPage.OnMenuSelect = (categoryPage) =>
{
Detail = new NavigationPage(categoryPage);
//Detail.Navigation.PushAsync(categoryPage);
IsPresented = false;
};
Master = menuPage;
Detail = new NavigationPage(new MainPage())
{
BarTextColor = Color.White,
BarBackgroundColor = ProjectVariables.PRIMARY_COLOR
};
MasterBehavior = MasterBehavior.Split;
}
}
Have a look at this documentation page from Xamarin.
It looks like you do not use the navigation service for this. You need a reference to your master page and set the Detail property for it.
Look at this section in particular.
public partial class MainPage : MasterDetailPage
{
public MainPage ()
{
...
masterPage.ListView.ItemSelected += OnItemSelected;
}
void OnItemSelected (object sender, SelectedItemChangedEventArgs e)
{
var item = e.SelectedItem as MasterPageItem;
if (item != null) {
Detail = new NavigationPage ((Page)Activator.CreateInstance (item.TargetType));
masterPage.ListView.SelectedItem = null;
IsPresented = false;
}
}
}
On the selection of a ListView item they set the Detail property and it will do the navigation for you.

Resources