msicc

.NET Dev at day & night, Geek. Father of 2 teenagers, husband of a fantastic wife. Founder of MSiccDev Software Development. Opinions are mine.
.NET Dev at day & night, Geek. Father of 2 teenagers, husband of a fantastic wife. Founder of MSiccDev Software Development. Opinions are mine.
Goodbye, 2021!

Goodbye, 2021!

Starting at dormakaba

I started this year with a new job, moving from a shareholder register to a company for access solutions. The first month was driven by a lot of explanations and testing. The main task at my new job is to write interfaces that connect our customers’ systems with our access control software. After legally being forced to work from home, I wrote a few interfaces.

During the year, I was able to convince my team of several optimizations in terms of architecture and took also the lead on them. Establishing a core library and building interface standards that just need configuration are those with the most positive impact. We also started to use Bitbucket (the company’s choice) internally, which is also one of my maintenance tasks now.

Overall, I am quite satisfied with my first year at dormakaba even if it was (and is) challenging due to the pandemic.

Side projects

In terms of my side projects, I had a slow year. I did some minor updates to my apps and eventually published them to the stores.

The main focus was put into TwistReader (a twitter list based newsreader), which isn’t available in stores yet.

TwistReader start page (dev view)

Writing this application produced some libraries (partly public/open source, partly private only). My goal is to get the app into TestFlight in the beginning of 2022 and also to write about the libraries.

Blogging

I did not blog much this year. I covered some interesting (hopefully) topics, though:

As I mentioned above, I plan to write about the libraries and also some other stuff I did in Xamarin.Forms next year.

Private stuff

The non technical part of my year was a turbulent one. As I became non-smoker last December, I restarted the sports ambitions I lost when I was young.

I started with running, did some free runs in the beginning, continuing with training for 5 km in under 30 minutes (which I am no able to achieve constantly).

I also started to train for 10 km in under 60 minutes, but was not able to finish the training course yet. I will restart this course in 2022. If you’re into running/cycling as well, feel free to follow me on Strava.

Just running isn’t enough, however, and so I also started with regular functional strength workouts with Freeletics (follow me here).

In our family, things became different as now both of our kids are no longer at school but started to work in apprenticeship. It is amazing to see them both starting they career, even though they routes are different from what we as parents expected. I wish both of my kids the best and the strength they need to succeed.


I wish all of you a Happy New Year, success, a lot of luck and strength for all the challenges of 2022.

Stay safe and healthy, everyone!

Title Image by Markéta Machová from Pixabay

Posted by msicc in Dev Stories, Editorials, 0 comments
Use the iOS system colors in Xamarin.Forms (Updated)

Use the iOS system colors in Xamarin.Forms (Updated)

Update

After publishing this post, Gerald Versluis from Microsoft responded on Twitter with an interesting information on how to get the system colors into our ResourceDictionary without using the DependencyService:

I had a quick look at the NamedPlatformColor class, but noticed that the implementation in Xamarin.Forms is incomplete. Gerald will try to update them. Once that is done, I will update the library on Github and this post again.

Original version below:


Overview

Let me give you a short overview first. To achieve our goal to use the iOS system colors, we need just a few easy steps:

  1. Xamarin.Forms interface that defines the colors
  2. Xamarin.iOS implementation of that interface
  3. ResourceDictionary to make the colors available in XAML
  4. Merging this dictionary with the application’s resource
  5. Handling of the OnRequestedThemeChanged event

Now that the plan is clear, let’s go into details.

ISystemColors interface

We will use the Xamarin.Forms DependencyService to get the colors from iOS to Xamarin.Forms. Let’s create our common interface:

using Xamarin.Forms;

namespace [YOURNAMESPACEHERE]
{
    public interface ISystemColors
    {
        Color SystemRed { get; }
        Color SystemOrange { get; }
        Color SystemYellow { get; }
        Color SystemGreen { get; }
        Color SystemMint { get; }
        Color SystemTeal { get; }
        Color SystemCyan { get; }
        Color SystemBlue { get; }
        Color SystemIndigo { get; }
        Color SystemPurple { get; }
        Color SystemPink { get; }
        Color SystemBrown { get; }
        Color SystemGray { get; }
        Color SystemGray2 { get; }
        Color SystemGray3 { get; }
        Color SystemGray4 { get; }
        Color SystemGray5 { get; }
        Color SystemGray6 { get; }
        Color SystemLabel { get; }
        Color SecondaryLabel { get; }
        Color TertiaryLabel { get; }
        Color QuaternaryLabel { get; }
        Color Placeholder { get; }
        Color Separator { get; }
        Color OpaqueSeparator { get; }
        Color LinkColor { get; }
        Color FillColor { get; }
        Color SecondaryFillColor { get; }
        Color TertiaryFillColor { get; }
        Color QuaternaryFillColor { get; }
        Color SystemBackgroundColor { get; }
        Color SecondarySystemBackgroundColor { get; }
        Color TertiarySystemBackgroundColor { get; }
        Color SystemGroupedBackgroundColor { get; }
        Color SecondarySystemGroupedBackgroundColor { get; }
        Color TertiarySystemGroupedBackgroundColor { get; }
        Color DarkTextColor { get; }
        Color LightTextColor { get; }
    }
}

As we are not able to change any of the system colors, we are just defining getters in the interface.

The Xamarin.iOS platform implementation

The implementation is straight forward. We are implementing the interface and just get the values for each system color. The list is based on Apple’s documentation for human interface and UI element colors.

using [YOURNAMESPACEHERE];

using UIKit;

using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;

[assembly: Dependency(typeof(SystemColors))]
namespace [YOURNAMESPACEHERE]
{
    //https://developer.apple.com/design/human-interface-guidelines/ios/visual-design/color/
    //https://developer.apple.com/documentation/uikit/uicolor/ui_element_colors

