Xamarin.Forms - James Montemagno https://staging.montemagno.com/tag/xamarin-forms/ https://staging.montemagno.com/content/images/2017/08/MonogramIcon_Orange_NoBuffer.png Xamarin.Forms - James Montemagno https://staging.montemagno.com/tag/xamarin-forms/ Hugo -- gohugo.io Tue, 13 Oct 2026 20:48:55 GMT 60 Enabling Users to Manage Subscriptions on iOS/Android https://staging.montemagno.com/enabling-users-to-manage-subscriptions-on-ios-android/ 632f2485ae7288003d7930aa Sat, 24 Sep 2022 16:01:17 GMT

You know I love talking about in app purchases and subscriptions. Due to my InAppBilling library I get all the "fun" updates when Apple or Google force developers to make changes to stay compliant. Upcoming is a nice large change from Google to push Android developers to use Billing v4 (which my library does!) and another is that we must now give users a way to easily manage and cancel their subscriptions. You may have recently seen this message from google:

We’re updating our Subscriptions policy to state that users must be able to easily cancel their subscriptions from within the app. {#we%E2%80%99re-updating-our-subscriptions-policy-to-state-that-users-must-be-able-to-easily-cancel-their-subscriptions-from-within-the-app}

What does this mean? What do I need to do Google?!?!! Well if you dig through the documentation you will see that you have to add a button to your purchase screen and also create a deep link to launch the store management screen. Let's see what this looks like in code for Xamarin and .NET MAUI apps:

public async Task ManageSubscription(string sku)
{
    var url = string.Empty;
    if (DeviceInfo.Platform == DevicePlatform.iOS)
    {
        url = "https://support.apple.com/HT202039";
    }
    else if (DeviceInfo.Platform == DevicePlatform.Android)
    {
        if (string.IsNullOrWhiteSpace(sku))
        {
            url = "https://play.google.com/store/account/subscriptions";
        }
        else
        {
            url = $"https://play.google.com/store/account/subscriptions?sku={sku}&package={AppInfo.PackageName}";
        }
    }

    if (string.IsNullOrWhiteSpace(url))
        return;

    await Browser.OpenAsync(url);
}

For iOS there isn't really a requirement or even an API to give users an easy way to manage subscriptions, but I figure why not.

For Android, there are two cases here:

  1. They don't have any non-expired subscriptions and you just launch the generic page.
  2. Your user has a non-expired subscriptions for your app, where expiryTime is in the future or autoRenewing is set to true. In this case you would want to open the subscription page to the very specific subscription for them to manage.

And, that is about it... Well actually you could simplify this entire process by creating a Manage App Subscriptions page on your website and linking to that. Then your code becomes:

await Browser.OpenAsync("https://refractored.com/manage-app-subscriptions");

This should also adhere to the app store guidelines and also you can add additional information. Cheers!

Checkout my videos on YouTube

]]>
Code Generation from XAML in Visual Studio is Mind-blowing Awesome https://staging.montemagno.com/code-generation-from-xaml-in-visual-studio/ 605f72ee20df30003b2b3b83 Sat, 27 Mar 2021 18:57:22 GMT

The more and IDE or code editor can do for you the better I say. Visual Studio has been crushing it with new refactorings, IntelliSense, and IntelliCode, one of my favorite features ever. One thing that I have always been hoping for as a XAML developer is deeper connectivity between the XAML and the View-Model. We have seen increased IntelliSense in this area, but with the release of Visual Studio 2019 v16.9 comes code generation from XAML! That is right, you can now have Visual Studio automatically create your properties, commands, and more!

I will walk through this awesome feature for Xamarin.Forms, WPF, and UWP, but if you just want to see it in action, I made an entire video:

Enabling Code Generation

The first thing to do is to create your ViewModel and implement INotifyPropertyChanged (or inherit from something that does). Then just create a control with a Binding associated with it. For example:

<StackLayout>
    <Label Text="{Binding Text}"/>
</StackLayout>

Once you do this, Visual Studio will put little dots under the Text binding and a lightbulb will show up (if you don't see this simply re-compile). The lightbulb will look to assign your x:DataType in Xamarin.Forms or d:DataContext in WPF/UWP.

Lightbulb in Visual studio to set x:DataType

When I selected this option, it auto added the following code:

xmlns:app1="clr-namespace:App1"
x:DataType="app1:MyViewModel"

What is x:DataType you may be asking? Well, it is a compiled binding, which makes your bindings and apps faster! This is an awesome feature of Xamarin.Forms that you should totally use!

With this code in place, you will now see the dots remain and a new lightbulb show up to create a property called Text for you!

Lightbulb and code preview to generate text

Here, it is recommending adding the property and creating a SetProperty method to invoke PropertyChanged, which is AWESOME!!!! Now, at this point you probably want to refactor the code a little bit and create  BaseViewModel that you put this method in and then in future ViewModels it will not attempt to create the code and just add the property. If you are using Mvvm Helpers, you can use this code as your base:

public class ViewModelBase : BaseViewModel
{
	public bool SetProperty<T>(ref T field, T newValue, [CallerMemberName] string propertyName = null) =>
		SetProperty<T>(ref field, newValue, propertyName, null, null);
}

Now, if you add another control with another binding, you will see nice tight code will be generated for you:

Another property being added with only a get/set

Is your mind blown yet?!?!? Mine is! However, it gets even better!

Generating Commands!

Now, let's say we are going to add a Command to a Button we would naturally want that code to be generated as well, correct? Well, you are in luck because it will!

Command and method being created!

This code is really neat because it not only created the command and the method, but it also brought in the correct namespace to use the Xamarin.Forms Command!

Command Generation on UWP/WPF

If you are over on UWP or WPF you will not see this code generation because the core framework does not have an implementation of ICommand. However, if you are using a framework or library such as Mvvm Helpers then it will be smart enough to figure it out and recommend code for you!

Code for a command being generated with Mvvm Helpers

MIND BLOWN!!!! ARE YOU NOT IMPRESSED!?!?!? Amazing!

Cleaner Code with C# 8 & 9!

One of the things you may have noticed is that the code for Xamarin.Forms and WPF/UWP are different in the screenshots. That is because my WPF sample app is using .NET 5, which uses C# 9 by default. The Xamrin.Forms app is using .NET Standard 2.0, which defaults to C# 7. However, you can easily adjust what version of C# is used in your project by adding the LangVersion into your csproj.

<LangVersion>8.0</LangVersion>

Take a look at my previous blog about upgraded a project to C# 9 in a minute.

Once you upgrade to 8.0 or higher the old code:

private ICommand clickCommand;

public ICommand ClickCommand
{
	get
	{
		if (clickCommand == null)
		{
			clickCommand = new Command(Click);
		}

		return clickCommand;
	}
}

private void Click()
{
}

will be upgraded to this lovely clean tight code:

private ICommand clickCommand;
public ICommand ClickCommand => clickCommand ??= new Command(Click);

private void Click()
{
}

Code Generation for Models

So far we have had Visual Studio generate code in our ViewModel classes on our page, but what about our models that are bound to an ItemsSource in a ListView or CollectionView Well no worries, all you need to do is set your x:DataType on your DataTemplate:

<ListView ItemsSource="{Binding Items}">
    <ListView.ItemTemplate>
        <DataTemplate x:DataType="app1:Item">
            <ViewCell>
                <Label Text="{Binding Text}"/>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

Then you will see lightbulbs on any control inside of the DataTemplate!!

Code being generated inside of the data model

Again, this is pretty mind blowing and amazing! I was able to create all of my ViewModels and Models all without leaving the XAML!

Just the start!

This is all from me just playing around with Visual Studio 2019 v16.9 for a few minutes exploring this awesome new feature. There is for sure much more to come as Marco from the XAML Tooling team tweeted about the new feature and discussed with commentors about extending the templates for code that is being generated. Also, as of right now this is just a feature on Visual Studio on Windows, but since Visual Studio for Mac uses pretty much the same engine, we can imagine it will make its way to VSM soon.

This is just one of the many features that was included in Visual Studio 2019 v16.9 so check the release notes and upgrade today!

]]>
Building, testing, & shipping My Cadence for iOS in less than a week https://staging.montemagno.com/building-testing-shipping-my-cadence-for-ios-in-less-than-a-week/ 5fe12e796c10e100399f4eae Thu, 24 Dec 2020 17:43:57 GMT

