2020.09.01.

Xamarin.Forms – NavigationPage Horizontal Alignment Center Title on Android

By bence960206

This project, you can find at: https://github.com/officialdoniald/Xamarin.Forms.CustomControls

We have to create some platforms specific code (custom NavigationPage Renderer), because in the base Xamarin.Forms code, we can’t find this implementation. So first step, we have to create a class in the .NET Standard/PCL project: CustomNavigationPage ( https://github.com/officialdoniald/Xamarin.Forms.CustomControls/blob/master/XamarinForms.CustomControls/XamarinForms.CustomControls/NavigationPage/CustomNavigationPage.cs ).

using Xamarin.Forms;
using XamarinForms.CustomControls.Enums;
namespace XamarinForms.CustomControls.NavigationPage
{
public class CustomNavigationPage : Xamarin.Forms.NavigationPage
{
public CustomNavigationPage() : base() { }
public CustomNavigationPage(Xamarin.Forms.Page page) : base(page) { }
public static readonly BindableProperty TitleFontFamilyProperty =
BindableProperty.Create(“TitleFontFamily”, typeof(string), typeof(Xamarin.Forms.NavigationPage), default(string));
public static readonly BindableProperty TitleFontSizeProperty =
BindableProperty.Create(“TitleFontSize”, typeof(float), typeof(Xamarin.Forms.NavigationPage), default(float));
public static readonly BindableProperty TitleHorizontalAlignmentProperty =
BindableProperty.Create(“TitleHorizontalAlignment”, typeof(HorizontalAlignment), typeof(Xamarin.Forms.NavigationPage), default(HorizontalAlignment));
public static readonly BindableProperty TitleFontAttributesProperty =
BindableProperty.Create(“TitleFontAttributes”, typeof(Enums.FontAttributes), typeof(Xamarin.Forms.NavigationPage), default(Enums.FontAttributes));
/// <summary>
/// Set the Horizontal Alignment of the Title.
/// </summary>
public HorizontalAlignment TitleHorizontalAlignment
{
get { return (HorizontalAlignment)GetValue(TitleHorizontalAlignmentProperty); }
set { SetValue(TitleHorizontalAlignmentProperty, value); }
}
/// <summary>
/// Set the Font Size of the Title.
/// </summary>
public float TitleFontSize
{
get { return (float)GetValue(TitleFontSizeProperty); }
set { SetValue(TitleFontSizeProperty, value); }
}
/// <summary>
/// Set the Font Family of the Title.
/// </summary>
public string TitleFontFamily
{
get { return (string)GetValue(TitleFontFamilyProperty); }
set { SetValue(TitleFontFamilyProperty, value); }
}
/// <summary>
/// Set the Font Attributes of the Title.
/// </summary>
public Enums.FontAttributes TitleFontAttributes
{
get { return (Enums.FontAttributes)GetValue(TitleFontAttributesProperty); }
set { SetValue(TitleFontAttributesProperty, value); }
}
}
}

Enums.FontAttributes is a custom enum, we can skip it, but here is the code: https://github.com/officialdoniald/Xamarin.Forms.CustomControls/blob/master/XamarinForms.CustomControls/XamarinForms.CustomControls/Enums/HelperEnums.cs

Second step: we have to implement in the Android code. Create a new class in the Droid Porject, call it: CustomNavigationPageRenderer ( https://github.com/officialdoniald/Xamarin.Forms.CustomControls/blob/master/XamarinForms.CustomControls/XamarinForms.CustomControls.Android/CustomRenderer/CustonNavigationPageRenderer.cs).

Implement the base class’s contructors, because it may not working:

public CustonNavigationPageRenderer() : base() { }
public CustonNavigationPageRenderer(Context context) : base(context) {}
public CustonNavigationPageRenderer(IntPtr a, JniHandleOwnership b) : base() { }

We have to override to base function:

protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
var page = (CustomNavigationPage)sender;
FontFamily = page.TitleFontFamily;
TitleHorizontalAlignment = page.TitleHorizontalAlignment;
TitleFontAttributes = page.TitleFontAttributes;
TitleFontSize = page.TitleFontSize;
}
protected override void OnLayout(bool changed, int l, int t, int r, int b)
{
base.OnLayout(changed, l, t, r, b);
SetTitle();
//if (view is LoginPage || view is PasswordResetPage || view is RegisterPage || view is SMSPage)
//{
// SetIcon();
//}
}

And create the SetTitle function:

private void SetTitle()
{
toolbar = GetToolbar();
if (toolbar != null)
{
for (var i = 0; i < toolbar.ChildCount; i++)
{
var Title = toolbar.GetChildAt(i);
if (Title is TextView)
{
var title = toolbar.GetChildAt(i) as TextView;
if (TitleHorizontalAlignment == HorizontalAlignment.Center)
{
//Title in center
float toolbarCenter = toolbar.Width / 2;
float titleCenter = title.Width / 2;
title.SetX(toolbarCenter – titleCenter);
}
//Title Font “HelveticaNeueLTStd”
if (!string.IsNullOrEmpty(FontFamily))
{
var typeface = Typeface.Create(FontFamily, ConvertFontAttributesToTypefaceStyle(TitleFontAttributes));
title.Typeface = typeface;
}
if (TitleFontSize != 0)
{
title.TextSize = TitleFontSize;
}
}
}
}
}

The default position of the Title on Android is Left, so we have to check just that, if the TitleHorizontalAlignment Property is Center. Or if we don’t create an enum, we just have to write without the if condition:

float toolbarCenter = toolbar.Width / 2;

float titleCenter = title.Width / 2;

title.SetX(toolbarCenter – titleCenter);

You can find the iOS implementation too: https://github.com/officialdoniald/Xamarin.Forms.CustomControls/blob/master/XamarinForms.CustomControls/XamarinForms.CustomControls.iOS/CustomRenderer/CustomNavigationPageRenderer.cs