    public class SystemColors : ISystemColors
    {
        #region System Colors
        public Color SystemRed => UIColor.SystemRedColor.ToColor();
        public Color SystemOrange => UIColor.SystemOrangeColor.ToColor();
        public Color SystemYellow => UIColor.SystemYellowColor.ToColor();
        public Color SystemGreen => UIColor.SystemGreenColor.ToColor();
        public Color SystemMint => UIColor.SystemMintColor.ToColor();
        public Color SystemTeal => UIColor.SystemTealColor.ToColor();
        public Color SystemCyan => UIColor.SystemCyanColor.ToColor();
        public Color SystemBlue => UIColor.SystemBlueColor.ToColor();
        public Color SystemIndigo => UIColor.SystemIndigoColor.ToColor();
        public Color SystemPurple => UIColor.SystemPurpleColor.ToColor();
        public Color SystemPink => UIColor.SystemPinkColor.ToColor();
        public Color SystemBrown => UIColor.SystemBrownColor.ToColor();


        public Color SystemGray => UIColor.SystemGrayColor.ToColor();
        public Color SystemGray2 => UIColor.SystemGray2Color.ToColor();
        public Color SystemGray3 => UIColor.SystemGray3Color.ToColor();
        public Color SystemGray4 => UIColor.SystemGray4Color.ToColor();
        public Color SystemGray5 => UIColor.SystemGray5Color.ToColor();
        public Color SystemGray6 => UIColor.SystemGray6Color.ToColor();
        #endregion

        #region UI Element Colors
        public Color SystemLabel => UIColor.LabelColor.ToColor();
        public Color SecondaryLabel => UIColor.SecondaryLabelColor.ToColor();
        public Color TertiaryLabel => UIColor.TertiaryLabelColor.ToColor();
        public Color QuaternaryLabel => UIColor.QuaternaryLabelColor.ToColor();
        public Color Placeholder => UIColor.PlaceholderTextColor.ToColor();
        public Color Separator => UIColor.SeparatorColor.ToColor();
        public Color OpaqueSeparator => UIColor.SeparatorColor.ToColor();
        public Color LinkColor => UIColor.SeparatorColor.ToColor();

        public Color FillColor => UIColor.SystemFillColor.ToColor();
        public Color SecondaryFillColor => UIColor.SecondarySystemFillColor.ToColor();
        public Color TertiaryFillColor => UIColor.TertiarySystemFillColor.ToColor();
        public Color QuaternaryFillColor => UIColor.QuaternarySystemFillColor.ToColor();

        public Color SystemBackgroundColor => UIColor.SystemBackgroundColor.ToColor();
        public Color SecondarySystemBackgroundColor => UIColor.SecondarySystemBackgroundColor.ToColor();
        public Color TertiarySystemBackgroundColor => UIColor.TertiarySystemBackgroundColor.ToColor();

        public Color SystemGroupedBackgroundColor => UIColor.SystemGroupedBackgroundColor.ToColor();
        public Color SecondarySystemGroupedBackgroundColor => UIColor.SecondarySystemGroupedBackgroundColor.ToColor();
        public Color TertiarySystemGroupedBackgroundColor => UIColor.TertiarySystemGroupedBackgroundColor.ToColor();

        public Color DarkTextColor => UIColor.DarkTextColor.ToColor();
        public Color LightTextColor => UIColor.LightTextColor.ToColor();

        #endregion
    }
}

Do not forget to add the Dependency attribute on top of the implementation, otherwise it won’t work.

The ResourceDictionary

As I prefer defining my UI in XAML in Xamarin.Forms, I naturally want those colors to be available there as well. This can be done by loading the colors into a ResourceDictionary. As you might remember, I prefer codeless ResourceDictionary implementations. This time, however, we need the code-behind file to make the ResourceDictionary work for us.

First, add a new ResourceDictionary:

Add_ResourceDictionary_XAML

Then, in the code-behind file, we are using the DependencyService of Xamarin.Forms to add the colors to the ResourceDictionary:

using Xamarin.Forms;
using Xamarin.Forms.Xaml;