My holiday hacking came early this year when I decided to build my own DIY spin bike. Soon, after a few rides, my mind started to swirl with app ideas of how to improve my ride. Then when Apple released Apple Fitness+ without support for displaying cadence information from sensors I knew I had to build an app. That app is My Cadence, which connects to a small cadence sensor and displays the current cadence. It is actually packed full of awesome features including custom themes, in-app purchases, store reviews, and more! Best of all it only took me around 12 hours to develop, test, and ship during the last week since I started it. So, today I want to walk through all of the features I put in and how I developed them.

Xamarin.Forms 5

With Xamarin.Forms 5 nearing stable release it was the first thing I updated to when I created the project. I leveraged a lot of new features such as embedded fonts, App Themes for Light/Dark mode, gradient brushes, geometry clipping, and a bunch more! I love how easy it is to react to the mode change on the user's device with a simple line of code.

 <Label Text="The following sensors have been tested with My Cadence."
        TextColor="{AppThemeBinding Dark=White, Light=Black}"/>

Here is a bit of the app themes in action:

Bluetooth

The cadence sensor broadcast over Bluetooth Low Energy. This was actually the first time that I had worked with Bluetooth and I leveraged the Plugin.BLE library to easily detect, connect, and read data from the device. I may upgrade to Shiny in the future, but this was the first one I grabbed and it has been working well.

I fell in love so much with Bluetooth that Frank and I recorded a full Merge Conflict podcast on it!

In-app Purchases

I decided to add a "Pro" mode into the application at the last minute. My thought was that the entire app would be free without restrictions, but to help support the app a user could upgrade to "Pro" to unlock custom theming in the app. I leveraged my InAppBilling plugin and had the upgraded implemented in about 30 minutes. Here is the code from the app if you are interested in how easy it is to implement.

const string productId = "pro";

async Task PurchasePro()
{
    if (IsBusy)
        return;

    IsBusy = true;

    try
    {
        if(Connectivity.NetworkAccess != NetworkAccess.Internet)
        {
            await DisplayAlert("No internet", "Please check internet connection and try purchase again.", "OK");
            return;
        }

        var connected = await CrossInAppBilling.Current.ConnectAsync();

        if (!connected)
        {
            await DisplayAlert("Unable to Connect", "Unable to connect to the app store, check your internet connectivity and try again.", "OK");
            return;
        }

        //check purchases
        var purchase = await CrossInAppBilling.Current.PurchaseAsync(productId, ItemType.InAppPurchase);

        if (purchase == null)
        {
            return;
        }
        else if (purchase.State == PurchaseState.Purchased)
        {
            Settings.IsPro = true;
            SetPro();
            return;
        }

        throw new InAppBillingPurchaseException(PurchaseError.GeneralError);

    }
    catch (InAppBillingPurchaseException purchaseEx)
    {
        var message = string.Empty;
        switch (purchaseEx.PurchaseError)
        {
            // figureout error message
        }

        if (string.IsNullOrWhiteSpace(message))
            return;

        Console.WriteLine("Issue connecting: " + purchaseEx);
        await DisplayAlert("Uh Oh!", message, "OK");
    }
    catch (Exception ex)
    {
        // Handle Exception
    }
    finally
    {
        await CrossInAppBilling.Current.DisconnectAsync();
        IsBusy = false;
    }
}

Store Reviews

On thing that I always forget to put in my app is a way to prompt the user to review the application. Another one of my random plugins comes in to save the day, the Store Review Plugin! In the settings screen I added a button to review the app:

void TextCellReview_Tapped(System.Object sender, System.EventArgs e)
{
    CrossStoreReview.Current.OpenStoreReviewPage("1545730360");
}

Then I also decided to do a prompt for the user to review after they use the app 5 times successfully.

var count = Settings.Usage;
count++;
if(count == 5)
{
    CrossStoreReview.Current.RequestReview(false);
}
Settings.Usage = count;

Custom Controls

I surprisingly I only used 1 custom control in the entire app and it was available directly on NuGet! This control was an advanced color picker and I landed on one built by Dalton Spillman. It is fantastic as it allows full fidelity of color selection and has a built in ViewModel that works great for getting and setting colors.

You can find the code to the control on GitHub.

Xamarin.Essentials

