Xamarin.Forms – CustomMasterDetailPage – change navigation icon(back button and “hamburger” menu button) – Android

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: CustomMasterDetailPage( https://github.com/officialdoniald/Xamarin.Forms.CustomControls/blob/master/XamarinForms.CustomControls/XamarinForms.CustomControls/MasterDetailPage/CustomMasterDetailPage.cs ).

using Xamarin.Forms; 
using XamarinForms.CustomControls.Enums;
namespace XamarinForms.CustomControls.MasterDetailPage
{
public class CustomMasterDetailPage : Xamarin.Forms.MasterDetailPage
{
public CustomMasterDetailPage() : base() { }
}
}

In Xamarin.Android, we can say that: ok, let’s change the back button and the hamburger menu button image forever, so we have to write an algorythm, that will change our icons. We have to watch the NavigationStack, and it’s count is equal to 1, we have to change the icon to a hamburger menu icon, otherwise we have to change the icon to a back button icon. Let’s do it.

So we have to write a MasterDetailPageRenderer class in the Android Project and we have to write the algorythm there.

 using Android.Content;
 using Android.Graphics;
 using Android.Graphics.Drawables;
 using Android.Runtime;
 using Android.Widget;
 using Plugin.CurrentActivity;
 using System;
 using Xamarin.Forms;
 using Xamarin.Forms.Platform.Android.AppCompat;
 using XamarinForms.CustomControls.Droid.CustomRenderer;
 using XamarinForms.CustomControls.MasterDetailPage;

[assembly: ExportRenderer(typeof(CustomMasterDetailPage), typeof(MasterNavigationPageRenderer))]
 namespace XamarinForms.CustomControls.Droid.CustomRenderer
 { 
pragma warning disable CS0618
public class MasterNavigationPageRenderer : MasterDetailPageRenderer
{
    private static Android.Support.V7.Widget.Toolbar GetToolbar() => (CrossCurrentActivity.Current?.Activity as MainActivity)?.FindViewById(Resource.Id.toolbar);

    private Android.Support.V7.Widget.Toolbar toolbar;

    public MasterNavigationPageRenderer() : base() { }

    public MasterNavigationPageRenderer(Context context) : base(context) { }

    public MasterNavigationPageRenderer(IntPtr a, JniHandleOwnership b) : base() { }

    protected override void OnLayout(bool changed, int l, int t, int r, int b)
    {
        base.OnLayout(changed, l, t, r, b);
        toolbar = GetToolbar();

        if (toolbar != null)
        {
            if (GlobalVariables.NavigationStackCount == 1)
            {
                SetNavigationButton(Resource.Drawable.menu);
            }
            else
            {
                SetNavigationButton(Resource.Drawable.back);
            }
        }
    }

    private void SetNavigationButton(int resourceID)
    {
        var icon = Forms.Context.GetDrawable(resourceID);
        using (var drawable = ((BitmapDrawable)icon).Bitmap)
        using (var bitmap = Bitmap.CreateScaledBitmap(drawable, 80, 80, false))
        using (var newDrawable = new BitmapDrawable(Resources, bitmap))
        {
            toolbar.NavigationIcon = newDrawable;
        }
    }
}
pragma warning restore CS0618
}
GlobalVariables.NavigationStackCount is public static variable. You can defined it in the .NET Standard/PCL project.

Next step, we have to create a platform specific NavigationPageRenderer. So let’s create a class in the .NET Standard/PCL project, and call it CustomNavigationPage ( https://github.com/officialdoniald/Xamarin.Forms.CustomControls/blob/master/XamarinForms.CustomControls/XamarinForms.CustomControls/NavigationPage/CustomNavigationPage.cs )

Than we have to create the platform spec. implementation in the Android project (https://github.com/officialdoniald/Xamarin.Forms.CustomControls/blob/master/XamarinForms.CustomControls/XamarinForms.CustomControls.Android/CustomRenderer/CustonNavigationPageRenderer.cs) :

 using System;
 using System.ComponentModel;
 using System.Threading.Tasks;
 using Android.Content;
 using Android.Graphics;
 using Android.Graphics.Drawables;
 using Android.Runtime;
 using Android.Support.V7.Graphics.Drawable;
 using Android.Util;
 using Android.Widget;
 using Plugin.CurrentActivity;
 using Xamarin.Forms;
 using Xamarin.Forms.Platform.Android;
 using XamarinForms.CustomControls.Droid.CustomRenderer;
 using XamarinForms.CustomControls.Enums;
 using XamarinForms.CustomControls.NavigationPage;
[assembly: ExportRenderer(typeof(CustomNavigationPage), typeof(CustonNavigationPageRenderer))] 
namespace XamarinForms.CustomControls.Droid.CustomRenderer
 { 
pragma warning disable CS0618
public class CustonNavigationPageRenderer : Xamarin.Forms.Platform.Android.AppCompat.NavigationPageRenderer
{
    #region Properties

    private static Android.Support.V7.Widget.Toolbar GetToolbar() => (CrossCurrentActivity.Current?.Activity as MainActivity)?.FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);

    private Android.Support.V7.Widget.Toolbar toolbar;

    private Page view;

    #endregion

    #region Kontruktor

    public CustonNavigationPageRenderer() : base() { }

    public CustonNavigationPageRenderer(Context context) : base(context) { }

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

    #endregion

 protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        base.OnElementPropertyChanged(sender, e);

        var page = (CustomNavigationPage)sender;
    }

    protected override void OnLayout(bool changed, int l, int t, int r, int b)
    {
        base.OnLayout(changed, l, t, r, b);

        //You can define special pages, where you can change the rule.
        //if (view is LoginPage || view is PasswordResetPage || view is RegisterPage || view is SMSPage)
        //{
        //    SetIcon();
        //}
    }

    protected override Task<bool> OnPushAsync(Page view, bool animated)
    {
        var retVal = base.OnPushAsync(view, animated);

        GlobalVariables.NavigationStackCount = view.Navigation.NavigationStack.Count;

        this.view = view;

        return retVal;
    }

    protected override Task<bool> OnPopToRootAsync(Page page, bool animated)
    {
        var retVal = base.OnPopToRootAsync(page, animated);

        GlobalVariables.NavigationStackCount = page.Navigation.NavigationStack.Count - 1;

        view = page;

        return retVal;
    }

    protected override Task<bool> OnPopViewAsync(Page page, bool animated)
    {
        var retVal = base.OnPopViewAsync(page, animated);

        GlobalVariables.NavigationStackCount = page.Navigation.NavigationStack.Count - 1;

        view = page;

        return retVal;
    }

    private void SetIcon()
    {
        toolbar = GetToolbar();

        if (toolbar != null)
        {
            if (GlobalVariables.NavigationStackCount == 1)
            {
                SetNavigationButton(Resource.Drawable.menu);
            }
            else
            {
                SetNavigationButton(Resource.Drawable.back);
            }
        }
    }

    private void SetNavigationButton(int resourceID)
    {
        var icon = Forms.Context.GetDrawable(resourceID);
        using (var drawable = ((BitmapDrawable)icon).Bitmap)
        using (var bitmap = Bitmap.CreateScaledBitmap(drawable, 80, 80, false))
        using (var newDrawable = new BitmapDrawable(Resources, bitmap))
        {
            toolbar.NavigationIcon = newDrawable;
        }
    }
}
pragma warning restore CS0618
}

Here the most important thing is to store the GlobalVariables.NavigationStackCount. Here can change the icons too.

Xamarin.Forms – CustomSearchBar

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: CustomSearchBar ( https://github.com/officialdoniald/Xamarin.Forms.CustomControls/blob/master/XamarinForms.CustomControls/XamarinForms.CustomControls/SearchBar/CustomSearchBar.cs ).

using Xamarin.Forms;
namespace XamarinForms.CustomControls.SearchBar
{
public class CustomSearchBar : Xamarin.Forms.SearchBar
{
public static readonly BindableProperty BorderColorProperty =
BindableProperty.Create(nameof(BorderColor), typeof(Color), typeof(CustomSearchBar));
public static readonly BindableProperty BorderWidthProperty =
BindableProperty.Create(nameof(BorderWidth), typeof(int), typeof(CustomSearchBar));
/// <summary>
/// Set the Border Color of the SearchBar.
/// </summary>
public Color BorderColor
{
set { SetValue(BorderColorProperty, value); }
get { return (Color)GetValue(BorderColorProperty); }
}
/// <summary>
/// Set the Border Width of the SearchBar.
/// </summary>
public int BorderWidth
{
set { SetValue(BorderWidthProperty, value); }
get { return (int)GetValue(BorderWidthProperty); }
}
}
}

Now, we have to implement to the various platforms. Let’s try with the Android part: https://github.com/officialdoniald/Xamarin.Forms.CustomControls/blob/master/XamarinForms.CustomControls/XamarinForms.CustomControls.Android/CustomRenderer/CustomSearchBarRenderer.cs

With this code, you can change the search icon of the searchbar:

int searchIconId = Context.Resources.GetIdentifier(“android:id/search_mag_icon”, null, null);
var icon = searchView.FindViewById(searchIconId);
(icon as ImageView).SetImageResource(Resource.Drawable.searchbaricon);

You have to create an image in the Resources/Drawable folder with this name: searchbaricon.png (you can change it, but don’t forget to rename Resource.Drawable.your_drawable).

iOS part:

using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using XamarinForms.CustomControls.iOS.CustomRenderer;
using XamarinForms.CustomControls.SearchBar;
[assembly: ExportRenderer(typeof(CustomSearchBar), typeof(CustomSearchBarRenderer))]
namespace XamarinForms.CustomControls.iOS.CustomRenderer
{
public class CustomSearchBarRenderer : SearchBarRenderer
{
#region Properties
private UIColor BorderColor = UIColor.Black;
private int BorderWidth = 1;
#endregion
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.SearchBar> e)
{
base.OnElementChanged(e);
var newElement = ((CustomSearchBar)e.NewElement);
BorderColor = newElement.BorderColor.ToUIColor();
if (newElement.BorderWidth != 0)
{
BorderWidth = newElement.BorderWidth;
}
var searchbar = (UISearchBar)Control;
if (e.NewElement != null)
{
//Foundation.NSString _searchField = new Foundation.NSString(“searchField”);
//var textFieldInsideSearchBar = (UITextField)searchbar.ValueForKey(_searchField);
//textFieldInsideSearchBar.BackgroundColor = UIColor.FromRGB(0, 0, 12);
//textFieldInsideSearchBar.TextColor = UIColor.White;
// searchbar.Layer.BackgroundColor = UIColor.Blue.CGColor;
//searchbar.TintColor = UIColor.White;
//searchbar.BarTintColor = UIColor.White;
searchbar.Layer.CornerRadius = 0;
searchbar.Layer.BorderWidth = BorderWidth;
searchbar.Layer.BorderColor = BorderColor.CGColor;
//searchbar.ShowsCancelButton = false;
}
}
}
}

Xamarin.Forms – CustomEntry (BorderWidth, BorderColor and TextPadding)

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: CustomEntry ( https://github.com/officialdoniald/Xamarin.Forms.CustomControls/blob/master/XamarinForms.CustomControls/XamarinForms.CustomControls/Entry/CustomEntry.cs ).

using Xamarin.Forms;
namespace XamarinForms.CustomControls.Entry
{
public class CustomEntry : Xamarin.Forms.Entry
{
public static readonly BindableProperty BorderColorProperty =
BindableProperty.Create(nameof(BorderColor), typeof(Color), typeof(CustomEntry));
public static readonly BindableProperty BorderWidthProperty =
BindableProperty.Create(nameof(BorderWidth), typeof(int), typeof(CustomEntry));
public static readonly BindableProperty TextPaddingProperty =
BindableProperty.Create(nameof(TextPadding), typeof(Thickness), typeof(CustomEntry));
/// <summary>
/// Set the Border Color of the Entry.
/// </summary>
public Color BorderColor
{
set { SetValue(BorderColorProperty, value); }
get { return (Color)GetValue(BorderColorProperty); }
}
/// <summary>
/// Set the Border Width of the Entry.
/// </summary>
public int BorderWidth
{
set { SetValue(BorderWidthProperty, value); }
get { return (int)GetValue(BorderWidthProperty); }
}
/// <summary>
/// Set the Text Padding of the Entry.
/// </summary>
public Thickness TextPadding
{
set { SetValue(TextPaddingProperty, value); }
get { return (Thickness)GetValue(TextPaddingProperty); }
}
}
}

Now, we have to implement to the various platforms. Let’s begin with Android: https://github.com/officialdoniald/Xamarin.Forms.CustomControls/blob/master/XamarinForms.CustomControls/XamarinForms.CustomControls.Android/CustomRenderer/CustomEntryRenderer.cs

using System;
using System.ComponentModel;
using Android.Content;
using Android.Graphics;
using Android.Graphics.Drawables;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using XamarinForms.CustomControls.Droid.CustomRenderer;
using XamarinForms.CustomControls.Entry;
[assembly: ExportRenderer(typeof(CustomEntry), typeof(CustomEntryRenderer))]
namespace XamarinForms.CustomControls.Droid.CustomRenderer
{
#pragma warning disable CS0618
public class CustomEntryRenderer : EntryRenderer
{
private Android.Graphics.Color BorderColor = Android.Graphics.Color.Black;
private int BorderWidth = 1;
private Thickness TextPadding = new Thickness(0);
private CustomEntry CustomEntry;
#endregion
#region Konstruktor
public CustomEntryRenderer() : base() { }
public CustomEntryRenderer(Context context) : base(context) { }
public CustomEntryRenderer(IntPtr a, JniHandleOwnership b) : base() { }
#endregion
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
BorderColor = CustomEntry.BorderColor.ToAndroid();
if (CustomEntry.BorderWidth != 0)
{
BorderWidth = CustomEntry.BorderWidth;
}
TextPadding = CustomEntry.TextPadding;
}
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Entry> e)
{
base.OnElementChanged(e);
CustomEntry = e.NewElement as CustomEntry;
}
protected override void OnLayout(bool changed, int l, int t, int r, int b)
{
base.OnLayout(changed, l, t, r, b);
if (CustomEntry != null)
{
ChangeCustomEntryProperties(CustomEntry);
Control.Gravity = GravityFlags.CenterVertical;
int left = Convert.ToInt32(TextPadding.Left);
int right = Convert.ToInt32(TextPadding.Right);
int top = Convert.ToInt32(TextPadding.Top);
int bottom = Convert.ToInt32(TextPadding.Bottom);
Control.SetPadding(left, top, right, bottom);
IntPtr IntPtrtextViewClass = JNIEnv.FindClass(typeof(TextView));
IntPtr mCursorDrawableResProperty = JNIEnv.GetFieldID(IntPtrtextViewClass, “mCursorDrawableRes”, “I”);
JNIEnv.SetField(Control.Handle, mCursorDrawableResProperty, Resource.Drawable.my_cursor);
}
}
private void ChangeCustomEntryProperties(CustomEntry entry)
{
var customEntry = entry;
var nativeEditText = (EditText)Control;
var shape = new ShapeDrawable(new Android.Graphics.Drawables.Shapes.RectShape());
shape.Paint.Color = BorderColor;
shape.Paint.SetStyle(Paint.Style.Stroke);
nativeEditText.Background = shape;
GradientDrawable gd = new GradientDrawable();
gd.SetColor(Android.Graphics.Color.White);
gd.SetStroke(BorderWidth, BorderColor);
nativeEditText.SetBackground(gd);
}
}
#pragma warning restore CS0618
}

