Xamarin 表单中的 Android 图像本地化 [英] Android image localisation in Xamarin Form

查看:27
本文介绍了Xamarin 表单中的 Android 图像本地化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 Xamarin Form 应用程序,它有一个语言下拉菜单,因此用户可以选择应用程序语言.当用户选择我调用的语言时:

 CultureInfoculture = CultureInfo.CreateSpecificCulture(language);System.Globalization.CultureInfo.CurrentUICulture = 文化;Thread.CurrentThread.CurrentCulture = 文化;Thread.CurrentThread.CurrentUICulture = 文化;AppResources.Culture = 文化;

应用程序运行良好并从 AppResources.{language}.resx 中选取字符串我的问题是本地化图像时.根据 Microsoft 的建议,我已将我的图像添加到 android 项目内的 Resources/drawable 文件夹中.就我而言,我将Thanks.jpg 添加到Resources/drawableResources/drawable-fr.但即使我选择 fr-FR 作为语言,它也只显示 Resources/drawable 文件夹上的图像,但是我发现如果不是更改应用程序语言(文化),而是更改设备语言,设备显示正确的图像(资源/drawable-fr 中的图像).我想知道是否有办法解决这个问题.

解决方案

您可以创建一个依赖服务来修复它.

首先,创建一个接口.

 公共接口 IChangeService{void ChangeIanguage(string lang);}

我们在 xamarin 表单的 this 格式代码中使用了它.

 <TimePicker></TimePicker><图像宽度请求=100"><图片来源><OnPlatform x:TypeArguments=ImageSource"><On Platform=iOS、Android"值=flag.png"/><在平台上=UWP"值=资产/图像/flag.png";/></OnPlatform></Image.Source></图片><按钮文本=更改"Clicked=Button_Clicked"></Button></StackLayout>