Wow, Xamarin.Essentials continues to make me super productive over and over and over again. I leveraged:

  • Version Tracking
  • Preferences
  • Connectivity
  • MainThread
  • and more!

Every time I thought I was going to need to write some custom code Xamarin.Essetials was there.

CI & CD

In one of my late night code sessions I decided to setup App Center Build/Distribute on the app and I am so glad I did. It took seconds to setup and I had things automatically building, versioning, and distributing to TestFlight in under 10 minutes!

App Center Build & Distribute

More!

There is a lot more that went into this application outside of just the code. I generated a full website and app screenshots from http://apptoolkit.io/, created an app icon from EasyAppIcon.com, & had some amazing tester on Twitter using TestFlight.  

Thanks Dan for Testing!
Thanks Dan for Testing!

Available Now & OSS Code Soon

It is now available in the App Store completely for free! Soon the app is coming to Android as well as I just need to tweak a few Android specific settings and get it through the review process.

If you are looking to get into spinning checkout my full blog on building a DIY spin bike.

Finally, I do plan on putting the full source code online, so be sure to check back when I write up a blog on it.

]]>
Introducing My Cadence for iOS & Android - a Simple Cadence Sensor Display https://staging.montemagno.com/introducing-my-cadence-for-ios-a-simple-cadence-sensor-display/ 5fe0dec86c10e100399f4e62 Tue, 22 Dec 2020 17:30:00 GMT

It has been nearly 3 weeks since I put together my DIY spin bike and I have now clocked in over 25 rides! Let's just say I am really enjoying have the bike at home now that it is chilly and more rainy outside. Last week I wrote a blog on my experience and did a full Apple Fitness+ review video, in which I mentioned one of the issues I had was the lack of Cadence sensor integration into the app. Knowing your cadence is really important during a ride because it is your RPM that you are spinning the pedals. A number is often called out during rides and you are set to match it. The Peloton digital app has the ability to connect to a sensor such as the Wahoo or moofit, but Apple Fitness+ does not. So like I always do I set out to fix this problem and build a mobile app! Today, I am proud to introduce My Cadence for iOS & Android available for free on the App Store and Google Play.

My Cadence for iOS

The application works by connecting to to any sensor that is broadcasting the Cadence & Speed Bluetooth service. This includes Wahoo, moofit, and other sensors that are popular for indoor cycling bikes. In addition the app fully supports light and dark mode, adjustable font sizes, and is completely free with no time restrictions at all. Here is a quick look at how the app works with me setting it up on my spin bike.

The app is completely free, but I also introduced a Pro mode for $2.99 that helps support independent development and unlocked custom theme colors :)

Selecting custom colors in the app

You can grab the app on the App Store and Google Play today. I will have another blog and video on my YouTube explaining how I built the app soon.

]]>
5 Must Install NuGet Packages for New Xamarin Projects https://staging.montemagno.com/essentials-nugets-for-new-xamarin-projects/ 5fc80a2879e5440039355a25 Wed, 09 Dec 2020 16:52:18 GMT

Starting your first project can be a bit overwhelming. I mean heck, I wrote nearly 3,000 words breaking down every bit of what to select and what each option means. Oh, and I also have a full video series walking you through it step by step on my YouTube channel. Before I start writing code in my projects I take some time to configure my projects and then install essential NuGet packages that help me be super productive from the start.

Yes, it is true that Xamarin.Forms and Xamarin.Essentials are included "in the box" with your new project, but there is a world of amazing libraries out there from amazing community members. I want to introduce you to my favorite packages that are key in ever app that I have developed. So, let's get started.

MVVM Helpers 🎉

I may be a bit bias with these first 2 NuGet packages because I wrote them, but I think they are super essentials. First is MVVM Helpers (Refractored.MvvmHelpers), a super small library that works in any app that contains nifty classes and utilities that help creating your app from the start. It includes things such as:

  • ObservableObject: A Simple implementation of INotifyPropertyChagned
  • BaseViewModel: The only base view model you will ever need. It implements INotifyPropertyChanged and a bunch of default properties such as Title, SubTitle, Icon, IsBusy, IsNotBusy, CanLoadMore.
  • ObservableRangeCollection: Best way to group items into a Key/Value pair ObservableCollection for managing groups of data.
  • AsyncCommand: An async version of ICommand!

So, now you can just start your project and write code like this:

public class MonkeyViewModel : BaseViewModel
{
	public MonkeyViewModel()
    {
    	Title = "Monkeys";
    }

    public ObservableRangeCollection<Monkey> Monkeys { get; } = new ();

    AsyncCommand doStuffCommand;
    public AsyncCommand DoStuffCommand => doStuffCommand ??= new AsyncCommand(AsyncMethod);

    string name;
    public string Name
    {
    	get => name;
        set => SetProperty(ref name, value);
    }

    public Task AsyncMethod()
    {
    	return Task.CompletedTask
    }
}

Monkey Cache 🐵

This nice little caching library enables you to easily store data objects for set amount of times. For example you may want to cache web results for a few minutes. It integrates directly with the file system, SQLite, or LiteDB so you can write code like this:

public async Task<T> GetAsync<T>(string url, int minutes = 3)
{
    var json = string.Empty;

    if (!Barrel.Current.IsExpired(url))
    {
    	json = Barrel.Current.Get<string>(url);
    }
    else
    {
        json = await client.GetStringAsync(url);
        Barrel.Current.Add(url, json, TimeSpan.FromMinutes(minutes));
    }

    return JsonConvert.DeserializeObject<T>(json);
}

Wow, data caching in 3 lines of code! :)

PancakeView 🥞

My apps can not live without the PancakeView NuGet from Steven Thewissen. It gives your apps a breadth of new life with beautiful gradients, cards, custom rounded corners, and so much more. I mean look at this beautiful thing:

Sharpnado 🦈🌪

Alright, technically Sharpnado is a bunch of smaller libraries, but you get to pick and choose because there is so much awesome from Jean-Marie Alfonsi.

First is Sharpnado.Tabs... fully customizable Tabs that you can put anywhere!

Then there is Sharpnado.Shadows, because you know you need to add lovely shadows to all of your views.

That is just the start as there is a plethora more available including the TaskLoaderView, HorizontalListView, and MaterialFrame. You need these libraries!

Xamarin Community Toolkit 🧰

