Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using UIKit;
using MyAppName.iOS.Renderers;
[assembly: ExportRenderer(typeof(ContentPage), typeof(ContentPageRenderer))]
namespace MyAppName.iOS.Renderers
{
/// <summary>
/// Custom renderer for ContentPage that allows for action buttons to be on the left or the right hand side (ex: a modal with cancel and done buttons)
/// ToolbarItems need to have Priority set to 0 to show on the left, 1 to show on the right (ref: https://gist.github.com/alexlau811/f1fff9e726333e6b4a2f)
/// </summary>
public class ContentPageRenderer : PageRenderer
{
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
var contentPage = this.Element as ContentPage;
if (contentPage == null || NavigationController == null)
return;
var itemsInfo = contentPage.ToolbarItems;
var navigationItem = this.NavigationController.TopViewController.NavigationItem;
var leftNativeButtons = (navigationItem.LeftBarButtonItems ?? new UIBarButtonItem[] { }).ToList();
var rightNativeButtons = (navigationItem.RightBarButtonItems ?? new UIBarButtonItem[] { }).ToList();
var newLeftButtons = new UIBarButtonItem[] { }.ToList();
var newRightButtons = new UIBarButtonItem[] { }.ToList();
rightNativeButtons.ForEach(nativeItem =>
{
// [Hack] Get Xamarin private field "item"
var field = nativeItem.GetType().GetField("_item", BindingFlags.NonPublic | BindingFlags.Instance);
if (field == null)
return;
var info = field.GetValue(nativeItem) as ToolbarItem;
if (info == null)
return;
if (info.Priority == 0)
newLeftButtons.Add(nativeItem);
else
newRightButtons.Add(nativeItem);
});
leftNativeButtons.ForEach(nativeItem =>
{
newLeftButtons.Add(nativeItem);
});
navigationItem.RightBarButtonItems = newRightButtons.ToArray();
navigationItem.LeftBarButtonItems = newLeftButtons.ToArray();
}
}
}
@stefandevo

This comment has been minimized.

Copy link

commented Feb 14, 2016

You should add the leftNativeButtons again
leftNativeButtons.ForEach(nativeItem => { newLeftButtons.Add(nativeItem); });
Otherwise the left buttons will be remove when you move away from this page, and return.

@SmartyP

This comment has been minimized.

Copy link
Owner Author

commented May 10, 2016

@stefandevo Thanks for the heads up. I just updated it for that as well as using "_list" instead of "list" which is required for Xamarin.Forms 2.2+.

@BenDevelopment

This comment has been minimized.

Copy link

commented May 10, 2017

Thanks for your code. However, I have a problem when I navigate away and come back to the page. The ButtonItems are in both left and right bar. Any idea ?

@heinst

This comment has been minimized.

Copy link

commented Jul 20, 2017

@SmartyP If the there is a ToolbarItem with an image, it seems to not make it into the actual Toolbar, but if I remove the image and just have it as text it does. Any ideas why?

@isax5

This comment has been minimized.

Copy link

commented Aug 7, 2017

thanks. this is cool

@buchatsky

This comment has been minimized.

Copy link

commented Sep 15, 2017

I had to use ViewDidAppear with TabbedPage instead. And I also had to use ViewDidDisappear to clear left bar buttons in order to avoid their duplication:

        public override void ViewDidDisappear(bool animated)
        {
            base.ViewDidDisappear(animated);

            var contentPage = this.Element as ContentPage;
            if (contentPage == null || NavigationController == null)
                return;

            var navigationItem = this.NavigationController.TopViewController.NavigationItem;
            navigationItem.LeftBarButtonItems = null;
        }
@Unitarian

This comment has been minimized.

Copy link

commented Oct 3, 2017

@buchatsky
I am trying to do the same thing with Tabbed page. Aren't you supposed to use
var page = this.Element as TabbedPage;
instead of ContentPage.
Moreover I have only two items in toolbar and I want to move the first one to left and want to keep the second one to right.
Can you please post your complete code?

Cheers

@rk2022

This comment has been minimized.

Copy link

commented Oct 24, 2017

Thank you so much, it worked! but any idea how to do this for android?

@e10a

This comment has been minimized.

Copy link

commented Nov 8, 2017

Super helpful. Thank you!

@hansmbakker

This comment has been minimized.

Copy link

commented Apr 18, 2018

I would suggest to make the priority check respond to Priority="-1" instead of 0 because otherwise it will move the first toolbar element always to the left even on pages where you don't intend to.

@Shaboo

This comment has been minimized.

Copy link

commented May 22, 2018

any solution for duplicated items when using tabbedpage

@ryanmendoza

This comment has been minimized.

Copy link

commented Sep 21, 2018

This seems broken on the latest version of Xamarin.Forms (3.2.0.839982), Xamarin.iOS (12.0.0.15). This was working for me before upgrading. It appears that it can't find the private field "item" anymore.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.