2021-08-06 14:42:40 +08:00

217 lines
8.4 KiB
C#

#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
}
}