I've have been trying for hours to get the custom fonts working in my MvvmCross project, specifically the Android platform. I successfully installed the component and followed the steps mentioned: https://components.xamarin.com/gettingstarted/calligraphyxamarin
It just doesn't want to work.
I tested it on a activity than inherits from Activity and AppCompatActivity they both work correctly.
Seems like inheriting from MvxAppCompatActivity breaks it? Any solutions this this problem?
I released a nuget package for this (see: MvvmCross.Calligraphy).
Just download it and modify your setup like:
public class Setup : MvxAndroidSetup
{
protected override MvxAndroidBindingBuilder CreateBindingBuilder()
{
return new CalligraphyMvxAndroidBindingBuilder();
}
}
Yes, because MvvmCross uses a custom layout inflator to bring in the bindings and some other magic stuff. This kicks out the Calligraphy inflator. Unfortunately, I didn't find a way usining the nuget package / xamarin component. You have to create a own binding and make CalligraphyFactory available.
Modified metadata.xml
<attr path="/api/package[@name='uk.co.chrisjenx.calligraphy']/class[@name='CalligraphyFactory']"
name="visibility">public</attr>
Custom factory
public class MyFactory : MvxAndroidViewFactory
{
private CalligraphyFactory _factory;
public MyFactory()
{
_factory = new Calligraphy.CalligraphyFactory(Resource.Attribute.fontPath);
}
public override View CreateView(View parent, string name, Context context, IAttributeSet attrs)
{
var view = base.CreateView(parent, name, context, attrs);
view = _factory.OnViewCreated(view, context, attrs);
return view;
}
}
Custom binding builder
class MyBindingBuilder : MvxAndroidBindingBuilder
{
protected override IMvxAndroidViewFactory CreateAndroidViewFactory()
{
return new MyFactory();
}
}
Setup.cs
public class Setup : MvxAndroidSetup
{
protected override MvxAndroidBindingBuilder CreateBindingBuilder()
{
return new MyBindingBuilder();
}
// ...
}
Activity
You don't need AttachBaseContext. Unfortunately it seems not to work with MvxAppCompatActivity, but with MvxActivity. I'm not sure what causes this issue, yet.
public class FirstView : MvxActivity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
CalligraphyConfig.InitDefault(new CalligraphyConfig.Builder()
.SetDefaultFontPath("fonts/gtw.ttf")
.SetFontAttrId(Resource.Attribute.fontPath)
.DisablePrivateFactoryInjection()
.Build());
SetContentView(Resource.Layout.FirstView);
}
}
View
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="40dp"
local:MvxBind="Text Hello"
/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="40dp"
local:MvxBind="Text Hello"
fontPath="fonts/gtw.ttf"
/>
</LinearLayout>
Result

Using Calligraphy and MvvmCross together is overkill because MvvmCross uses a custom layout inflator to bring in the bindings you can easily bind custom fonts to TextView typeface by a custom converter.
public class StringToFontConverter : MvxValueConverter<string, Typeface>
{
private static readonly Dictionary<string, Typeface> Cache = new Dictionary<string, Typeface>();
protected override Typeface Convert(string fontName, Type targetType, object parameter, CultureInfo culture) {
try {
if (!fontName.StartsWith(@"fonts/")) fontName = @"fonts/" + fontName;
if (!fontName.EndsWith(".ttf")) fontName += ".ttf";
if (!Cache.ContainsKey(fontName))
Cache[fontName] = Typeface.CreateFromAsset(Application.Context.Assets, fontName);
return Cache[fontName];
} catch {
return Typeface.Default;
}
}
}
And use it in layout:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
local:MvxBind="Typeface StringToFont('Roboto-Light')"/>
Or in styles:
<style name="CustomTextViewStyle" parent="@android:style/Widget.TextView">
<item name="MvxBind">"Typeface StringToFont('Roboto-Regular')"</item>
</style>
Calligraphy library does the same work, override layout inflate process and change TextView typeface, so it's undesirable to add next library and increase apk weight.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With