This code:

IntPtr IntPtrtextViewClass = JNIEnv.FindClass(typeof(TextView));

IntPtr mCursorDrawableResProperty = JNIEnv.GetFieldID(IntPtrtextViewClass, “mCursorDrawableRes”, “I”);

will change the cursor’s color. If you want to really change the color of the cursor, you have to create in the Resources/Drawable folder a my_cursor.xml file:

<shape xmlns:android=”http://schemas.android.com/apk/res/android” android:shape=”rectangle”>
<solid android:color=”@color/colorCursors”></solid>
<size android:width=”2dp” />
</shape>

@color/colorCursors is a color from the Resources/values/color.xml. If you don’t have this file, just create it:

<?xml version=”1.0″ encoding=”utf-8″?>
<resources>
<color name=”launcher_background”>#FFFFFF</color>
<color name=”colorPrimary”>#3F51B5</color>
<color name=”colorPrimaryDark”>#303F9F</color>
<color name=”colorAccent”>#FF4081</color>
<color name=”colorCursors”>#000000</color>
</resources>

<color name=”colorCursors”>#000000</color> here can you gain the color of the cursor.

If you don’t want to change, just skip this code, comment in it.

Now continue with the iOS site: https://github.com/officialdoniald/Xamarin.Forms.CustomControls/blob/master/XamarinForms.CustomControls/XamarinForms.CustomControls.iOS/CustomRenderer/CustomEntryRenderer.cs

