Device.OnPlatform deprecated

Viewed 7634

Inside the constructor of my ContentPage I try to set a platform dependent padding value:

Padding = new Thickness(5, Device.OnPlatform(20, 5, 5), 5, 5);

Visual Studio underlines Device.OnPlatform and when I hover the mouse pointer over the method call I get the following warning:

Devide.OnPlatform(T, T, T) is obsolete: 'Use switch(RuntimePlatform) instead'.

The code initially used is from the e-book 'Creating Mobile Apps with Xamarin.Forms Book' published in 2016. I 'm really surprised how fast this platform evolves!

Unfortunately I'm not aware of how Device.OnPlatform should be replaced using the way suggested by the warning.

5 Answers
switch (Device.RuntimePlatform)
        {
            case Device.iOS:
                    Padding = new Thickness(5, 5, 5, 0);
                    break;

            default:
                    Padding = new Thickness(5, 5, 5, 0);
                    break;
         }

In case someone has the same problem in a XAML file, this is way to get around the deprecated message:

<ContentPage.Padding>
    <OnPlatform x:TypeArguments="Thickness">
        <On Platform="iOs">0,20,0,0</On>
    </OnPlatform>
</ContentPage.Padding>

I resolved this by using inline ternary conditional operator, this assumes you want something different for just iOS

Padding = new Thickness(5, (Device.RuntimePlatform==Device.iOS?20:5), 5, 5);

That was an incredible API, I don't think the reasons stated in this forum, justify it's deprecation.

It could easily have been extended to support multiple platforms. I understand that there have and will be a lot of changes in the near future but I don't think any developer would pick writing cumbersome switch statements every single time they have to make a simple decision. Code like that gets bulky.

So, I attempted to recreate the Device.OnPlatform<T>

namespace Xamarin.Forms
{
    public static class DevicePlatform
    {
        private static T OnImpl<T>(T @default = default, T iOS = default, T Android = default, Func<T> computeCustom = null)
        {
            switch (Device.RuntimePlatform)
            {
                case Device.iOS: return iOS;

                case Device.Android: return Android;

                default:
                    if (computeCustom == null) return @default;
                    return computeCustom.Invoke();
            }
        }

        public static T On<T>(T @default = default, T iOS = default, T Android = default) => OnImpl(@default, iOS, Android, null);

        public static T On<T>(T @default = default, T iOS = default, T Android = default, (string Platform, T Value) custom = default)
        {
            string runtimePlatform = Device.RuntimePlatform;

            return OnImpl(@default, iOS, Android, () =>
            {
                if (custom.Platform == runtimePlatform)
                    return custom.Value;

                return @default;
            });
        }

        public static T On<T>(T @default = default, T iOS = default, T Android = default, (string Platform, T Value) custom = default, (string Platform, T Value) custom2 = default)
        {
            string runtimePlatform = Device.RuntimePlatform;

            return OnImpl(@default, iOS, Android, () =>
            {
                if (custom.Platform == runtimePlatform)
                    return custom.Value;
                else if (custom2.Platform == runtimePlatform)
                    return custom2.Value;

                return @default;
            });
        }

        public static T On<T>(T @default = default, T iOS = default, T Android = default, (string Platform, T Value) custom = default, (string Platform, T Value) custom2 = default, (string Platform, T Value) custom3 = default)
        {
            string runtimePlatform = Device.RuntimePlatform;

            return OnImpl(@default, iOS, Android, () =>
            {
                if (custom.Platform == runtimePlatform)
                    return custom.Value;
                else if (custom2.Platform == runtimePlatform)
                    return custom2.Value;
                else if (custom3.Platform == runtimePlatform)
                    return custom3.Value;

                return @default;
            });
        }

        public static T On<T>(T @default = default, T iOS = default, T Android = default, (string Platform, T Value) custom = default, (string Platform, T Value) custom2 = default, (string Platform, T Value) custom3 = default, (string Platform, T Value) custom4 = default)
        {
            string runtimePlatform = Device.RuntimePlatform;

            return OnImpl(@default, iOS, Android, () =>
            {
                if (custom.Platform == runtimePlatform)
                    return custom.Value;
                else if (custom2.Platform == runtimePlatform)
                    return custom2.Value;
                else if (custom3.Platform == runtimePlatform)
                    return custom3.Value;
                else if (custom4.Platform == runtimePlatform)
                    return custom4.Value;

                return @default;
            });
        }

        public static T On<T>(T @default = default, T iOS = default, T Android = default, params (string Platform, T Value)[] customPlatforms)
        {
            string runtimePlatform = Device.RuntimePlatform;

            return OnImpl(@default, iOS, Android, () =>
            {
                for (int i = 0; i < customPlatforms.Length; i++)
                {
                    var platform = customPlatforms[i];
                    if (platform.Platform == runtimePlatform)
                        return platform.Value;
                }

                return @default;
            });
        }
    }
}

Here's a sample on how it can be used:

Padding = new Thickness(0, DevicePlatform.On(0, iOS: 20, Android: 0, custom: (Device.Tizen, 34)));

As you can see our cool API is back and Tizen stays remembered forever.

I plan on making a micro nuget package out of this, so I'm open to corrections and help in any form.

Cheers

Related