I've created some custom elements such as a CustomTextView, so I can change at desire some visual styles such as fontsize, font family etc. This is the code for my CustomTextView:
using System;
using Android.Content;
using Android.Graphics;
using Android.Runtime;
using Android.Util;
using Android.Widget;
using myapp.Core;
using myapp.Models;
namespace myapp.Views.CustomControls
{
public class TextViewCustom : TextView
{
private Color color;
private Typeface customFont;
private CUSTOM_FONTS_SIZE textSize;
protected TextViewCustom(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
{
}
public TextViewCustom(Context context) : base(context)
{
Initialize(context);
}
public TextViewCustom(Context context, IAttributeSet attrs) : base(context, attrs)
{
Initialize(context, attrs);
}
private void Initialize(Context context, IAttributeSet attrs = null)
{
color = AppearanceManager.ColorPrimary;
customFont = AppearanceManager.Typeface;
textSize = CUSTOM_FONTS_SIZE.SMALL;
int textType = 0;
int colorType = 0;
if (attrs != null)
{
var array = context.ObtainStyledAttributes(attrs, Resource.Styleable.text_view_custom, 0, 0);
colorType = array.GetInt(Resource.Styleable.text_view_custom_tvc_color, colorType);
textType = array.GetInt(Resource.Styleable.text_view_custom_tvc_type, textType);
array.Recycle();
}
switch (colorType)
{
case 1: color = AppearanceManager.ColorPrimary;
break;
case 2: color = AppearanceManager.ColorSecundary;
break;
default: colorType = 0;
break;
}
switch (textType)
{
case 1: textSize = CUSTOM_FONTS_SIZE.SMALL;
break;
case 2: textSize = CUSTOM_FONTS_SIZE.MIDDLE;
break;
case 3: textSize = CUSTOM_FONTS_SIZE.LARGE;
break;
case 4: textSize = CUSTOM_FONTS_SIZE.TINY;
break;
}
if(colorType > 0) SetTextColor(color);
SetTypeface(customFont, TypefaceStyle.Normal);
SetTextSize(ComplexUnitType.Px, AppearanceManager.TypefaceSize(textSize));
}
}
}
, this
using System;
using Android.Graphics;
using myapp.Core;
namespace myapp.Models
{
public enum CUSTOM_FONTS_STYLE { DEFAULT, SEGOE_UI, BUBLE_JELLY_SHADOW, AUGUSTA, VCR_OSD_MONO, SWEET_PURPLE}
public enum CUSTOM_FONTS_SIZE { SMALL, MIDDLE, LARGE, TINY }
public class AppearanceInfo
{
public Color? ColorPrimary { get; set; }
public Color? ColorPrimaryDark { get; set; }
public Color? ColorPrimaryText { get; set; }
public Color? ColorSecundary { get; set; }
public Color? ColorSecundaryDark { get; set; }
public Color? ColorSecundaryText { get; set; }
public CUSTOM_FONTS_STYLE CustomFont { get; set; }
public void SetColorPrimaryFromHex(string hexColor)
{
if (hexColor.IndexOf("#", StringComparison.Ordinal) != 0) hexColor = $"#{hexColor}";
if (!Utils.IsValidHexColor(hexColor)) return;
ColorPrimary = Color.ParseColor(hexColor);
}
public void SetColorPrimaryDarkFromHex(string hexColor)
{
if (hexColor.IndexOf("#", StringComparison.Ordinal) != 0) hexColor = $"#{hexColor}";
if (!Utils.IsValidHexColor(hexColor)) return;
ColorPrimaryDark = Color.ParseColor(hexColor);
}
public void SetColorPrimaryTextFromHex(string hexColor)
{
if (hexColor.IndexOf("#", StringComparison.Ordinal) != 0) hexColor = $"#{hexColor}";
if (!Utils.IsValidHexColor(hexColor)) return;
ColorPrimaryText = Color.ParseColor(hexColor);
}
public void SetColorSecundaryFromHex(string hexColor)
{
if (hexColor.IndexOf("#", StringComparison.Ordinal) != 0) hexColor = $"#{hexColor}";
if (!Utils.IsValidHexColor(hexColor)) return;
ColorSecundary = Color.ParseColor(hexColor);
}
public void SetColorSecundaryDarkFromHex(string hexColor)
{
if (hexColor.IndexOf("#", StringComparison.Ordinal) != 0) hexColor = $"#{hexColor}";
if (!Utils.IsValidHexColor(hexColor)) return;
ColorSecundaryDark = Color.ParseColor(hexColor);
}
public void SetColorSecundaryTextFromHex(string hexColor)
{
if (hexColor.IndexOf("#", StringComparison.Ordinal) != 0) hexColor = $"#{hexColor}";
if (!Utils.IsValidHexColor(hexColor)) return;
ColorSecundaryText = Color.ParseColor(hexColor);
}
}
}
and finally this:
using Android.Graphics;
using myapp.Models;
namespace myapp.Core
{
public enum APPEARANCES_TEMPORAL { DEFAULT, MEDIEVAL, GAMER, MODERN, CHILDREN, CUTE }
public static class AppearanceManager
{
private static AppearanceInfo _customAppearance;
public static Color ColorPrimary { get; private set; }
public static Color ColorPrimaryDark { get; private set; }
public static Color ColorPrimaryText { get; private set; }
public static Color ColorSecundary { get; private set; }
public static Color ColorSecundaryDark { get; private set; }
public static Color ColorSecundaryText { get; private set; }
public static Typeface Typeface
{
get
{
if (_customAppearance == null || _customAppearance.CustomFont == CUSTOM_FONTS_STYLE.DEFAULT)
return Typeface.Default;
switch (_customAppearance.CustomFont)
{
case CUSTOM_FONTS_STYLE.SEGOE_UI:
return LocalResourceProvider.GetFont(Resource.Font.segoe_ui);
case CUSTOM_FONTS_STYLE.BUBLE_JELLY_SHADOW:
return LocalResourceProvider.GetFont(Resource.Font.buble_jelly_shadow);
case CUSTOM_FONTS_STYLE.VCR_OSD_MONO:
return LocalResourceProvider.GetFont(Resource.Font.vcr_osd_mono);
case CUSTOM_FONTS_STYLE.AUGUSTA:
return LocalResourceProvider.GetFont(Resource.Font.augusta);
case CUSTOM_FONTS_STYLE.SWEET_PURPLE:
return LocalResourceProvider.GetFont(Resource.Font.sweet_purple);
default:
return Typeface.Default;
}
}
}
public static float TypefaceSize(CUSTOM_FONTS_SIZE size)
{
float tinySize = LocalResourceProvider.GetDimension(Resource.Dimension.textTiny);
float smallSize = LocalResourceProvider.GetDimension(Resource.Dimension.textSmall);
float middleSize = LocalResourceProvider.GetDimension(Resource.Dimension.textMiddle);
float largeSize = LocalResourceProvider.GetDimension(Resource.Dimension.textLarge);
if (_customAppearance != null)
{
if (_customAppearance.CustomFont == CUSTOM_FONTS_STYLE.SWEET_PURPLE)
{
tinySize = LocalResourceProvider.SpToPx(17);
smallSize = LocalResourceProvider.SpToPx(20);
middleSize = LocalResourceProvider.SpToPx(25);
largeSize = LocalResourceProvider.SpToPx(30);
}
//ADD MORE CUSTOM SIZES WHEN NECESSARY
}
if (size == CUSTOM_FONTS_SIZE.TINY) return tinySize;
if (size == CUSTOM_FONTS_SIZE.SMALL) return smallSize;
if (size == CUSTOM_FONTS_SIZE.MIDDLE) return middleSize;
if (size == CUSTOM_FONTS_SIZE.LARGE) return largeSize;
return smallSize;
}
public static void LoadDefaultAppearance()
{
ColorPrimary = LocalResourceProvider.GetColor(Resource.Color.primary);
ColorPrimaryDark = LocalResourceProvider.GetColor(Resource.Color.primaryDark);
ColorSecundary = LocalResourceProvider.GetColor(Resource.Color.secundary);
ColorSecundaryDark = LocalResourceProvider.GetColor(Resource.Color.secundaryDark);
ColorPrimaryText = Color.White;
ColorSecundaryText = Color.White;
_customAppearance = null;
}
public static void LoadCustomAppearance(AppearanceInfo customAppearance)
{
LoadDefaultAppearance();
if (customAppearance == null) return;
_customAppearance = customAppearance;
ColorPrimary = _customAppearance.ColorPrimary ?? ColorPrimary;
ColorPrimaryDark = _customAppearance.ColorPrimaryDark ?? ColorPrimaryDark;
ColorPrimaryText = _customAppearance.ColorPrimaryText ?? ColorPrimaryText;
ColorSecundary = _customAppearance.ColorSecundary ?? ColorSecundary;
ColorSecundaryDark = _customAppearance.ColorSecundaryDark ?? ColorSecundaryDark;
ColorSecundaryText = _customAppearance.ColorSecundaryText ?? ColorSecundaryText;
}
public static void SetAppearanceTemporal(APPEARANCES_TEMPORAL appearanceType)
{
switch (appearanceType)
{
case APPEARANCES_TEMPORAL.MEDIEVAL:
AppearanceInfo MedievalAppearance = new AppearanceInfo();
MedievalAppearance.SetColorPrimaryFromHex("5d4037");
MedievalAppearance.SetColorPrimaryDarkFromHex("3e2723");
MedievalAppearance.SetColorPrimaryTextFromHex("ffd54f");
MedievalAppearance.SetColorSecundaryFromHex("607d8b");
MedievalAppearance.SetColorSecundaryDarkFromHex("455a64");
MedievalAppearance.CustomFont = CUSTOM_FONTS_STYLE.AUGUSTA;
LoadCustomAppearance(MedievalAppearance);
break;
case APPEARANCES_TEMPORAL.GAMER:
AppearanceInfo GamerAppearance = new AppearanceInfo();
GamerAppearance.SetColorPrimaryFromHex("212121");
GamerAppearance.SetColorPrimaryDarkFromHex("212121");
GamerAppearance.SetColorPrimaryTextFromHex("ffff00");
GamerAppearance.SetColorSecundaryFromHex("212121");
GamerAppearance.SetColorSecundaryDarkFromHex("212121");
GamerAppearance.CustomFont = CUSTOM_FONTS_STYLE.VCR_OSD_MONO;
LoadCustomAppearance(GamerAppearance);
break;
case APPEARANCES_TEMPORAL.MODERN:
AppearanceInfo ModernAppearance = new AppearanceInfo();
ModernAppearance.SetColorPrimaryFromHex("78909c");
ModernAppearance.SetColorPrimaryDarkFromHex("546e7a");
ModernAppearance.SetColorSecundaryFromHex("00796b");
ModernAppearance.SetColorSecundaryDarkFromHex("004d40");
ModernAppearance.CustomFont = CUSTOM_FONTS_STYLE.SEGOE_UI;
LoadCustomAppearance(ModernAppearance);
break;
case APPEARANCES_TEMPORAL.CHILDREN:
AppearanceInfo ChildrenAppearance = new AppearanceInfo();
ChildrenAppearance.SetColorPrimaryFromHex("2196f3");
ChildrenAppearance.SetColorPrimaryDarkFromHex("1976d2");
ChildrenAppearance.SetColorPrimaryTextFromHex("ffea00");
ChildrenAppearance.SetColorSecundaryFromHex("4caf50");
ChildrenAppearance.SetColorSecundaryDarkFromHex("388e3c");
ChildrenAppearance.CustomFont = CUSTOM_FONTS_STYLE.BUBLE_JELLY_SHADOW;
LoadCustomAppearance(ChildrenAppearance);
break;
case APPEARANCES_TEMPORAL.CUTE:
AppearanceInfo CuteAppearance = new AppearanceInfo();
CuteAppearance.SetColorPrimaryFromHex("c2185b");
CuteAppearance.SetColorPrimaryDarkFromHex("880e4f");
CuteAppearance.SetColorSecundaryFromHex("ba68c8");
CuteAppearance.SetColorSecundaryDarkFromHex("9c27b0");
CuteAppearance.CustomFont = CUSTOM_FONTS_STYLE.SWEET_PURPLE;
LoadCustomAppearance(CuteAppearance);
break;
default:
LoadDefaultAppearance();
break;
}
}
}
}
But when I use one of this CustomTextView and want to see it rendering the layout at VS2019, I',m prompted this error:
Any ideas about it?
Regards

The error says it all. You have a NullReferenceException in your code. Set a break-point and narrow it down to where it happens.
But it looks like it happens in
AppearanceManager.TypefaceSize. It is unclear to me whatLocalResourceProvideris, but it likely requires a context to convert the dimensions, which throws a NullReferenceException.You have the debugger, set some appropriate break points and debug your code. The relevant failing code is not in your question.