I am really jazzed about this initiative because it is an official package from the Xamarin team, but a deep collaboration with the community. This toolkit is a collection of controls, Animations, Behaviors, Converters, and Effects for mobile development with Xamarin.Forms. It simplifies and demonstrates common developer tasks building iOS, Android, and UWP apps with Xamarin.Forms. The NuGet is still in pre-release phase for testing, but is packed full of amazing functionality including:

  • Toast
  • Snackbar
  • AvatarView
  • MVVM Helpers (awesome stuff from my library)
  • C# Markup Extensions
  • Tons more!

Even More NuGets

These are just a few of my recommended NuGet packages that you should totally check out. There are a lot more awesome community libraries out there that you should checkout and I have a curated list on my GitHub!

]]>
Introducing Island Tracker for Animal Crossing New Horizons https://staging.montemagno.com/introducing-island-tracker-for-animal-crossing-new-horizons/ 5eb04dd46c478d00392fb981 Sat, 09 May 2020 17:25:00 GMT

tldr; I built a new iOS & Android app called Island Tracker that enables you to track turnip prices, get predictions, and share them with friends. It is available today.

Get it on: download-on-app-store download-on-google-play

When Animal Crossing New Horizons launched in late March I fell in love immediately. My wife adopted my Nintendo Switch Lite and we both got copies the night of release. Over on the Nintendo Dispatch podcast, we call it the perfect game at the perfect time. It truly has been for us during this time of staying inside away from all of our closest friends. Each day we dig up fossils, shake trees, give gifts to neighbors, visit islands and collect things for our museum.

However, something is different each Sunday morning at our house. We wake up and race to our Switch to see what price we can buy bundles and bundles of turnips. Then throughout the week we are constantly bugging our friends to see what we can sell them for, in hopes that someone has a huge spike and we can make a mad profit. After a week of text message madness, my must solve everything with a mobile app mind went to work and Island Tracker was born.

Island Tracker enables you to easily track your turnip purchases on Sunday and then track your prices throughout the week. You can easily get predictions, see if you are up or down, and then share your prices with all of your friends with a click of the button! Through weeks of beta testing with Animal Crossing die hards, I have even added some really cool features such as sharing your Switch Friend Code and nifty calculators to make buying turnips a breeze. After weeks of development, architecting, testing, and getting ready for release, Island Tracker is available right now on Google Play for Android and the Apple App Store for iOS for $2.99. Need some convincing? Here is a full walk through:

The Tech Behind Island Tracker

As you would expect the entire application is completely open source and available on GitHub. The application shares around 98% shared source code between iOS & Android, leveraging Xamarin.Forms for the user interface and C# business logic. There are tons of great libraries that I leveraged to build the app including PancakeView, Sharpnado, Syncfusion, MvvmHelpers, Monkey Cache, App Center, Xamarin.Essentials, and Resizetizer.NT.

For the backend system I leveraged Azure Functions combined with Azure Table Storage. With just a few Tables I was able to achieve some really cool functionality with a full friends system, encryption, and no-signup users.

If you are interested in how it all works checkout this YouTube video I shot on the entire process.

A Huge Thanks

There is an amazing Xamarin community making awesome libraries that really helped me be productive throughout the process. I built a lot of the app live on my Twitch stream and got tons of great feedback and help. Then there is the hard work of Mike Bryant and Steve aka sparkie108 who ported tons of the predictions code to JavaScript and then to  C# to use in the app, which is awesome! Finally, thanks to all of my awesome beta testers that gave me feedback all throughout the last month really making the app spectacular.

What's Next

Well, it is out! I am super proud of this app and hope that people enjoy it and make tons of bells in Animal Crossing! I will continue to improve the app, add new features, and make it the best Animal Crossing app that I can! Cheers <3

Get it today: download-on-app-store download-on-google-play

]]>
Animate Anything with Xamarin.Forms https://staging.montemagno.com/animate-anything-with-xamarin-forms/ 5eb04d596c478d00392fb97c Tue, 05 May 2020 17:41:37 GMT

I have been building apps with Xamarin.Forms for nearly 6 years now! I love how it has evolved over the years, added new controls, new features, and simplified everything with Shell. While I think I can build pretty decent apps in general, one thing that I have  always struggled with is animations. The very first release of Xamarin.Forms had a built in animation system to fade, move, and scale any of the controls. These are great and there have been several videos on how to use these:

One thing that I always wanted.... was more control! On my Twitch stream a few weeks ago I was trying to spin a little icon that looped when I was submitting a friend request and it was brought to my attention that there is a full animation system built in to do just about anything you want.

To accomplish this, it requires a bit of code in the code behind using the Animation class.

readonly Animation rotation;

public SubmitFriendRequestPage()
{
    //..
    rotation = new Animation(v => LabelRotateIcon.Rotation = v, 0, 360);

    VM.PropertyChanged += OnPropertyChanged;
}

Here we create a new custom Animation. It takes in a a callback to set any properties to a value that will be increased over time. The next two parameters are the start and stop values. So here I am saying start playing the animation with the rotation starting at 0 and then stop when you reach 360.

Next, comes time to play the animation, which I do when my IsBusy property changes. The Animation class allows you to name and check an animation at any time, which is very nifty.

void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    if(e.PropertyName == nameof(VM.IsBusy))
    {
        if (!VM.IsBusy)
            this.AbortAnimation("rotate");
        else
            rotation.Commit(this, "rotate", 16, 1000, Easing.Linear, (v, c) => 			LabelRotateIcon.Rotation = 0, () => true);
    }
}

So, a few things happening here. First is AbortAnimation, which says hey if you are running "rotate" animation stop it. Next is Commit of the animation which will start it. Here I am saying the owner of the animation is the page, the name is "rotate", update very 16 milliseconds, run for 1000 milliseconds, and do linear easing on it. Now, the last two are functions, which are nice touches. The first is what to do when you finish (reset to 0) and then the last function is if you want to loop the animation!

That's it! Literally 3 lines of code to create, start, and stop the custom animation. For some reason I never knew this existed even though there have been a bunch of really cool libraries built on top of is such as Xamanimation.

To learn more about custom animations checkout the full documentation!

]]>
Xamarin.Forms Custom Fonts Simplified & Everywhere https://staging.montemagno.com/xamarin-forms-custom-fonts-everywhere/ 5eade503e04bb2003806f8da Sat, 02 May 2020 21:56:10 GMT It was just about 1 year ago when I wrote about using font icons for images inside of Xamarin.Forms apps. Well time has flown by and now more than ever is the time to go all in on custom fonts and font icons because with Xamarin.Forms 4.6 everything got so much easier!