using System.ComponentModel;
using CoreGraphics;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using XamarinForms.CustomControls.Entry;
using XamarinForms.CustomControls.iOS.CustomRenderer;
[assembly: ExportRenderer(typeof(CustomEntry), typeof(CustomEntryRenderer))]
namespace XamarinForms.CustomControls.iOS.CustomRenderer
{
public class CustomEntryRenderer : EntryRenderer
{
#region Properties
private UIColor BorderColor = UIColor.Black;
private int BorderWidth = 1;
private Thickness TextPadding = new Thickness(0);
#endregion
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
var element = ((CustomEntry)sender);
BorderColor = element.BorderColor.ToUIColor();
BorderWidth = element.BorderWidth;
TextPadding = element.TextPadding;
}
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Entry> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.Layer.BorderWidth = BorderWidth;
Control.VerticalAlignment = UIControlContentVerticalAlignment.Center;
Control.LeftView = new UIView(new CGRect(TextPadding.Left, TextPadding.Top, TextPadding.Right, TextPadding.Bottom));
Control.LeftViewMode = UITextFieldViewMode.Always;
Control.TintColor = UIColor.Black;
Control.Layer.BorderColor = BorderColor.CGColor;
//Control.RightView = new UIView(new CGRect(0, 0, 15, 0));
//Control.RightViewMode = UITextFieldViewMode.Always;
//// Use tint color to change the cursor’s color
//Control.TintColor = UIColor.White;
}
}
}
}