[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
namespace [YOURNAMESPACEHERE]
{
    public partial class SystemColorsIosResourceDictionary
    {
        public SystemColorsIosResourceDictionary()
        {
            InitializeComponent();

            this.Add(nameof(ISystemColors.SystemRed), DependencyService.Get<ISystemColors>().SystemRed);
            this.Add(nameof(ISystemColors.SystemOrange), DependencyService.Get<ISystemColors>().SystemOrange);
            this.Add(nameof(ISystemColors.SystemYellow), DependencyService.Get<ISystemColors>().SystemYellow);
            this.Add(nameof(ISystemColors.SystemGreen), DependencyService.Get<ISystemColors>().SystemGreen);
            this.Add(nameof(ISystemColors.SystemMint), DependencyService.Get<ISystemColors>().SystemMint);
            this.Add(nameof(ISystemColors.SystemTeal), DependencyService.Get<ISystemColors>().SystemTeal);
            this.Add(nameof(ISystemColors.SystemCyan), DependencyService.Get<ISystemColors>().SystemCyan);
            this.Add(nameof(ISystemColors.SystemBlue), DependencyService.Get<ISystemColors>().SystemBlue);
            this.Add(nameof(ISystemColors.SystemIndigo), DependencyService.Get<ISystemColors>().SystemIndigo);
            this.Add(nameof(ISystemColors.SystemPurple), DependencyService.Get<ISystemColors>().SystemPurple);
            this.Add(nameof(ISystemColors.SystemPink), DependencyService.Get<ISystemColors>().SystemPink);
            this.Add(nameof(ISystemColors.SystemBrown), DependencyService.Get<ISystemColors>().SystemBrown);


            this.Add(nameof(ISystemColors.SystemGray), DependencyService.Get<ISystemColors>().SystemGray);
            this.Add(nameof(ISystemColors.SystemGray2), DependencyService.Get<ISystemColors>().SystemGray2);
            this.Add(nameof(ISystemColors.SystemGray3), DependencyService.Get<ISystemColors>().SystemGray3);
            this.Add(nameof(ISystemColors.SystemGray4), DependencyService.Get<ISystemColors>().SystemGray4);
            this.Add(nameof(ISystemColors.SystemGray5), DependencyService.Get<ISystemColors>().SystemGray5);
            this.Add(nameof(ISystemColors.SystemGray6), DependencyService.Get<ISystemColors>().SystemGray6);

            this.Add(nameof(ISystemColors.SystemLabel), DependencyService.Get<ISystemColors>().SystemLabel);
            this.Add(nameof(ISystemColors.SecondaryLabel), DependencyService.Get<ISystemColors>().SecondaryLabel);
            this.Add(nameof(ISystemColors.TertiaryLabel), DependencyService.Get<ISystemColors>().TertiaryLabel);
            this.Add(nameof(ISystemColors.QuaternaryLabel), DependencyService.Get<ISystemColors>().QuaternaryLabel);

            this.Add(nameof(ISystemColors.Placeholder), DependencyService.Get<ISystemColors>().Placeholder);
            this.Add(nameof(ISystemColors.Separator), DependencyService.Get<ISystemColors>().Separator);
            this.Add(nameof(ISystemColors.OpaqueSeparator), DependencyService.Get<ISystemColors>().OpaqueSeparator);
            this.Add(nameof(ISystemColors.LinkColor), DependencyService.Get<ISystemColors>().LinkColor);

            this.Add(nameof(ISystemColors.FillColor), DependencyService.Get<ISystemColors>().FillColor);
            this.Add(nameof(ISystemColors.SecondaryFillColor), DependencyService.Get<ISystemColors>().SecondaryFillColor);
            this.Add(nameof(ISystemColors.TertiaryFillColor), DependencyService.Get<ISystemColors>().TertiaryFillColor);
            this.Add(nameof(ISystemColors.QuaternaryFillColor), DependencyService.Get<ISystemColors>().QuaternaryFillColor);

            this.Add(nameof(ISystemColors.SystemBackgroundColor), DependencyService.Get<ISystemColors>().SystemBackgroundColor);
            this.Add(nameof(ISystemColors.SecondarySystemBackgroundColor), DependencyService.Get<ISystemColors>().SecondarySystemBackgroundColor);
            this.Add(nameof(ISystemColors.TertiarySystemBackgroundColor), DependencyService.Get<ISystemColors>().TertiarySystemBackgroundColor);

            this.Add(nameof(ISystemColors.SystemGroupedBackgroundColor), DependencyService.Get<ISystemColors>().SystemGroupedBackgroundColor);
            this.Add(nameof(ISystemColors.SecondarySystemGroupedBackgroundColor), DependencyService.Get<ISystemColors>().SecondarySystemGroupedBackgroundColor);
            this.Add(nameof(ISystemColors.TertiarySystemGroupedBackgroundColor), DependencyService.Get<ISystemColors>().TertiarySystemGroupedBackgroundColor);

            this.Add(nameof(ISystemColors.DarkTextColor), DependencyService.Get<ISystemColors>().DarkTextColor);
            this.Add(nameof(ISystemColors.LightTextColor), DependencyService.Get<ISystemColors>().LightTextColor);

        }
    }
}

That’s all for the implementation. Now let’s start having a look at how to use the whole code we wrote until now.

Merging the ResourceDictionary

In Xamarin.Forms, we are able to merge ResourceDictionary classes to make them available for the whole app or on view/page level only. I consider our above created dictionary as an app-level dictionary. On top, to make it reusable, I put all these classes in a separate multi-platform library, which you can find here on Github.

Please note that the syntax will be a little different if you implement the ResourceDictionary directly in your app. Using the library approach, you will merge the dictionary in this way in App.xaml:

<?xml version="1.0" encoding="utf-8" ?>
<Application
    x:Class="SystemColorsTest.App"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:systemcolors="clr-namespace:MSiccDev.Libs.iOS.SystemColors;assembly=MSiccDev.Libs.iOS.SystemColors">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <systemcolors:SystemColorsIosResourceDictionary />
                <!--  more dictionaries here  -->
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

Responding to system theme changes

Even if I personally only change the system theme at runtime for testing themes in my apps, your users may do so frequently. Luckily, it is just a matter of handling an event to handle this scenario. In your App.xaml.cs file, register for the RequestedThemeChanged event within the constructor:

        public App()
        {
            InitializeComponent();

            Application.Current.RequestedThemeChanged += OnRequestedThemeChanged;

            this.MainVm = new MainViewModel();
            MainPage mainPage = new MainPage()
            {
                BindingContext = this.MainVm
            };

            MainPage = mainPage;
        }

As the system colors respond to the system theme change, we need to reload them to get these changes.

Within the OnRequestedThemeChanged method, we are first getting the actual merged ResourceDictionary instance. Then, we will remove this instance and register a new instance of the ResourceDictionary. This will lead to a full reload of the system colors from iOS into the app. Here is the code:

private void OnRequestedThemeChanged(object sender, AppThemeChangedEventArgs e)
{
    ResourceDictionary iosResourceDict = App.Current.Resources.MergedDictionaries.SingleOrDefault(dict => dict.GetType() == typeof(SystemColorsIosResourceDictionary));

    if (iosResourceDict != null)
    {
        App.Current.Resources.MergedDictionaries.Remove(iosResourceDict);
        App.Current.Resources.MergedDictionaries.Add(new SystemColorsIosResourceDictionary());
    }
}

That’s it, we are now ready to use the colors in XAML and our app adapts to system theme changes. Here is a sample XAML which I wrote to test the colors:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
    x:Class="SystemColorsTest.MainPage"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:local="clr-namespace:SystemColorsTest"
    x:DataType="local:MainViewModel"
    BackgroundColor="{DynamicResource SystemBackgroundColor}">

    <StackLayout>
        <Frame
            Padding="12,42,24,12"
            BackgroundColor="{DynamicResource SystemGray3}"
            CornerRadius="0">
            <Label
                FontSize="36"
                HorizontalTextAlignment="Center"
                Text="iOS SystemColors in XF"
                TextColor="{AppThemeBinding Dark={DynamicResource LightTextColor},
                                            Light={DynamicResource DarkTextColor}}" />
        </Frame>

        <ScrollView>
            <StackLayout BindableLayout.ItemsSource="{Binding SystemColors}">
                <BindableLayout.ItemTemplate>
                    <DataTemplate>
                        <Frame
                            Margin="6,3"
                            x:DataType="local:SystemColorViewModel"
                            BackgroundColor="{Binding Value}">
                            <Label Text="{Binding Name}" />
                        </Frame>
                    </DataTemplate>
                </BindableLayout.ItemTemplate>
            </StackLayout>
        </ScrollView>
    </StackLayout>