Custom fonts in Xamarin.Forms Shell
Custom fonts in Xamarin.Forms Shell

See my full walkthrough:

So, let's start off with the basics when it comes to fonts. You usually think about fonts as just a fancy way to display text. However, with resources such as Font Awesome you can use fonts as icons instead of images. Font Awesome provides a plethora of free font icons and the actual files are small at about 400KB for all 3 free that you can download from this link here. You can put them in Tabs, Labels, and Images, and they are awesome!

Previously there was a lot of setup required, but with Xamarin.Forms 4.6 embedded fonts you can now drag them into your .NET Standard project in Visual Studio and mark them as an EmbeddedResource:

Add fonts and mark as EmbeddedResource
Add fonts and mark as EmbeddedResource

Then all you need to do is head over to your AssemblyInfo.cs or App.xaml.cs and add this new fancy export code. You can even give the font an Alias to easily identify it later.

[assembly: ExportFont("CustomFont.ttf", Alias = "AnimalCrossing")]
[assembly: ExportFont("fa-regular-400.ttf", Alias = "FA-R")]
[assembly: ExportFont("fa-solid-900.ttf", Alias = "FA-S")]
[assembly: ExportFont("fa-brands-400.ttf", Alias = "FA-B")]

When you head over to the font awesome website each icon will have a specific unicode associated with it:

Coffee icon from font awesome with unicode f0f4
Coffee icon from font awesome with unicode f0f4

We can now put these in our Application Resources that we can call on later:

<x:String x:Key="IconCoffee">&#xf0f4;</x:String>

Now, we can use it in our fancy Shell Tabs (or Image) like you saw earlier using FontImageSource:

 <Tab Title="Profile" Route="profile">
     <Tab.Icon>
     	<FontImageSource Glyph="{StaticResource IconCoffee}" FontFamily="FA-S" />
     </Tab.Icon>
 	<ShellContent ContentTemplate="{DataTemplate view:ProfilePage}"/>
 </Tab>

We can also use them in a Label:

<Label
    FontFamily="FA-S"
    Style="{StaticResource SocialLabel}"
    Text="{StaticResource IconCoffee}" />
Custom fonts as labels!
Custom fonts as labels!

If you are referencing your Icons from C# you can generate a full schema from the font by using this awesome site IconFont2Code. Or if you want a pre-generated on checkout Matthew Robin's GitHub fa2cs project that has a pre-made file to do this. Once you add the file you can then have access to every icon!

You can use an icon in XAML by:

  • Adding a namespace reference to FontAwesome: xmlns:fontAwesome="clr-namespace:FontAwesome";
  • Referencing a icon using x:Static: <Label Text="{x:Static fontAwesome:FontAwesomeIcons.Alicorn}"/>
  • or in code submitButton.Text = FontAwesome.FontAwesomeIcons.Check;

Now, go off and use those custom fonts! Want more, read through the docs.

]]>
Setting Android Status Bar Background & Icon Colors https://staging.montemagno.com/setting-android-status-bar-background-icon-colors/ 5dd3091684e2c7003870dfcf Thu, 05 Dec 2019 20:15:00 GMT Over the past few months, I have been attempting to figure out the best ways to implement a light theme and dark theme in my Hanselman.Forms app. Working closely with my friend Kym Phillpotts we came up with a very nice theme changer for Xamarin.Forms, that allowed us to change all of the colors dynamically. The result is a very nice looking application that allows the users to pick their theme or use system defaults.

Picking themes in Hanselman.Forms between light and dark theme

One thing that bugged me in the original implementation for Android, was the status bar color that was a single dark blue color. Modern apps will set the status bar to match the background color when toggling between light and dark. Since we are allowing the user to set the theme, we must also set the color of the status bar.

This can be accomplished with the following code:

public void SetStatusBarColor(System.Drawing.Color color, bool darkStatusBarTint)
{
    if (Build.VERSION.SdkInt < Android.OS.BuildVersionCodes.Lollipop)
        return;

    var activity = Plugin.CurrentActivity.CrossCurrentActivity.Current.Activity;
    var window = activity.Window;
    window.AddFlags(Android.Views.WindowManagerFlags.DrawsSystemBarBackgrounds);
    window.ClearFlags(Android.Views.WindowManagerFlags.TranslucentStatus);
    window.SetStatusBarColor(color.ToPlatformColor());
}

This uses my Current Activity Plugin to get the Window of the app, and also Xamarin.Essentials Color Converters to set the color to light or dark.

Screenshot of the status bar in dark theme with matching color

This works really great unless I set it to a light color where the icon colors remain white.

Screenshot of the status bar in light them where icons are white too

We can also control this with the following code:

if(Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.M)
{
    var flag = (Android.Views.StatusBarVisibility)Android.Views.SystemUiFlags.LightStatusBar;
    window.DecorView.SystemUiVisibility = darkStatusBarTint ? flag : 0;
}

Now it looks beautiful, and we are in full control!

Screenshot of the status bar in light them where icons are dark color

Get the code

All of the source code for Hanselman.Forms can be found on GitHub and you can watch me code live on Twitch. I also archive all the videos on my YouTube channel.

]]>
Investing Time in the Xamarin Linker for Smaller App Sizes https://staging.montemagno.com/investing-time-in-the-xamarin-linker-for-smaller-app-sizes/ 5dd314f084e2c7003870dfd4 Mon, 02 Dec 2019 19:00:00 GMT When developing an app, 99% of our time goes into writing the code, testing the functionality, and making small UI tweaks to please our end users. Most of this is done in debug mode which optimizes compilation and app size for speed, which makes sense. When we flip that flag to Release with the default settings, we often pay very little attention as to what is happening to our app. We get a nice APK or IPA and ship it up to the app store and we are done. However, if we just spent a little time fine tuning our settings, we could really reduce the overall app size. I recently sat down for 1 hour and reduced Hanselman.Forms by 4 MB on Android by optimizing the linker in Full Link mode. When I flipped on Startup Tracing for comparison the app size was reduced by 10MB!

App Before and After Optimizing the Linker

I have written many times about using & understanding the linker, however today I want to talk about how to debug the linker.