Xamarin.Forms – ListView – CustomTextCell

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: CustomTextCell ( https://github.com/officialdoniald/Xamarin.Forms.CustomControls/blob/master/XamarinForms.CustomControls/XamarinForms.CustomControls/ListView/CustomTextCell.cs ).

using Xamarin.Forms;
namespace XamarinForms.CustomControls.ListView
{
public class CustomTextCell : TextCell
{
public static readonly BindableProperty TextFontSizeProperty =
BindableProperty.Create(“TextFontSize”, typeof(double), typeof(CustomTextCell), default(double));
public static readonly BindableProperty DetailFontSizeProperty =
BindableProperty.Create(“DetailFontSize”, typeof(double), typeof(CustomTextCell), default(double));
public static readonly BindableProperty TextFontAttributesProperty =
BindableProperty.Create(“TextFontAttributes”, typeof(Enums.FontAttributes), typeof(CustomTextCell), default(Enums.FontAttributes));
public static readonly BindableProperty TextFontFamilyProperty =
BindableProperty.Create(“TextFontFamily”, typeof(string), typeof(CustomTextCell), default(string));
public static readonly BindableProperty DetailFontAttributesProperty =
BindableProperty.Create(“DetailFontAttributes”, typeof(Enums.FontAttributes), typeof(CustomTextCell), default(Enums.FontAttributes));
public static readonly BindableProperty DetailFontFamilyProperty =
BindableProperty.Create(“DetailFontFamily”, typeof(string), typeof(CustomTextCell), default(string));
/// <summary>
/// Set the Text font size.
/// </summary>
public double TextFontSize
{
get { return (double)GetValue(TextFontSizeProperty); }
set { SetValue(TextFontSizeProperty, value); }
}
/// <summary>
/// Set the Detail font size.
/// </summary>
public double DetailFontSize
{
get { return (double)GetValue(DetailFontSizeProperty); }
set { SetValue(DetailFontSizeProperty, value); }
}
/// <summary>
/// Set the Font Attributes of the Text.
/// </summary>
public Enums.FontAttributes TextFontAttributes
{
get { return (Enums.FontAttributes)GetValue(TextFontAttributesProperty); }
set { SetValue(TextFontAttributesProperty, value); }
}
/// <summary>
/// Set the Font Family of the Text.
/// </summary>
public string TextFontFamily
{
get { return (string)GetValue(TextFontFamilyProperty); }
set { SetValue(TextFontFamilyProperty, value); }
}
/// <summary>
/// Set the Font Attributes of the Detail.
/// </summary>
public Enums.FontAttributes DetailFontAttributes
{
get { return (Enums.FontAttributes)GetValue(DetailFontAttributesProperty); }
set { SetValue(DetailFontAttributesProperty, value); }
}
/// <summary>
/// Set the Font Family of the Detail.
/// </summary>
public string DetailFontFamily
{
get { return (string)GetValue(DetailFontFamilyProperty); }
set { SetValue(DetailFontFamilyProperty, value); }
}
}
}

Enums.FontAttributes is a custtom enum class, we can create it, but we can skip it too. You can find it at: https://github.com/officialdoniald/Xamarin.Forms.CustomControls/blob/master/XamarinForms.CustomControls/XamarinForms.CustomControls/Enums/HelperEnums.cs

Now we have to implement the platform spec. code at the various platforms.

Let’s begin with the Android site ( https://github.com/officialdoniald/Xamarin.Forms.CustomControls/blob/master/XamarinForms.CustomControls/XamarinForms.CustomControls.Android/CustomRenderer/CustomTextCellRenderer.cs ):

First, we have to implement the base class’s contructor:

public CustomTextCellRenderer() : base() { }
public CustomTextCellRenderer(System.IntPtr a, Android.Runtime.JniHandleOwnership b) : base() { }

Then we have to override the GetCellCore base function:

protected override Android.Views.View GetCellCore(Cell item, Android.Views.View convertView, ViewGroup parent, Android.Content.Context context)
{
var view = (CustomTextCell)item;
if (convertView == null)
{
convertView = new BaseCellView(context, item);
}
if (convertView is BaseCellView cellView)
{
cellView.SetImageVisible(false);
cellView.MainText = view.Text;
cellView.DetailText = view.Detail;
cellView.SetMainTextColor(view.TextColor);
cellView.SetDetailTextColor(view.DetailColor);
var control = ((LinearLayout)convertView);
if (control.GetChildAt(1) is LinearLayout linearLayout)
{
var mainTextView = (TextView)linearLayout.GetChildAt(0);
var detailTextView = (TextView)linearLayout.GetChildAt(1);
mainTextView.TextSize = (float)view.TextFontSize;
detailTextView.TextSize = (float)view.DetailFontSize;
var titleTypeface = Typeface.Create(view.TextFontFamily, ConvertFontAttributesToTypefaceStyle(view.TextFontAttributes));
var detailTypeface = Typeface.Create(view.DetailFontFamily, ConvertFontAttributesToTypefaceStyle(view.DetailFontAttributes));
mainTextView.Typeface = titleTypeface;
detailTextView.Typeface = detailTypeface;
}
}
return _cellCore = convertView;
}

If we implement the custom FontAttribute enum, we have to create the ConvertFontAttributesToTypefaceStyle() function:

private TypefaceStyle ConvertFontAttributesToTypefaceStyle(Enums.FontAttributes fontAttributes)
{
if (fontAttributes == Enums.FontAttributes.Bold)
{
return Android.Graphics.TypefaceStyle.Bold;
}
else if (fontAttributes == Enums.FontAttributes.BoldItalic)
{
return Android.Graphics.TypefaceStyle.BoldItalic;
}
else if (fontAttributes == Enums.FontAttributes.Italic)
{
return Android.Graphics.TypefaceStyle.Italic;
}
else return Android.Graphics.TypefaceStyle.Normal;
}

Let’s continue with the iOS site ( https://github.com/officialdoniald/Xamarin.Forms.CustomControls/blob/master/XamarinForms.CustomControls/XamarinForms.CustomControls.iOS/CustomRenderer/CustomTextCellRenderer.cs ):

The mechanism is the same, but we don’t need to implement the base class’s constructors, but we need to override the GetCell() function:

using Foundation;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using XamarinForms.CustomControls.iOS.CustomRenderer;
using XamarinForms.CustomControls.ListView;
[assembly: ExportRenderer(typeof(CustomTextCell), typeof(CustomTextCellRenderer))]
namespace XamarinForms.CustomControls.iOS.CustomRenderer
{
public class CustomTextCellRenderer : TextCellRenderer
{
public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
{
var view = (CustomTextCell)item;
var cell = base.GetCell(item, reusableCell, tv);
//cell.SelectedBackgroundView = new UIView { BackgroundColor = UIColor.Red };
var TextLabel = cell.TextLabel;
var DetailTextLabel = cell.DetailTextLabel;
TextLabel.Font = UIFont.FromName(view.TextFontFamily, (int)view.TextFontSize);
DetailTextLabel.Font = UIFont.FromName(view.DetailFontFamily, (int)view.DetailFontSize);
TextLabel.AttributedText = ConvertAttributes(TextLabel.Text, view.TextFontAttributes, (int)view.TextFontSize);
DetailTextLabel.AttributedText = ConvertAttributes(DetailTextLabel.Text, view.DetailFontAttributes, (int)view.DetailFontSize);
return cell;
}
private NSMutableAttributedString ConvertAttributes(string text, Enums.FontAttributes attr, int size)
{
if (attr == Enums.FontAttributes.Bold)
{
return new NSMutableAttributedString(
str: text,
font: UIFont.BoldSystemFontOfSize(size)
);
}
else if (attr == Enums.FontAttributes.Italic)
{
return new NSMutableAttributedString(
str: text,
font: UIFont.ItalicSystemFontOfSize(size)
);
}
//else if (attr == Enums.FontAttributes.BoldItalic)
//{
// var textattr = new NSMutableAttributedString(
// str: text,
// font: UIFont.BoldSystemFontOfSize(size)
// );
// textattr.Append(new NSMutableAttributedString(
// str: text,
// font: UIFont.ItalicSystemFontOfSize(size)
// ));
// return textattr;
//}
else
{
return new NSMutableAttributedString(
str: text,
font: UIFont.SystemFontOfSize(size)
);
}
}
}
}