</ContentPage>

Please note that I use DynamicResource instead of StaticResource, even if some colors are static. Using DynamicResource forces the app to reload the colors, and there are some that change (like the SystemGray color palette).

Conclusion

Using the iOS system colors in Xamarin.Forms isn’t that complicated with this implementation. If you have more platforms, you could implement the same technique for the other platforms. As I am focusing on iOS for the moment, I just wrote that part. But who knows, maybe this will be extended in the future.

As always, I hope this post will be helpful for some of you.

Until the next post, happy coding, everyone!

Posted by msicc in Dev Stories, iOS, Xamarin, 5 comments
#XFQaD: Compile XAML without code behind in Xamarin.Forms

#XFQaD: Compile XAML without code behind in Xamarin.Forms

How I discovered this #XFQaD

When I was reorganizing the application resources on my current side project, I decided to create some thematically divided ResourceDictionary files. This has led me to do a quick research on Xamarin.Forms resource dictionaries.

If you’re doing this research, you will stumble upon this post from 2018 (!), where the hint to the magic I’ll show you soon was hidden.

Until now, I only used this with ResourceDictionary files. Maybe it will be helpful also for other XAML resources like controls (I will try that in the future).

How to make XAML only files compile

Add a new XAML file (sample is still ResourceDictionary) to your project:

Add_ResourceDictionary

Delete the code behind file, and add your XAML code. Before hitting the Build button, add this line immediately after the .xml file header:

<?xaml-comp compile="true" ?>

This line is where the magic happens. It tells the compiler to include the XAML file in the Build, pretty much like it does with XAML compile attribute in the code behind file.

Conclusion

The only place where I found this hint was the blog post mentioned above. Neither the docs on XAML Compilation nor the docs on resource dictionaries are mentioning this trick. It somehow went quietly from the nightly builds into production code.

Using this trick, we are able to have a more clean project structure. As always, I hope this post will be helpful for some of you.

Until the next post, happy coding!

Posted by msicc in Dev Stories, 9 comments
Dealing with the System UI on iOS in Xamarin.Forms

Dealing with the System UI on iOS in Xamarin.Forms

Having written a few applications with Xamarin.Forms by now, there was always the one part where you have to go platform specific. Over time, this part got easier as the collection of Platform-specifics in the Xamarin.Forms package was growing and growing.

This post will show (my) most used implementations leveraging the comfort of Platform-specifics as well as some other gotchas I collected over time. At the end of this post, you will also find a link to a demo project on my Github.

Large page title

Let’s start on top (literally). With iOS 11, Apple introduced large title’s that go back to small once the user is scrolling the content.

To make your app use this feature, you need two perform two steps. The first step is to tell your NavigationPage instance to prefer large titles. I often do this when creating my apps MainPage in App.xaml.cs:

public App()
{
    InitializeComponent();

    var navigationPage = new Xamarin.Forms.NavigationPage(new MainPage())
    {
        BarBackgroundColor = Color.DarkGreen,
        BarTextColor = Color.White
    };

    navigationPage.On<iOS>().SetPrefersLargeTitles(true);

    MainPage = navigationPage; 
}