My recommendation is to flip on Link "Sdk & User Assemblies" and run your application. See if everything works or if your application crashes. Most likely, it will crash and you will see an error such as:

Getting: System.InvalidOperationException: 'A suitable constructor for type 'Shiny.Jobs.JobManager' could not be located. Ensure the type is concrete and services are registered for all parameters of a public constructor.'

If you see this, it means it is time to debug through.

Debug the Linker

You should NEVER have the linker on when debugging an app.... unless you are debugging the linker settings! So, turn on that linker in debug and see what happens. Like I said above, you will probably see a crash with the linker stripping away too much. That is usually because of reflection or the main project not referencing items from your .NET Standard project. Hopefully library creators have optimized their libraries to handle the linker, however if they haven't you can easily setup assembly skipping in your csproj file. Here is what it looks like to completely skip over Xamarin.Forms:

// iOS
 <MtouchExtraArgs>--linkskip=Xamarin.Forms.Platform.iOS --linkskip=Xamarin.Forms.Platform --linkskip=Xamarin.Forms.Core --linkskip=Xamarin.Forms.Xaml --linkskip=Samples</MtouchExtraArgs>

// Android
<AndroidLinkSkip>Xamarin.Forms.Platform.Android;Xamarin.Forms.Platform;Xamarin.Forms.Core;Xamarin.Forms.Xaml;FormsViewGroup;</AndroidLinkSkip>

We can easily add assemblies into this list until the app runs. Here is what Hanselman.Forms looks like:

<AndroidLinkSkip>Xamarin.Forms.Platform.Android;Xamarin.Forms.Platform;Xamarin.Forms.Core;Xamarin.Forms.Xaml;FormsViewGroup;Shiny.Core;MediaManager;MediaManager.Forms;</AndroidLinkSkip>

Don't Skip, Inform the Linker

Have you ever wondered why you have all this those Init calls in your app's startup?

Forms.SetFlags("CarouselView_Experimental");
Forms.Init(this, bundle);
FormsMaterial.Init(this, bundle);
Xamarin.Essentials.Platform.Init(this, bundle);
CrossMediaManager.Current.Init(this);
ImageCircleRenderer.Init();
Android.Glide.Forms.Init(this);

This is to help the linker become aware that you are using this library, so don't remove it. If a library doesn't have an Init, you can easily inform the linker you are using a class that is getting linked out like this:

var pancake = typeof(PancakeView);
var circle = new CircleImage();

Depending on how complex the dependency is then you may want to link skip assemblies out since we don't have access to the source code.

Custom Preserve Flags

If you are getting exceptions in classes that are in your own code then you can add a special attribute to the class to tell the linker to preserve it.

In your shared code (usually .NET Standard) add a new file called PreserveAttribute:

public sealed class PreserveAttribute : System.Attribute
{
    public bool AllMembers;
    public bool Conditional;
}

Now, on any class that is getting stripped out add the following attribute:

[Preserve(AllMembers = true)]
public partial class Tweet
{
}

Keep doing this until your code is linker safe and everything is working as expected. In no time at all you will have your app ready to be fully linker optimized and the app size will be reduced :)

Cleanup Before Committing Code

When debugging linker issues, I like to have the same settings mirrored acrossed debug and release. However, leaving these settings on in debug will slow down your builds and will turn off XAML Hot Reload. So, NEVER turn on linking in debug unless you are doing this.

Read More

Now that you have an idea of how to debug and customize yoru code for the linker be sure to read the in-depth documentation for even more goodies. I would also read the following blogs on shrinking your app size, optimizing Android builds, and faster startup times with startup tracing.

]]>
Azure DevOps Settings for Xamarin iOS 13 and Android 10 Apps https://staging.montemagno.com/azure-devops-settings-for-xamarin-ios-13-and-android-10-apps/ 5dd43e2784e2c7003870dfe2 Wed, 20 Nov 2019 20:12:00 GMT

Settings up continuous integration can be tricky when there are new versions coming out. Recently Visual Studio 2019 updated to support Xcode 11, iOS 13, Android 10, .NET Core 3, and C# 8. What a whirlwind of new updates that CI servers got all around the same time! This means that as you were updating your apps your hosted machines also got updated and probably broke your builds :(. My good friend Jonathan Peppers wrote an amazing tool called Boots that allows you to manually install dependencies and previews of Xamarin and Mono.

Boots task in Azure DevOps installing Mono 6.4.0

This is great, but it also means that your build takes a little bit longer to manually install items. Did you know that Azure DevOps has all of the latest bits installed on their hosted agents and even have simple scripts enabling you to decide what version of Xamarin and Mono to run? Here is what you need to know to build your apps in Azure DevOps with C# 8, iOS 13, and Android 10.

Use macOS 10.14

Be sure that you select the latest version of macOS to build your iOS and Android apps on. You can simply specify macOS-latest or macOS-10.14 in your Pipeline settings.

macOS-version selection in Azure DevOps

You can find what software is installed here.

Install .NET Core

This may sound funny to install .NET Core for a Xamarin build, but the latest reference assemblies and build system require it. You can find what version of .NET Core is compatible with Visual Studio for Mac on the docs site.

You can add the Use .NET Core task to install .NET Core 2.2.x or 3.0.x. Either work just fine.

.NET-Core version task in Azure DevOps

Set Xamarin & Mono Version

This next task is very important as it will tell the build agent what version of Xamarin and Mono to use when compiling the app. I like to define a variable with the version number in the format Major_Minor_Revision. For the latest we will use 6_4_0:

Variable in Azure DevOps specifying Mono 6.4.0

Then we will add a task to run a bash script to set the version of Xamarin. This is done with the following inline script:

sudo $AGENT_HOMEDIRECTORY/scripts/select-xamarin-sdk.sh $(MonoVersion)

Bash script setting the version of Xamarin to use

That is it! Now you are good to go to build your apps with C# 8, iOS 13, and Android 10!

More DevOps!

Looking for more DevOps? Checkout my Channel 9 series on DevOps for Mobile Developers where I walk you through everything you need to know about DevOps with my friend Abel.

]]>
Opt-out of Dark Mode on iOS, Android, UWP, and macOS https://staging.montemagno.com/opt-out-of-dark-mode-on-ios-android-uwp-and-macos/ 5da372290980fc00385d9b78 Mon, 14 Oct 2019 19:17:00 GMT Everyone can't stop talking about dark mode now that iOS 13 and Android 10 are officially released. To my surprise I have actually really been enjoying dark mode on my desktop and mobile devices. I really want to go through all my apps and add proper dark mode support, however I just haven't had the time. When running apps on iOS 13 or macOS and flipping on dark mode can make your app look.... not so great:

