Search code examples
c#iosxamarin.formsxamarin.iosios-extensions

How to utilize Xamarin Forms Global Styles in iOS Extension


I've got a theme switcher in my Xamarin Forms app that works great using a set of static Resource files. However, my app also has an iOS extension and the theming breaks down at that point.

In the main application, I am assigning the theme to the current application's Resources property (ie. Global Styles) and all views utilize the resources and automatically change when the theme changes. Something like so:

Application.Current.Resources = new MyThemes.Default();

In the extension however, there is no "Application" as pages are just added directly to the root UIViewController. Because of that, I can't use Application.Current, which is always null. The pages work fine, but no theme is applied. I can use the themes if I manually assign them to each page as I create them, though it doesn't act like Global Styles and cascade down to child pages. In other words, something like this:

var myPage = new ContentPage();
myPage.Resources = new MyThemes.Default();
viewController = myPage.CreateViewController();

This works, but it's not perfect and would require me to rewrite portions of shared views that currently are styled automatically by the Global Styles.

I've been digging around trying to find a clue to implement this proper, but haven't had any luck and feel like I'm missing something. Everything I've found only seems to talk about themes from a core application point and not extensions.

Are there documentation or examples on using Theme Resources and Global Styles in a Xamarin Forms iOS Extensions? Any help is appreciated, thanks!

Edit: It's also worth noting that references to Application.Current in custom renderers cause silent crashes when the custom renderer is loaded as an extension. This can be fixed by using a BindableProperty instead.


Solution

  • After spending some time looking into this, I've found two possible solutions.

    Simply set the Resources for the child pages on creation using a helper class to fetch the current theme. Something like:

    var myPage = new Page()
    {
         Resources = ThemeHelper.CurrentTheme()
    });
    

    You can also create the Application in your extension manually after Xamarin Forms' Init() and set the resources there as well. Though the Application object won't technically be accurate, it does appear to allow you to reference the resources as expected for the purposes of styling. This actually achieves my goal a little better, but I haven't tested it thoroughly. Edit: Despite the oddity of this solution, it seems to work really well and completely solves the issue without having to do anything special pages loaded by the extension.

    Application.Current = new Application();
    Application.Current.Resources = ThemeHelper.CurrentTheme();
    

    Interestingly, I did stumble upon an old bug post that stated that Page.CreateViewController() used to set Application.Current. This probably would have solved my issue without any special considerations, but it was patched.

    Either of these seems to work well enough, but I welcome any other thoughts.