This opens the door to show large titles on all pages that are managed by this NavigationPage instance. Sometimes, however, you need to actively tell the page it should use the large title (mostly happened to me in my base page implementation – never was able to nail it down to a specific point. I just opted in to always explicitly handle it on every page. In the sample application for this post, you will find a switch to toggle and untoggle the large title on the app’s MainPage:

On<iOS>().SetLargeTitleDisplay(_useLargeTitle ? 
LargeTitleDisplayMode.Always : 
LargeTitleDisplayMode.Never);

You can read more in the documentation.

StatusBar text color

Chances are high that we are customizing the BarBackgroundColor and BarTextColor properties. Of course, it makes absolutely sense that the StatusBar text follows the BarTextColor. Luckily, there is a Platform-specific for that as well:

if (this.Parent is Xamarin.Forms.NavigationPage navigationPage)
{
    navigationPage.On<iOS>().SetStatusBarTextColorMode(_statusBarTextFollowNavBarTextColor ? 
                             StatusBarTextColorMode.MatchNavigationBarTextLuminosity : 
                             StatusBarTextColorMode.DoNotAdjust);
}

The documentation ends here. However, I always need to add/change the Info.plist file as well:

<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>

Only after adding this value the above-mentioned trick for the StatusBar text works.

On iOS, the NavigationBar has a separator on its bottom. If you want to hide this separator (which always disturbs the view), you can leverage another Platform-specific on your page:

if (this.Parent is Xamarin.Forms.NavigationPage navigationPage)
{
    navigationPage.On<iOS>().SetHideNavigationBarSeparator(_hideNavBarSeparator);
}

Home indicator visibility

All iPhones after the iPhone 8 (except the SE 2) do not have the home button. Instead, they have a home indicator on the bottom of the device (at least in app). If you are trying to set the color on it, I have bad news for you: you can’t (read on to learn why).

You can hide the indicator in your app, however. Just use this Platform-specific:

On<iOS>().SetPrefersHomeIndicatorAutoHidden(_hideHomeIndicator);

Home indicator background color

Hiding the home indicator is a hard measure. Most users do not even really recognize the indicator if it is incorporated into the app’s UI. To better understand how the home indicator works, I absolutely recommend to read Nathan Gitter’s great post on the topic.

The home indicator is adaptive to its surroundings. Most probably using a matching background color is all it needs to integrate the indicator nicely in your app(s).

Safe area

Thanks to the notch and the home indicator, putting content of our apps got trickier than before. However, Xamarin.Forms has you covered as well. All we have to do is to use the SetUseSafeArea Platform-specific – it will allow us to just use the area where we are not covering any System UI like the StatusBar or the home indicator:

On<iOS>().SetUseSafeArea(_useSafeArea);

Conclusion

Even though iOS has some specialties when it comes to the System UI, Xamarin.Forms has the most important tools built in to deal with them. I absolutely recommend creating a base page for your applications and set the most common specifics there. You can find the promised demo project here on Github. Like always, I hope this post is helpful for some of you.

Until the next post, happy coding, everyone!

Posted by msicc in Dev Stories, iOS, Xamarin, 2 comments
Fix ‘Xcode is not currently installed or could not be found’ error in Visual Studio 2019 for Mac

Fix ‘Xcode is not currently installed or could not be found’ error in Visual Studio 2019 for Mac

Every now and then, our IDE’s get some updates. This week, Visual Studio for MacOS got updated once again. After that, there was a separated Download initiated for the Xcode Command Line Tools. Two days later, Visual Studio started to greet me with this little message:

Xcode missing message VS Mac

Of course, I checked first that my installed version of Xcode is still working – it stopped already for me some time ago and I had to reinstall it. As you can see, that was not the case:

Xcode 12.5 about window

After doing some research on the web, others had similar issues. The problem was that the installation of the Xcode CLI tools has overridden the location of Xcode in Preferences – as you can see in the

The fix is easy, just paste /Applications/Xcode.app/ into the location field. Please note that the trailing slash is also important:

The dialog will immediately verify the existence of Xcode (at least in version 8.9.10). Just hit that restart button and you are once again good to go.

As always, I hope this short post will be helpful for some of you.

Until the next post – happy coding, everyone.

Posted by msicc in Dev Stories, iOS, Xamarin, 2 comments
Workaround to force Xamarin.Forms WebView to use a dark mode CSS for local content on Android

Workaround to force Xamarin.Forms WebView to use a dark mode CSS for local content on Android

Recently I updated my blog reader app to support the dark mode newer iOS and Android version support. While everything went smooth on iOS and the update is already live in the App Store, I had some more work to do on Android. One of the bigger problems: the WebView I use to view posts does not automatically switch to dark mode with Xamarin.Forms.

What’s causing this problem?

On part of the problem is that the WebView does not support the CSS query “prefers-color-scheme“. This works as intended on iOS however and is a problem specific to Android. You can refer to this issue on the Xamarin.Forms repository on Github.

Workaround

I am not sure if this problem will ever get solved by the Xamarin.Forms team. I tried to play around with some Javascript solutions that are floating around the web to keep just one CSS file. In the end however, I went with a Xamarin.Forms only approach following the KISS principle.

Xamarin.Forms has a working theme detection mechanism. Based on the return value of the Application.Current.RequestedTheme property, I am loading either the dark mode CSS file or the light mode CSS file (which is default in my case).

Shipping the CSS files is easy, we just need to add them to the Assets folder and set the Build action to AndroidAsset. This results in the following structure within the Android project:

All files that are shipped that way are accessible via the android_asset file uri:

<link rel="stylesheet" href="file:///android_asset/dummycss_light.css">

Now that everything is set up in the Android project, let’s head over to the Xamarin.Forms project. In the sample for this post, I am loading a local html file, while I generate the html dynamically in my blog reader app. The idea works the same way in both cases:

private async Task SetThemeAndLoadSource()
{
    _html = await LoadHtmlFromFileAsync();

    _html = Application.Current.RequestedTheme == OSAppTheme.Dark ?
            _html.Replace("light", "dark") :
            _html.Replace("dark", "light");

    this.TestWebView.Source = new HtmlWebViewSource() { Html = _html };
}

As you can see, I just override the light and dark part of the CSS file name I load into the HTML. That’s all the “magic” that needs to happen here. Just one little thing left to add – what if the user changes the theme while the app is running? Xamarin.Forms has the solution built in as well – just handle the RequestedThemeChanged event and override the file name again, followed by setting the HtmlWebViewSource again:

private async void Current_RequestedThemeChanged(object sender, AppThemeChangedEventArgs e)
{
    await SetThemeAndLoadSource();
}

Conclusion

As most of us are already used to, we sometimes need to find some workarounds when dealing with Xamarin.Forms. While this problem could have been solved with a bunch of Javascript and a custom CSS in a WebViewRenderer as well (I tried that, but didn’t like the complexity), you can achieve reliable results with the workaround above just in Xamarin.Forms.

You can find a working sample here on Github. As always, I hope this post will be helpful for some of you.

Until the next post, happy coding, everyone!
Posted by msicc in Android, Dev Stories, Xamarin, 1 comment
Extending glidex.forms on Android to load a placeholder for images that fail to load

Extending glidex.forms on Android to load a placeholder for images that fail to load

What is glidex.forms?

The glidex.forms library is a Xamarin.Forms implementation of Glide, which is one of the quasi standards for imaging on Android (it is even recommended by Google). Luckily, Jonathan Peppers from Microsoft has a passion to improve Xamarin.Android, and Xamarin.Forms takes a big advantage from that as well. He made the Xamarin.Android Binding library as well as the Xamarin.Forms implementation. Like before with Xamarin.Forms.Nuke, I learned about that library because I am substituting my former image caching solution with Akavache.

Why do we need to extend the library?

If you want to load a placeholder that is stored in the resources of your Android project – there is no need. You could just implement a custom hook into the GlideExtensions class of glidex.forms (I’ll show you that one as well). But if you want to load an image from a Xamarin.Forms resource or even a from a font, we’ll need to extend the GlideExtensions class a little bit.

On a side note, I tried to use the existing mechanism of implementing an IGlideHandler for these purposes, but due to timing issues I never was able to load these kinds of placeholders and I moved on by extending the GlideExtensions class.

Show me some code!

Use Android resource

Let’s have a look at how to load an Android resource as a placeholder first (because it is the easiest way). To do so, we just need to create a custom implementation of an IGlideHandler in the Android project, which will then be called by the GlideExtensions implementation:

public class GlideWithAndroidResourcePlaceholder : IGlideHandler
{
    public GlideWithAndroidResourcePlaceholder()
    {
    }

    public bool Build(ImageView imageView, ImageSource source, RequestBuilder builder, CancellationToken token)
    {
        if (builder != null)
        {
            //easiest way - add the image to Android resources ....
            //general placeholder:
            //builder.Placeholder(Resource.Drawable.MSicc_Logo_Base_Blue_1024px_pad25).Into(imageView);

            //error placeholder:
            builder.Error(Resource.Drawable.MSicc_Logo_Base_Blue_1024px_pad25).Into(imageView);

            return true;
        }
        else
            return false;
    }
}

As you can see, the RequestBuilder has already a placeholder mechanism in place. We just hook into that. If you want a general placeholder (shows the image also during download), use the Placeholder method. For failed image loading only, use the Error method. That’s it.

Use Xamarin.Forms resouce/FontImageSource

As we want to be able to load FontImageSource and Xamarin.Forms resources as well however, we need to go another route. Like we did on iOS, we need to add a placeholder property to the Forms class:

public static ImageSource? PlaceholderImageSource { get; private set; }

To fill our ImageSource with either a Xamarin.Forms resource or a FontImageSource, add these two methods as well:

public static void PlaceholderFromResource (string resourceName, Assembly assembly) =>
	PlaceholderImageSource = ImageSource.FromResource (resourceName, assembly);

public static void PlaceholderFromFontImageSource (FontImageSource fontImageSource) =>
	PlaceholderImageSource = fontImageSource;

Now that we have the PlaceholderImageSource in place, we need to extend the GlideExtensions class. First, we implement a Handler for FontImageSource. The Xamarin.Forms handler for FontImageSource provides us a bitmap, which we are going to use as a placeholder. I only got this working with the AsDrawable method, the AsBitmap method always threw an exception because it couldn’t cast the Bitmap to Drawable (I did not investigate that further).

private static async Task<RequestBuilder?> HandleFontImageSource (RequestManager request, Context? context, FontImageSource fontImageSource, CancellationToken token, Func<bool> cancelled)
{
	if (context == null)
		return null;

	var defaultHandler = new Xamarin.Forms.Platform.Android.FontImageSourceHandler ();

	var bitmap = await defaultHandler.LoadImageAsync (fontImageSource, context, token);

	if (token.IsCancellationRequested || cancelled())
		return null;

	if (bitmap == null)
		return null;

	return request.AsDrawable().Load (bitmap);
}

As for the HandleFontImageSource method, I also needed to change the return value of the HandleStreamImageSource method to use the AsDrawable method, otherwise we would get the same exception as with the FontImageSource:

static async Task<RequestBuilder?> HandleStreamImageSource (RequestManager request, StreamImageSource source, CancellationToken token, Func<bool> cancelled)
{ 
        //code omitted for readability

	return request.AsDrawable().Load (memoryStream.ToArray ());
}

The final steps to make it all work are done in the LoadViaGlide method. First, add another RequestBuilder? variable and name it errorBuilder:

RequestBuilder? errorBuilder = null;

After the switch that handles the source parameter, add these lines of code:

switch(Forms.PlaceholderImageSource) {
	case StreamImageSource streamSource:
		errorBuilder = await HandleStreamImageSource (request, streamSource, token, () => !IsActivityAlive (imageView, Forms.PlaceholderImageSource));
		break;
	case FontImageSource fontImageSource:
		errorBuilder = await HandleFontImageSource(request, imageView.Context, fontImageSource, token, () => !IsActivityAlive (imageView, Forms.PlaceholderImageSource));
		break;
	default:
		errorBuilder = null;
		break;
}

if (errorBuilder != null)
	builder?.Error (errorBuilder);

We are handling our PlaceholderImageSource like we do with the ImageSource that we intend to load. If we have a valid errorBuilder, we pass that into the entire process. With that, we have already everything in place. Let’s see how to use it in your app.

How to use it in your Xamarin.Forms – Android project

Head over to the MainActivity class in your Android project and add the following method:

private void AttachGlide()
{
    Android.Glide.Forms.Init(this, null, false);

    //recommended way of loading resource images=>
    //Android.Glide.Forms.Init(this, new GlideWithAndroidResourcePlaceholder(), false);

    //Xamarin Forms resource image
    //Android.Glide.Forms.PlaceholderFromResource("CachedImageTest.MSicc_Logo_Base_Blue_1024px_pad25.png", Assembly.GetAssembly(typeof(MainViewModel)));

    //FontImageSource
    Android.Glide.Forms.PlaceholderFromFontImageSource(new FontImageSource
    {
        Glyph = XfNativeCachedImages.Resources.MaterialDesignIcons.ImageBroken,
        FontFamily = "MaterialDesignIcons",
        Color = Xamarin.Forms.Color.Red
    });
}

The Glide library needs to be initialized. Depending on the method you are using, there are separate ways to do so. The method above shows them all, you just need to change the commented code to play around with it in the sample (link at the end of the post). The mechanism is like the one I used for iOS and the Nuke package.

If you followed along (or downloaded the sample), you should see similar result to this:

Placeholder_Sample_Android_Title
Left: Single image with placeholder, Right: CollectionView placeholder

Conclusion

As we did on iOS, we now also use native caching and image handling on Android. It took me quite some time to get it up and running, but it was worth the effort. The sample has more than five hundred remote images loaded into a CollectionView. Check how smooth the scrolling is (even with DataBinding!).

You can find the sample here on Github, while the modified version of glidex.forms is available here. As always, I hope this post will be helpful for some of you.

Until the next post, happy coding, everyone!

Posted by msicc in Android, Dev Stories, Xamarin, 1 comment
Extending Xamarin.Forms.Nuke on iOS to load a placeholder for images that fail to load

Extending Xamarin.Forms.Nuke on iOS to load a placeholder for images that fail to load

What is Xamarin.Forms.Nuke?

Xamarin.Forms.Nuke is a Xamarin.Forms implementation of Nuke, one of the most advanced image libraries on iOS today. The Xamarin.Forms implementation focuses heavily on caching only, while the original library has a bunch of more features. I learned about this library when I started to look for an alternative to cache images via Akavache which I used before (I never blogged about that part because it wasn’t ready for that, tbh).

Why do we need to extend the library?

The library currently does only one thing (pretty well) – handling the caching of web images. It uses the default settings of the native Nuke library. The Xamarin.Forms implementation overwrites the ImageSourceHandler for UriImageSource and FileImageSource (optionally), but the case of placeholder loading is not intended in the original version. As I have multiple scenarios where a placeholder comes in handy, I decided to extend the library – and maintain my own fork of it from now on. (Maybe there will be a pull request to the original source, too).

Show me some code, finally!

For our extension, we modify the FormsHandler class as well as the ImageSourceHandler class. Let’s have a look at the FormsHandler class first. We are adding a new property for the placeholder:

public static ImageSource PlaceholderImageSource { get; private set; }

With that property in place, let’s add two methods. One method is for loading a placeholder image from an embedded resource file, while the second one is for specifying a FontImageSource.

public static void PlaceholderFromResource(string resourceName, Assembly assembly) =>
    PlaceholderImageSource = ImageSource.FromResource(resourceName, assembly);

public static void PlaceholderFromFontImageSource(FontImageSource fontImageSource) =>
    PlaceholderImageSource = fontImageSource;

I have chosen the FormsHandler class because setting the placeholder is a global thing (in my scenarios, your mileage may vary). That’s already everything in takes in the FormsHandler class, so let’s have a look at the ImageSourceHandler class.

As we are using the default Xamarin.Forms ImageSourceHandler for the resource image (which is a StreamImageSource) and the FontImageSource, we need to add the static fields for them first:

private static readonly StreamImagesourceHandler DefaultStreamImageSourceHandler = new StreamImagesourceHandler();

private static readonly FontImageSourceHandler DefaultFontImageSourcehandler = new FontImageSourceHandler();

Now let’s implement the loading of the placeholder in a separate method:

private static Task<UIImage> LoadPlaceholderAsync()
{
    switch (FormsHandler.PlaceholderImageSource)
    {
        case StreamImageSource streamImageSource:
            FormsHandler.Warn($"loading placeholder from resource");
            return DefaultStreamImageSourceHandler.LoadImageAsync(streamImageSource);
                    
        case FontImageSource fontImageSource:
            FormsHandler.Warn($"loading placeholder from Font");
            return DefaultFontImageSourcehandler.LoadImageAsync(fontImageSource);
        default:
            FormsHandler.Warn($"no valid placeholder found");
            return null;
    }
}

As you can see, there is nothing overly complicated in this method. Based on the type of the placeholder set in the FormsHandler class, we are calling the default Xamarin.Forms implementation for the placeholder image. Let’s take this code into action by changing the LoadImageAsync method of the ImageSourceHandler:

public async Task<UIImage> LoadImageAsync(
    ImageSource imageSource,
    CancellationToken cancellationToken = new CancellationToken(),
    float scale = 1)
{
    var result = await NukeHelper.LoadViaNuke(imageSource, cancellationToken, scale);
    if (result == null)
        result = await LoadPlaceholderAsync();

    return result;
}

As we need to know if the Nukehelper class is able to load the image, we are already running the code by awaiting it at this level. If the result is null, we are loading the placeholder image via our prior implemented method. That’s all we need to do in our forked Xamarin.Forms.Nuke repository.

How to use it in your Xamarin.Forms – iOS project

First, clone my fork (or fork it if you want) of the Xamarin.Forms.Nuke repository and import it into your Xamarin.Forms solution and reference it in your iOS project. Once that is done, we need to initialize the Nuke library (like in the original source) in the AppDelegate‘s FinishedLaunching method:

Xamarin.Forms.Nuke.FormsHandler.Init(true, false);

The second step is to define the placeholder image source. The FontImageSource should be defined after the LoadApplication method. This way, you can the Xamarin.Forms way of loading the font as a resource.

//Resource image
Xamarin.Forms.Nuke.FormsHandler.PlaceholderFromResource("CachedImageTest.MSicc_Logo_Base_Blue_1024px_pad25.png", Assembly.GetAssembly(typeof(MainViewModel)));

//FontImageSource
Xamarin.Forms.Nuke.FormsHandler.PlaceholderFromFontImageSource(new FontImageSource
{
    Glyph = CachedImageTest.Resources.MaterialDesignIcons.ImageBroken,
    FontFamily = "MaterialDesignIcons",
    Color = Color.Red
});

Now use the Xamarin.Forms Image control like you always do. If the image from the web cannot be loaded, you will see the placeholder, like in these two examples:

cached image placeholder sample
Left: Single image failed loading, right image in CollectionView failed loading

With a few additions to the Xamarin.Forms.Nuke library, we have implemented a placeholder mechanism for images that can’t be loaded. As always, I hope this post will be useful for some of you. Now that I have the iOS implementation of a fast cached image with placeholder loading in place, I will turn to Android, where I will try to achieve the same using the Glidex.Forms library and extend it to load a placeholder. There will be a full sample once that is implemented as well. Stay tuned for that one!

Until the next post, happy coding, everyone!
Posted by msicc in Dev Stories, iOS, Xamarin, 2 comments
Goodbye, 2020!

Goodbye, 2020!

In the beginning of 2020, I was polishing up the app for my personal blog as well as my WordPress reader library. I started to write a series about my experience on implementing push notifications with Azure which I still must finish.

During the spring lockdown, I also started a new project, which is now in the MVP (minimum viable product) state. I started to improve the overall performance by moving parts of the application to the cloud (ongoing process). I hope I will be able to share more on this project soon, but here’s already a screen shot:

TwistReader

Besides working on my personal projects and trying to get some fruit/vegetables from our garden, I was contacted by my new employer (dormakaba AG, starting 2021) in summer on StackOverflow. As I haven’t done any interview for close to 6 years at that time, I decided to “play the game” to gain some refreshing experience. I went through the entire process (which was also different due to COVID-19) and was offered the job – in the end, I accepted it.

Since I am changing my employer, I was quite busy in the last three months of the years to finish the work I started in my daytime job – which is the reason I was so quiet during that time.

2020 was a challenging year (mostly due to COVID-19). Overall, my family and I went through it and did handle most challenges quite well. My biggest personal achievement in 2020: I finally freed myself from the slavery of nicotine and became a non-smoker. Besides that, Santa did an excellent job again this year and upgraded my computer to a MacBook Pro:

2021 will still be a challenging year due to COVID-19. We will still need to keep distance, wear masks, and wash our hands (and stay at home as much as possible). I am sure there will be other challenges and hopefully plenty of chances as well.

Let me close this post by wishing you all a Happy New Year and more important: stay safe and healthy!


Title Image by iXimus from Pixabay

Posted by msicc in Editorials, 0 comments
Some helpful extensions when dealing with types in .NET

Some helpful extensions when dealing with types in .NET

If you are writing reusable code, chances are high that you will write quite some code that deals with types, generics, and interfaces. Over the years, the collection of my helper extensions for that have grown. As some of my upcoming posts use them, I share them (also) for future reference.

1. Check if a Type is deriving from another Type

Deriving types is a common practice. To some extent, you can use pattern matching. Sometimes, that isn’t enough, though (especially if you have a multi-level derivation path). This is when I use one of these two extensions:

        public static bool IsDerivingFrom(this Type type, Type searchType)
        {
            if (type == null) throw new NullReferenceException();

            return
                type.BaseType != null &&
                (type.BaseType == searchType ||
                type.BaseType.IsDerivingFrom(searchType));
        }

        public static bool IsDerivingFromGenericType(this Type type, Type searchGenericType)
        {
            if (type == null) throw new ArgumentNullException(nameof(type));
            if (searchGenericType == null) throw new ArgumentNullException(nameof(searchGenericType));

            return
                type != typeof(object) &&
                (type.IsGenericType &&
                searchGenericType.GetGenericTypeDefinition() == searchGenericType ||
                IsDerivingFromGenericType(type.BaseType, searchGenericType));
        }

Update 1: Type.IsSubclassOf will give you the same result as IsDerivingFrom. The main purpose was (is) to use my implementation when having multiple levels of derivation and being able to debug the whole detection process.

2. Get type of T from IEnumerable<T>

Sometimes, one needs to know the item type of an IEnumerable<T>. These two extensions will help you in this case:

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "Extension method")]
        public static Type GetItemType<T>(this IEnumerable<T> enumerable) => typeof(T);

        public static Type? GetItemType(this object enumerable)
            => enumerable == null ? null :
            (enumerable.GetType().GetInterface(typeof(IEnumerable<>).Name)?.GetGenericArguments()[0]);

