Skip to content

Instantly share code, notes, and snippets.

@SmartyP
Last active November 17, 2018 06:03
Show Gist options
  • Save SmartyP/1b0ef834fb757baa51c2 to your computer and use it in GitHub Desktop.
Save SmartyP/1b0ef834fb757baa51c2 to your computer and use it in GitHub Desktop.
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
Copy link

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
Copy link
Author

SmartyP 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
Copy link

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
Copy link

heinst 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
Copy link

isax5 commented Aug 7, 2017

thanks. this is cool

@buchatsky
Copy link

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

@umaqs
Copy link

umaqs 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
Copy link

rk2022 commented Oct 24, 2017

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

@e10a
Copy link

e10a commented Nov 8, 2017

Super helpful. Thank you!

@hansmbakker
Copy link

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
Copy link

Shaboo commented May 22, 2018

any solution for duplicated items when using tabbedpage

@ryanmendoza
Copy link

ryanmendoza 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