Skip to content

Instantly share code, notes, and snippets.

@SmartyP
Last active November 25, 2024 15:47
Show Gist options
  • Select an option

  • Save SmartyP/1b0ef834fb757baa51c2 to your computer and use it in GitHub Desktop.

Select an option

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

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

SmartyP commented May 10, 2016

Copy link
Copy Markdown
Author

@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
Copy Markdown

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

heinst commented Jul 20, 2017

Copy link
Copy Markdown

@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

isax5 commented Aug 7, 2017

Copy link
Copy Markdown

thanks. this is cool

@buchatsky

buchatsky commented Sep 15, 2017

Copy link
Copy Markdown

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

umaqs commented Oct 3, 2017

Copy link
Copy Markdown

@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

rk2022 commented Oct 24, 2017

Copy link
Copy Markdown

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

@e10a

e10a commented Nov 8, 2017

Copy link
Copy Markdown

Super helpful. Thank you!

@hansmbakker

Copy link
Copy Markdown

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

Shaboo commented May 22, 2018

Copy link
Copy Markdown

any solution for duplicated items when using tabbedpage

@ryanmendoza

ryanmendoza commented Sep 21, 2018

Copy link
Copy Markdown

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