3. Check if a type implements a certain interface

Interfaces are supposed to make the life of a developer easier. Like with the type derivation, sometimes we need to know if a type implements a certain interface. This extension answers the question for you:

        public static bool ImplementsInterface(this Type? type, Type? @interface)
        {
            bool result = false;

            if (type == null || @interface == null)
                return result;

            var interfaces = type.GetInterfaces();
            if (@interface.IsGenericTypeDefinition)
            {
                foreach (var item in interfaces)
                {
                    if (item.IsConstructedGenericType && item.GetGenericTypeDefinition() == @interface)
                        result = true;
                }
            }
            else
            {
                foreach (var item in interfaces)
                {
                    if (item == @interface)
                        result = true;
                }
            }

            return result;
        }

Update 2: Type.IsAssignableFrom will also tell you if a type implements an interface. As for the IsDerivingFrom method, I wanted to be able to debug the detection, which is – besides from having an explicit implementation – the main reason for this method.

4. Find a Type in an external assembly

If you need a type that lives in an external assembly but you only have it’s Name (or FullName, it’s easy to adapt), this one will resolve the Type for you as long as its assembly is loaded into your AppDomain:

        public static Type? FindType(this string name)
        {
            Type? result = null;
            var nonDynamicAssemblies = AppDomain.CurrentDomain.GetAssemblies().Where(a => !a.IsDynamic);
            try
            {
                result = nonDynamicAssemblies.
                     SelectMany(a => a.GetExportedTypes()).
                     FirstOrDefault(t => t.Name == name);
            }
            catch
            {
                result = nonDynamicAssemblies.
                     SelectMany(a => a.GetTypes()).
                     FirstOrDefault(t => t.Name == name);
            }

            return result;
        }

Conclusion

Like I said in the beginning, this post will be used for future reference. These extensions made a lot of controls, MVVM implementations and business logic I wrote in the past (both for work and my private projects) a whole lot easier. Like always, I hope this post will be helpful for some of you.

Please find the full class in this Gist.

Until the next post, happy coding!

Title Image by Tim Hill from Pixabay

Posted by msicc in Dev Stories, 3 comments