Xamarin 表单变暗,切换语言时 appshell 不再工作



我通过AppResources.resx文件实现了语言更改,我有两个文件:AppResources.res和AppResources.fr.resx。使用以下代码切换语言:

private void Language_switch(object sender, EventArgs e)
{
var lang_switch = Lang.Text;
if (lang_switch == "FR")
{
CultureInfo language = new CultureInfo("fr");
Thread.CurrentThread.CurrentUICulture = language;
AppResources.Culture = language;
}
else
{
CultureInfo language = new CultureInfo("");
Thread.CurrentThread.CurrentUICulture = language;
AppResources.Culture = language;
}
Application.Current.MainPage = new NavigationPage(new PointsPage());
}

语言切换得很好,但每当我这样做时,应用程序就会变暗,AppShell似乎会崩溃,它只显示我制作的工具栏项目的顶部栏(似乎是标准的xamarin颜色(,并显示它试图在底部显示导航的内容,但这看起来只是一个栏,但上面似乎没有导航,也没有任何导航标签。

如果我向下滚动,页面上的内容似乎也与该栏重叠。如果我再次按下切换按钮,它仍然会切换语言,但仍处于这种黑暗模式。我的应用程序中没有任何深色设置,也没有实现深色模式。

它似乎也在我做的每一个页面上都这样做。我如何才能阻止这种情况的发生,使它使用我为应用程序制作的布局,而不会变暗?

编辑:我发现问题不在语言转换上。当我使用转到另一个页面时

Application.Current.MainPage = new NavigationPage(new PointsPage());

删除语言切换代码后,它仍然会改变颜色。在我看来,页面被放在了顶部,而AppShell却没有移动到顶部。有没有办法重新加载AppShell?

第二版:我设法修复了它。因为我怀疑AppShell没有重新加载,也没有放在重新加载的页面上。我添加了

Application.Current.MainPage = new AppShell();

在页面下方重新加载,现在一切都在中工作

当您使用.resx文件进行本地化时,创建具有匹配文件名的resx文件,当您更改系统语言时,重新打开应用程序将显示您在.resx.中设置的匹配资源

有关它的更多详细信息,您可以参考MS文档。https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/localization/text?pivots=windows

代码示例:https://github.com/xamarin/xamarin-forms-samples/tree/main/UsingResxLocalization

如果您想在运行时更改它,可以使用ResourceManager。它在运行时提供了对特定于区域性的资源的方便访问。

我举一个简单的例子供你参考。

MainPage:String1,设置是.resx文件中的关键。

<StackLayout>
<Label Text="{Binding Resources[String1]}" 
VerticalOptions="Center" 
HorizontalOptions="Center" />
<Button Text="{Binding Resources[Settings]}" 
HorizontalOptions="Center"
Clicked="Button_Clicked" />
</StackLayout>

代码背后:

public MainPage()
{
InitializeComponent();
this.BindingContext = new MainPageViewModel();
}
private void Button_Clicked(object sender, EventArgs e)
{
Navigation.PushAsync(new SettingsPage());
}

设置页面:

<StackLayout>
<Label Text="{Binding Resources[PickLng]}" />
<Picker ItemsSource="{Binding Languages}" SelectedItem="{Binding SelectedLanguage, Mode=TwoWay}" />
</StackLayout>

代码背后:

public SettingsPage()
{
InitializeComponent();
BindingContext = new SettingsViewModel();
}

ViewModel:

public class CultureChangedMessage
{
public CultureInfo NewCultureInfo { get; private set; }
public CultureChangedMessage(string lngName)
: this(new CultureInfo(lngName))
{ }
public CultureChangedMessage(CultureInfo newCultureInfo)
{
NewCultureInfo = newCultureInfo;
}
}
public class LocalizedResources : INotifyPropertyChanged
{
const string DEFAULT_LANGUAGE = "en";
readonly ResourceManager ResourceManager;
CultureInfo CurrentCultureInfo;
public string this[string key]
{
get
{
return ResourceManager.GetString(key, CurrentCultureInfo);
}
}
public LocalizedResources(Type resource, string language = null)
: this(resource, new CultureInfo(language ?? DEFAULT_LANGUAGE))
{ }
public LocalizedResources(Type resource, CultureInfo cultureInfo)
{
CurrentCultureInfo = cultureInfo;
ResourceManager = new ResourceManager(resource);
MessagingCenter.Subscribe<object, CultureChangedMessage>(this,
string.Empty, OnCultureChanged);
}
private void OnCultureChanged(object s, CultureChangedMessage ccm)
{
CurrentCultureInfo = ccm.NewCultureInfo;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Item"));
}
public event PropertyChangedEventHandler PropertyChanged;
}
public class ViewModelBase : INotifyPropertyChanged
{
public LocalizedResources Resources
{
get;
private set;
}
public ViewModelBase()
{
Resources = new LocalizedResources(typeof(AppResources), App.CurrentLanguage);
}
public void OnPropertyChanged([CallerMemberName] string property = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}
public event PropertyChangedEventHandler PropertyChanged;
}
public class MainPageViewModel : ViewModelBase
{ }
public class SettingsViewModel : ViewModelBase
{
public List<string> Languages { get; set; } = new List<string>()
{
"EN",
"FR"
};
private string _SelectedLanguage;
public string SelectedLanguage
{
get { return _SelectedLanguage; }
set
{
_SelectedLanguage = value;
SetLanguage();
}
}
public SettingsViewModel()
{
_SelectedLanguage = App.CurrentLanguage;
}
private void SetLanguage()
{
App.CurrentLanguage = SelectedLanguage;
MessagingCenter.Send<object, CultureChangedMessage>(this,
string.Empty, new CultureChangedMessage(SelectedLanguage));
}
}

最新更新