image_from_ios

This can depend on the framework you are using, hard coded values, or a bunch of other things. You may be in this situation or perhaps you have a completely custom theme and you don't want the operating system to touch it. Well, you are in luck because you can opt-out!

iOS

You have two options here. The easiest is to update your Info.plist and add a new entry named UIUserInterfaceStyle. You can manually set this to Light or Dark to apply a theme to your entire app.

<key>UIUserInterfaceStyle</key>
<string>Light</string>

If your app is basically ready to go and just a few screens require a specific mode you can set the OverrideUserInterfaceStyle propety. This can be done on any UIView, UIViewController, or UIWindow.

public override void ViewDidLoad()
{
    base.ViewDidLoad();
    if (UIDevice.CurrentDevice.CheckSystemVersion(13, 0))
        OverrideUserInterfaceStyle = UIUserInterfaceStyle.Light;
}

macOS

Similar to iOS you can add a very special key to your Info.plist called NSRequiresAquaSystemAppearance and set it to true:

<key>NSRequiresAquaSystemAppearance</key>
<true/>

Android

Android is actually really easy as you have to opt-in for the dark mode to apply to your application. Traditionally, you have always set a light or dark mode for your app in your app's styles. Every Xamarin app defaults to a light theme:

<style name="MainTheme.Base" parent="Theme.AppCompat.Light.DarkActionBar">

You have to opt in by setting the theme to DayNight:

<style name="MainTheme.Base" parent="Theme.AppCompat.DayNight.DarkActionBar">

This also works if you are using MaterialComponents theming:

<style name="MainTheme.Base" parent="Theme.MaterialComponents.DayNight">

UWP

UWP is also similar to Android as you have to opt-in for the system wide defaults. Traditionally in your App.xaml file you would set a requested theme:

<Application
    RequestedTheme="Light">

</Application>

This means your app will always use light theme no matter what. To opt-in you will need to remove this property completely.

Checking Requested Theme

It is actually pretty simple to check theme of the app. It has been blogged abotu a lot, and I have even submitted a pull request to Xamarin.Essentials that hightlights it, so take a look. There are also great docs for iOS, Android, and UWP to help guide you.

]]>
Xamarin.Forms Design Time Data Tips & Best Practices https://staging.montemagno.com/xamarin-forms-design-time-data-tips-best-practices/ 5d9f5e420980fc00385d9b6a Thu, 10 Oct 2019 21:15:00 GMT

One of my favorite features of building applications with XAML is the ability to use design time data to preview it inside the IDE. Recently in Xamarin.Forms 4.0 the team introduced an official pattern to specify design time properties, controls, or just about anything else. It is a really neat feature that I have been using on my live streams and in my apps. There is some really great docs that you should read through, but I will repeat the core info here.

DesignTime

Why Design Time Data?

Xamarin.Forms XAML Hot Reload is the future ( available today in VS 16.3 and VSM 8.3) for rapid iteration and productivity with XAML, I still sometimes find myself working on new screens or wanting to get a mockup of my UI without having to run my app. Also, sometimes you don't have your ViewModel setup yet and you just want to start building a screen. That is where design time data comes in, allowing you to preview your data without having to run your app. So, let's get started.

Getting Started

The Xamarin.Forms leveraged the basic building blocks of design time data from WPF/UWP and added a few name spaces that you can import into your XAML to start using it.

xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"

If you create a new project or page this will already be included and may even have some design time data already in there. These three lines of code setup the ability to start using design time data with the magical d character. You can of course change this, but d: is a nice and simple. That's it, you are ready to go!

Simple Properties

The previewer will automatically pick up any property that you set, however if you are using data binding then it will not be able to display anything.

<Label Margin="10"
       Text="{Binding MonkeyCount, StringFormat='{0} Monkeys'}"/>

DesignTime1

To get design time data showing up we can simply add d: to a new Text property and assign the value.

<Label Margin="10"
       Text="{Binding MonkeyCount, StringFormat='{0} Monkeys'}"
       d:Text="3 Monkeys"/>

DesignTime2

What is really great is that you can actually set ANY property! This is very nifty when you are trying to figure out spacing and sizing. I love to set the BackgroundColor all the time, but now, I can use design time data to see it only in the previewer.

<Label Margin="10"
       Text="{Binding MonkeyCount, StringFormat='{0} Monkeys'}"
       d:Text="3 Monkeys"
       d:BackgroundColor="Orange"/>

DesignTime3

One of my favorite things to do is to see my ActivityIndicator in the previewer by setting d:IsRunning="True":

<ActivityIndicator
    Grid.RowSpan="2"
    IsVisible="{Binding IsBusy}"
    IsRunning="{Binding IsBusy}"
    d:IsRunning="True"
    HorizontalOptions="Center"
    VerticalOptions="Center"/>

Activity

Lists of Data

One really cool thing about using design time data is that you can also specify an Array of data. This means that you can easily specify a design time ItemsSource on your ListView, CollectionView, CarouselView, etc. This is really great when we want to work on our cells, but don't have the data yet.

<d:ListView.ItemsSource>
    <x:Array Type="{x:Type x:String}">
        <x:String>Item One</x:String>
        <x:String>Item Two</x:String>
        <x:String>Item Three</x:String>
    </x:Array>
</d:ListView.ItemsSource>

