#if __ANDROID_21__ using Xamarin.Forms.Platform.Android; #endif using System.Globalization; using System.Threading; using Gallery.Resources; using Gallery.Util; using Xamarin.Forms; namespace Gallery.Services { public class Environment { private static readonly CultureInfo DefaultCulture = new("zh-CN"); #if __ANDROID_21__ public static void SetStatusBarColor(Color color) { if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.Lollipop) { Android.OS.Droid.MainActivity.Main.SetStatusBarColor(color.ToAndroid()); Android.OS.Droid.MainActivity.Main.Window.DecorView.SystemUiVisibility = App.CurrentTheme == Xamarin.Essentials.AppTheme.Dark ? Android.Views.StatusBarVisibility.Visible : (Android.Views.StatusBarVisibility)Android.Views.SystemUiFlags.LightStatusBar; } } #endif public static void SetStatusBarStyle(StatusBarStyles style) { #if __IOS__ SetStatusBarStyle(ConvertStyle(style)); } public static void SetStatusBarStyle(UIKit.UIStatusBarStyle style) { if (UIKit.UIApplication.SharedApplication.StatusBarStyle == style) { return; } if (style == UIKit.UIStatusBarStyle.BlackOpaque) { UIKit.UIApplication.SharedApplication.SetStatusBarHidden(true, true); } else { if (UIKit.UIApplication.SharedApplication.StatusBarHidden) { UIKit.UIApplication.SharedApplication.SetStatusBarStyle(style, false); UIKit.UIApplication.SharedApplication.SetStatusBarHidden(false, true); } else { UIKit.UIApplication.SharedApplication.SetStatusBarStyle(style, true); } } } public static UIKit.UIStatusBarStyle ConvertStyle(StatusBarStyles style) { return style switch { StatusBarStyles.DarkText => UIKit.UIStatusBarStyle.DarkContent, StatusBarStyles.WhiteText => UIKit.UIStatusBarStyle.LightContent, StatusBarStyles.Hidden => UIKit.UIStatusBarStyle.BlackOpaque, _ => UIKit.UIStatusBarStyle.Default, }; #endif } public static void SetCultureInfo(CultureInfo ci) { Thread.CurrentThread.CurrentCulture = ci; Thread.CurrentThread.CurrentUICulture = ci; #if DEBUG Log.Print($"CurrentCulture set: {ci.Name}"); #endif } public static CultureInfo GetCurrentCultureInfo() { string lang; #if __IOS__ if (Foundation.NSLocale.PreferredLanguages.Length > 0) { var pref = Foundation.NSLocale.PreferredLanguages[0]; lang = ToDotnetLanguage(pref); } else { lang = "zh-CN"; } #elif __ANDROID__ var locale = Java.Util.Locale.Default; lang = ToDotnetLanguage(locale.ToString().Replace('_', '-')); #endif CultureInfo ci; var platform = new PlatformCulture(lang); try { ci = new CultureInfo(platform.Language); } catch (CultureNotFoundException e) { try { var fallback = ToDotnetFallbackLanguage(platform); Log.Print($"{lang} failed, trying {fallback} ({e.Message})"); ci = new CultureInfo(fallback); } catch (CultureNotFoundException e1) { Log.Error("culture.get", $"{lang} couldn't be set, using 'zh-CN' ({e1.Message})"); ci = DefaultCulture; } } return ci; } #if __IOS__ private static string ToDotnetLanguage(string iOSLanguage) { //certain languages need to be converted to CultureInfo equivalent string netLanguage = iOSLanguage switch { // "Malaysian (Malaysia)" not supported .NET culture // "Malaysian (Singapore)" not supported .NET culture "ms-MY" or "ms-SG" => "ms", // closest supported // "Schwiizertüütsch (Swiss German)" not supported .NET culture "gsw-CH" => "de-CH", // closest supported // add more application-specific cases here (if required) // ONLY use cultures that have been tested and known to work _ => iOSLanguage }; #if DEBUG Log.Print($"iOS Language: {iOSLanguage}, .NET Language/Locale: {netLanguage}"); #endif return netLanguage; } #elif __ANDROID__ private static string ToDotnetLanguage(string androidLanguage) { //certain languages need to be converted to CultureInfo equivalent string netLanguage = androidLanguage switch { // "Malaysian (Brunei)" not supported .NET culture // "Malaysian (Malaysia)" not supported .NET culture // "Malaysian (Singapore)" not supported .NET culture "ms-BN" or "ms-MY" or "ms-SG" => "ms", // closest supported // "Indonesian (Indonesia)" has different code in .NET "in-ID" => "id-ID", // correct code for .NET // "Schwiizertüütsch (Swiss German)" not supported .NET culture "gsw-CH" => "de-CH", // closest supported // add more application-specific cases here (if required) // ONLY use cultures that have been tested and known to work _ => androidLanguage }; #if DEBUG Log.Print($"Android Language: {androidLanguage}, .NET Language/Locale: {netLanguage}"); #endif return netLanguage; } #endif private static string ToDotnetFallbackLanguage(PlatformCulture platCulture) { string netLanguage = platCulture.LanguageCode switch { "pt" => "pt-PT", // fallback to Portuguese (Portugal) "gsw" => "de-CH", // equivalent to German (Switzerland) for this app // add more application-specific cases here (if required) // ONLY use cultures that have been tested and known to work _ => platCulture.LanguageCode // use the first part of the identifier (two chars, usually); }; #if DEBUG Log.Print($".NET Fallback Language/Locale: {platCulture.LanguageCode} to {netLanguage} (application-specific)"); #endif return netLanguage; } } public static class Screen { private const string StatusBarStyle = nameof(StatusBarStyle); private const string HomeIndicatorAutoHidden = nameof(HomeIndicatorAutoHidden); public static readonly BindableProperty StatusBarStyleProperty = BindableProperty.CreateAttached(StatusBarStyle, typeof(StatusBarStyles), typeof(Page), StatusBarStyles.WhiteText); public static StatusBarStyles GetStatusBarStyle(VisualElement page) => (StatusBarStyles)page.GetValue(StatusBarStyleProperty); public static void SetStatusBarStyle(VisualElement page, StatusBarStyles value) => page.SetValue(StatusBarStyleProperty, value); public static readonly BindableProperty HomeIndicatorAutoHiddenProperty = BindableProperty.CreateAttached(HomeIndicatorAutoHidden, typeof(bool), typeof(Shell), false); public static bool GetHomeIndicatorAutoHidden(VisualElement page) => (bool)page.GetValue(HomeIndicatorAutoHiddenProperty); public static void SetHomeIndicatorAutoHidden(VisualElement page, bool value) => page.SetValue(HomeIndicatorAutoHiddenProperty, value); } public enum StatusBarStyles { Default, // Will behave as normal. // White text on black NavigationBar/in iOS Dark mode and // Black text on white NavigationBar/in iOS Light mode DarkText, // Will switch the color of content of StatusBar to black. WhiteText, // Will switch the color of content of StatusBar to white. Hidden // Will hide the StatusBar } }