这是后台代码.

 公共部分类 LocalizedXamlPage : ContentPage{公共 LocalizedXamlPage(){初始化组件();}私有无效Button_Clicked(对象发送者,System.EventArgs e){DependencyService.Get().ChangeIanguage(en");}}

然后在android平台实现接口.如果我们更改本地化,我们需要它在运行时工作,我们应该重新启动我们的应用程序.

[程序集:依赖(typeof(ChangeLanguageService))]命名空间 UsingResxLocalization.Droid{公共类 ChangeLanguageService : IChangeService{public void ChangeIanguage(string lang = "in"){LanguageManager.ChangeLanguage(MainActivity.instance, lang);//重新启动您的应用程序.Intent intent = new Intent(MainActivity.instance, typeof(MainActivity));intent.SetFlags(ActivityFlags.ClearTask | ActivityFlags.NewTask);MainActivity.instance.StartActivity(intent);}}}

然后我们需要创建一个BaseActivity(因为我们在android中改变了Locale,所以我们应该使用相同的Context.)和LanguageManager(在运行时更改本地化)

使用系统;使用 System.Collections.Generic;使用 System.Linq;使用 System.Text;使用 Android.App;使用 Android.Content;使用Android.OS;使用 Android.Runtime;使用 Android.Support.V7.App;使用 Android.Views;使用 Android.Widget;使用 Java.Util;使用 Xamarin.Forms.Platform.Android;命名空间 UsingResxLocalization.Droid{公共类 BaseActivity : FormsAppCompatActivity{protected override void AttachBaseContext(Context @base){base.AttachBaseContext(LanguageManager.LoadLanguage(@base));}}公共类语言管理器{private const string MYLANGUAGE = "myLanguage";私有常量字符串 MYPREF = "myPreference";公共静态上下文加载语言(上下文上下文){var loadedLanguage = GetLanguage(context, Locale.Default.Language);返回 ChangeLanguage(context,loadedLanguage);}public static Context ChangeLanguage(上下文上下文,字符串语言){SaveLanguage(上下文,语言);if (Build.VERSION.SdkInt >= BuildVersionCodes.N){返回 ChangeForAPI24(上下文,语言);}返回 ChangeForLegacy(上下文,语言);}私有静态字符串 GetLanguage(上下文上下文,字符串语言){var privatePreference = context.GetSharedPreferences(MYPREF, FileCreationMode.Private);返回 privatePreference.GetString(MYLANGUAGE, Language);}private static void SaveLanguage(上下文上下文,字符串语言){var privatePreference = context.GetSharedPreferences(MYPREF, FileCreationMode.Private);var editor = privatePreference.Edit();editor.PutString(MYLANGUAGE, 语言);editor.Apply();}私有静态上下文 ChangeForAPI24(上下文上下文,字符串语言){//对于 api >= 24var locale = new Locale(language);Locale.Default = locale;var configuration = context.Resources.Configuration;configuration.SetLocale(locale);configuration.SetLayoutDirection(locale);返回 context.CreateConfigurationContext(configuration);}私有静态上下文 ChangeForLegacy(上下文上下文,字符串语言){var locale = new Locale(language);Locale.Default = locale;var 资源 = context.Resources;var 配置 = 资源.配置;configuration.Locale = locale;resources.UpdateConfiguration(配置,resources.DisplayMetrics);返回上下文;}}}

为了使 mainAcitvity 扩展 BaseActivity.cs.并公开公共静态MainActivity实例;,

 [Activity(Label = "UsingResxLocalization", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]公共类 MainActivity : BaseActivity{公共静态 MainActivity 实例;protected override void OnCreate(Bundle savedInstanceState){TabLayoutResource = Resource.Layout.Tabbar;ToolbarResource = Resource.Layout.Toolbar;实例=这个;base.OnCreate(savedInstanceState);global::Xamarin.Forms.Forms.Init(this, savedInstanceState);加载应用程序(新应用程序());}}

这是正在运行的 GIF.

========更新==========

当设备语言为英语时,我通过将语言更改为 fr 来使用法国国旗进行测试.

我把我的演示上传给你,你可以测试一下.

I have a Xamarin Form application which has a language dropdown so user can select the application language. When user select a language I call:

            CultureInfo culture = CultureInfo.CreateSpecificCulture(language);
            System.Globalization.CultureInfo.CurrentUICulture = culture;
            Thread.CurrentThread.CurrentCulture = culture;
            Thread.CurrentThread.CurrentUICulture = culture;
            AppResources.Culture = culture;

The application works fine and picks the strings from AppResources.{language}.resx My problem is when localising an image. As per Microsoft's suggestion I have added my image to Resources/drawable folders inside the android project. In my case, I added thanks.jpg to Resources/drawable and Resources/drawable-fr. But it only shows the image on Resources/drawable folder even when I select fr-FR as language, however I found out if instead of changing the application language(culture), I change the device language, the device show the correct image(the image inside Resources/drawable-fr). I was wondering if there is any way to fix this issue.

解决方案

You can create a dependence service to fix it.

First of all, create a interface.

    public interface IChangeService
    {
        void ChangeIanguage(string lang);
    }

We used it in the this format code in the xamarin forms.

  <StackLayout>
        <TimePicker></TimePicker>
        <Image WidthRequest="100">
            <Image.Source>
                <OnPlatform x:TypeArguments="ImageSource">
                    <On Platform="iOS, Android" Value="flag.png" />
                    <On Platform="UWP" Value="Assets/Images/flag.png" />
                </OnPlatform>
            </Image.Source>
            </Image>
            <Button Text="Change" Clicked="Button_Clicked"></Button>
    </StackLayout>

Here is background code.

 public partial class LocalizedXamlPage : ContentPage
    {
        public LocalizedXamlPage()
        {
            InitializeComponent();
        }

        private void Button_Clicked(object sender, System.EventArgs e)
        {
            DependencyService.Get<IChangeService>().ChangeIanguage("en");
        }
    }

Then achieve the interface in the android platform. If we change the localization, we need it to work at the runtime, we should restart our application.

[assembly: Dependency(typeof(ChangeLanguageService))]
namespace UsingResxLocalization.Droid
{
    public class ChangeLanguageService : IChangeService
    {
        public void ChangeIanguage(string lang = "in")
        {
           
            LanguageManager.ChangeLanguage(MainActivity.instance, lang);
            //restart your application.
            Intent intent = new Intent(MainActivity.instance, typeof(MainActivity));
            intent.SetFlags(ActivityFlags.ClearTask | ActivityFlags.NewTask);
            MainActivity.instance.StartActivity(intent);
        }
    }
}

Then we need to create a BaseActivity(because we change the Locale in android, we should use the same Context.) and LanguageManager(change the localization at the runtime)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Support.V7.App;
using Android.Views;
using Android.Widget;
using Java.Util;
using Xamarin.Forms.Platform.Android;

namespace UsingResxLocalization.Droid
{
    public class BaseActivity : FormsAppCompatActivity
    {
        protected override void AttachBaseContext(Context @base)
        {
            base.AttachBaseContext(LanguageManager.LoadLanguage(@base));
        }

    }

    public class LanguageManager
    {
        private const string MYLANGUAGE = "myLanguage";
        private const string MYPREF = "myPreference";

        public static Context LoadLanguage(Context context)
        {
            var loadedLanguage = GetLanguage(context, Locale.Default.Language);
            return ChangeLanguage(context, loadedLanguage);
        }

        public static Context ChangeLanguage(Context context, string language)
        {
            SaveLanguage(context, language);
            if (Build.VERSION.SdkInt >= BuildVersionCodes.N)
            {
                return ChangeForAPI24(context, language);
            }
            return ChangeForLegacy(context, language);
        }

        private static string GetLanguage(Context context, string Language)
        {
            var privatePreference = context.GetSharedPreferences(MYPREF, FileCreationMode.Private);
            return privatePreference.GetString(MYLANGUAGE, Language);
        }

        private static void SaveLanguage(Context context, string language)
        {
            var privatePreference = context.GetSharedPreferences(MYPREF, FileCreationMode.Private);
            var editor = privatePreference.Edit();
            editor.PutString(MYLANGUAGE, language);
            editor.Apply();
        }

        private static Context ChangeForAPI24(Context context, string language)
        {
            // for api >= 24
            var locale = new Locale(language);
            Locale.Default = locale;
            var configuration = context.Resources.Configuration;
            configuration.SetLocale(locale);
            configuration.SetLayoutDirection(locale);

            return context.CreateConfigurationContext(configuration);
        }

        private static Context ChangeForLegacy(Context context, string language)
        {
            var locale = new Locale(language);
            Locale.Default = locale;
            var resources = context.Resources;
            var configuration = resources.Configuration;
            configuration.Locale = locale;
            resources.UpdateConfiguration(configuration, resources.DisplayMetrics);
            return context;
        }
    }
}

To make the mainAcitvity extend the BaseActivity.cs. And expose the public static MainActivity instance;,

 [Activity(Label = "UsingResxLocalization", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
    public class MainActivity : BaseActivity
    {
        public static MainActivity instance;
        protected override void OnCreate(Bundle savedInstanceState)
        {
            TabLayoutResource = Resource.Layout.Tabbar;
            ToolbarResource = Resource.Layout.Toolbar;
            instance = this;
            base.OnCreate(savedInstanceState);

            global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
            LoadApplication(new App());
        }
    }

Here is runinng GIF.

========Update=========

I make a test with France flag by changing language to fr when the device language is English.

I upload my demo to you, you can test it.

https://github.com/851265601/LocalzationDemo/blob/master/LocalzationDemoWithFlag.zip

If you want to change the text of Button or other label, when you click the Button, Please add CultureInfo.CurrentUICulture = new CultureInfo("fr", false); as well in the click event. You can see this GIF.

这篇关于Xamarin 表单中的 Android 图像本地化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