Then you can use d: on any property on the cell, or you can use `{Binding .} to bind to the string that you have specified:

<ListView.ItemTemplate>
    <DataTemplate x:DataType="models:Monkey">
        <ImageCell Text="{Binding .}"
                   Detail="{Binding Location}"
                   d:Detail="Location"
                   ImageSource="{Binding Image}"
                   d:ImageSource="icon.png"/>
    </DataTemplate>
</ListView.ItemTemplate>

DesignTIme4

Lists of Model Data

Lucky for us, we can also use our real data model, which means our bindings will actually work! You just need to make sure that your properties you want to use have a public get and set.

<d:ListView.ItemsSource>
    <x:Array Type="{x:Type models:Monkey}">
        <models:Monkey Name="Baboon" Location="Africa and Asia"/>
        <models:Monkey Name="Capuchin Monkey" Location="Central and South America"/>
        <models:Monkey Name="Blue Monkey" Location="Central and East Africa"/>
    </x:Array>
</d:ListView.ItemsSource>
<ListView.ItemTemplate>
    <DataTemplate x:DataType="models:Monkey">
        <ImageCell Text="{Binding Name}"
                   Detail="{Binding Location}"
                   ImageSource="{Binding Image}"
                   d:ImageSource="icon.png"/>
    </DataTemplate>
</ListView.ItemTemplate>

DesignTIme5

Notice that I am still using d:ImageSource because the previewer wont go and download images from the internet. This icon.png is just in my drawable/resource folder and it will be displayed.

Important: You need to re-compile your libraries/app when you make changes to a model or ViewModel so the previewer can re-load it.

ViewModels, IntelliSense, & XAML Hot Reload

Alright, now for what you have been waiting for... ViewModels! A long time ago, I wrote a blog on how to use design time data ViewModels with the previewer. Many developers may be binding their ViewModel directly in their XAML. If you are using XAML Hot Reload then you may have noticed that everytime you reload that your ViewModel gets re-created! My recommendation would be to set your BindingContext in your page constructor:

public MonkeysPage()
{
    InitializeComponent();
    BindingContext = new MonkeysViewModel();
}

Now, the issue here is that you will no longer get IntelliSense in your XAML because the XAML doesn't know about your BindingContext! Don't worry, design time data to the rescue!

<d:ContentPage.BindingContext>
    <viewmodels:MonkeysViewModel/>
</d:ContentPage.BindingContext>

Now your IntelliSense will work again!

IntelliSense

Running ViewModel Logic

Now, you may be saying.. James, but I already have mock ViewModels that are ready to be consumed in my XAML & the previewer. Well, don't worry because while the previewer no longer runs your page's code behind, it will still execute the constructor of your ViewModel! This means you could set your d:ContentPage.BindingContext to the mock ViewModel, or if you need to pass parameters to the constructor to setup mock data, you can do that to.

So, let's say you have something like this for your ViewModel:

public MonkeysViewModel(bool designData)
{
    if (designData)
    {
        Monkeys = MonkeyHelper.Monkeys;
        MonkeysGrouped = MonkeyHelper.MonkeysGrouped;
    }
    else
    {
        //Setup web requests and such
    }
}

We can setup the design time ViewModel in XAML and then remove ALL of the d: bindings that we were using:

<d:ContentPage.BindingContext>
    <viewmodels:MonkeysViewModel IsBusy="True">
        <x:Arguments>
            <x:Boolean>true</x:Boolean>
        </x:Arguments>
    </viewmodels:MonkeysViewModel>
</d:ContentPage.BindingContext>

Final

Future of Design Time Data

Design time data today is pretty cool and works well with the updates to the previewer that the team made to make it more stable. My hope for design time data is that the team opens up the API and actually allows you to use design time data at runtime! That is right! At runtime! I think that this would be super cool and I even opened a GitHub issue that you should go +1 on.

Get the code

As always, you can grab the code on GitHub for the monkeys app and give it a go.

This post is part of the Xamarin October Best Practice Challenge. Checkout the GitHub page for more great posts!

]]>
Free C# and Xamarin for Beginners Videos Series https://staging.montemagno.com/announcing-free-xamarin-and-c-sharp-for-beginners-videos-series/ 5d97809d0980fc00385d9b5a Fri, 04 Oct 2019 22:00:00 GMT

Last week Hanselman announced all of the great new videos that are available at dot.net/videos. However, he forgot to mention that there is an entire new getting started series for iOS & Android development with Xamarin! The lovely developer advocate's and friends Matt Soucoup and Brandon Minnick just released the 11 part series! If you are new to C# then don't worry as there is a full C# 101 series.

It has never beena better time to get started learning C# and building mobile apps with Xamarin.

GetSTarted-1

The entire series is available on YouTube and Channel 9. And walks you through:

  • What is Xamarin?
  • Installing Xamarin
  • Xamarin Solution Architecture
  • Xamarin.Forms UI with XAML (and with C#)
  • MVVM
  • Navigation
  • Full Recap!

Series

So much more C# .NET!

There are also tons of amazing series available for all things .NET including:

There is SO MUCH GOOD STUFF! Now go off and learn!

]]>
James on Tour - October 2019 Europe Edition! https://staging.montemagno.com/james-on-tour-october-2019-europe-edition/ 5d94e96ce9addb0038c60615 Wed, 02 Oct 2019 18:43:46 GMT

I can't believe it is October already! What an amazing year with so many amazing announcements for Xamarin developers. Between Build, Xamarin Developer Summit, and .NET Conf there truly has been something for everyone. Now, I want to take this Xamarin goodness on the road for a two week Europe roadshow! I worked closely with user group leaders all over Europe to set up a great schedule where I am literally traveling just about every day!

Oct 22nd - 23rd - DevReach - Sofia, Bulgaria

To kick things off, the fine folks over at Telerik invited me to keynote DevReach! On Tuesday I will be giving my ".NET Everywhere" keynote and a follow up session on Wednesday on "What's new for Xamarin developers".

sofia

Oct 24th - VISUG - Mechelen, Belgium

The Belgian Visual Studio and App Dev User Groups have combined forces to host me for my "What's new, hot, and awesome for Xamarin Developers!"

Oct 25th - Xamarin Expert Day - Cologne, Germany

This one day Xamarin conference is PACKED with amazing speakers including Luce, Jean-Marie, Sandra, Tomasz, and so many more! I will be doing a full general session of awesome!

expertday

Oct 26th - Oxford.NET - Oxford, UK

Since I have a free weekend on the road I decided to do a talk out in the UK! I have partnered up with the Oxford .NET user group to do an introductory Xamarin session for .NET developers.

Oct 28th - Dutch Mobile .NET - Hilversum, Netherlands

I am heading back to the Netherlands for a special talk on all of the hot and awesome things coming for Xamarin developers! Who knows what I will be rambling on about on my 6th talk in a week!

dutch

Oct 29th - Coding After Work - Stockholm, Sweden

To cap things off I am heading to Sweden for the first time to present! I can't wait to bring all the latest Xamarin goodness!

Don't forget you can always keep up to date where I am on my Speaking page.

]]>