如何在顶部导航中没有后退按钮的情况下切换 Xamarin Shell 中的页面

Posted

技术标签:

【中文标题】如何在顶部导航中没有后退按钮的情况下切换 Xamarin Shell 中的页面【英文标题】:How to switch pages in the Xamarin Shell without a back button in the top navigation 【发布时间】:2021-12-08 20:25:25 【问题描述】:

我的左侧菜单导航外壳中有选择器,可以更改主页语言, 例如实际上是英文的应用程序。当我更改为法语时,它会更改并重定向到带有法语文本的主页。 问题是当我在导航页面按返回箭头时,它会返回旧语言(英语)。

这里是shell导航

<Shell ..>
    <Shell.FlyoutHeader>
<Picker  ItemsSource="Binding MultiLang, Mode=TwoWay" SelectedItem="Binding SelectedLang">
     </Picker>
</Shell.FlyoutHeader>


<ShellContent x:Name="home"
Route="main"
ContentTemplate="DataTemplate home:Dashboard" />
</Shell>

这是重定向到主页的方法:

private async void ChangeLange(string lang)

...
            Routing.RegisterRoute(nameof(Dashboard), typeof(Dashboard));
            await Shell.Current.GoToAsync($"nameof(Dashboard)");// it redirect but with button back
            RemoveStackNavigation ()
         //   await Shell.Current.GoToAsync("//main"); like this , it dosent refresh the page with 

            Shell.Current.FlyoutIsPresented = false; 

这里是 MVMM

        public string _selectedLang;
        public string  SelectedLang
        
            get
            
                return _selectedLang;
            
            set
            
                if (_selectedLang != value)
                
                    _selectedLang = value;
                    OnPropertyChanged("SelectedLang");
                    ChangeBuilding(value);

                
            
        

在像这样重定向到仪表板之前,我尝试了 RemoveStackNavigation:

        public static void RemoveStackNavigation()
        
            var existingPages = Shell.Current.Navigation.NavigationStack.ToList();
            foreach (var page in existingPages)
            
                if (page != null)
                    Shell.Current.Navigation.RemovePage(page);
            
        

【问题讨论】:

您必须在主页的OnAppearing 中做一些事情,以确保它以当前语言重新呈现。我不知道该怎么做-希望其他人有建议。另一种方法是覆盖后退按钮方法 - 但由于页面已经在堆栈上,我认为这种方法更复杂 - 你必须在导航堆栈上找到页面,将其删除并替换用一个新的。 【参考方案1】:

我不太了解会发生什么,但我假设您想在滑动选择器时更改应用的语言。我认为问题不在于导航,而在于创建页面的方式。

例如,如果您现在运行您的应用程序并转到Main page,它将存储在临时缓存中,因此如果您转到另一个页面并返回,它将比您第一次进入时加载速度更快在应用程序中。

您可以测试的东西是(仅测试):

把这个选择器结果(例如:如果是法语而不是一个变量是 1,如果是英语,2 等等)和这个变量作为static,只是它不刷新,你失去了这个值。李> 在您的主页中,创建Label 并设置动态文本:
switch(pickerResult):
case "1":
 lblTest.Text = "french";
break;
case "2":
 lblTest.Text = "English";
break;
case "3":
 lblTest.Text = "Italian";
break;

并且,当你点击返回按钮时你进入的页面现在以英文显示,创建与上面完全相同的标签,看看是否有效。

如果它有效,那么一些提示:

您的页面可以包含静态文本; 您的页面未在运行时获取语言;

所以,要解决这个问题,您需要创建一些 List&lt;Words&gt; 并在选择器更改时获取正确的语言:

private void SelectedIndexChanged(sender s, EventArgs e)

  switch(pickerResult):
  case "1":
     App.wordsList = GetListOfWords("french");
  break;

这个GetListOfWords 是一个函数,您可以调用您的 xml 或 App Resource 或您用来更改语言的任何内容(即使是翻译者)。

现在你的 wordsList(或者你怎么称呼它)将被更新。

【讨论】:

【参考方案2】:

Shell 的导航栈有一些特别之处。清除导航堆栈不是一个好的选择。我们总是使用 Routes 来为 Shell 进行导航。您需要知道哪个会生成堆栈。

一个路由,它定义了作为 Shell 视觉层次结构的一部分存在的内容的路径。 一页。 Shell 视觉层次结构中不存在的页面可以从 Shell 应用程序中的任何位置推送到导航堆栈。例如,详细信息页面不会在 Shell 视觉层次结构中定义,但可以根据需要推送到导航堆栈中。

有关详细信息,请查看 MS 文档。 https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/shell/navigation

当你按下返回按钮时,覆盖返回按钮事件,然后判断路线做导航会更好。使用具体的路由名称返回。

更新:

我们在 Xamarin Forms 中调用的 Navigation Bar 编译后,在运行时变成 android 的 Action Bar。

在LoadApplication(new App());之后设置工具栏在 MainActivity 的 OnCreate 中。

        AndroidX.AppCompat.Widget.Toolbar toolbar
     = this.FindViewById<AndroidX.AppCompat.Widget.Toolbar>(Resource.Id.toolbar);
    SetSupportActionBar(toolbar);

然后覆盖 OnOptionsItemSelected()。当您按下导航栏上的返回按钮时,将触发此事件。

 public override bool OnOptionsItemSelected(IMenuItem item)
    
   
     

【讨论】:

感谢您的回答,我覆盖了后退按钮,但它仅在按下按钮后退而不是箭头后退导航时触发..您是否有任何解决方案来解决我的问题自 4 天以来一直卡住.. 请检查我的更新。

以上是关于如何在顶部导航中没有后退按钮的情况下切换 Xamarin Shell 中的页面的主要内容,如果未能解决你的问题,请参考以下文章

仅使用后退按钮和透明背景导航

导航栏上没有后退按钮

导航栏上的后退按钮仅显示没有单词的指示器

设置活动如何使用顶部的箭头向后导航

如果同时触发滑动手势和后退按钮,导航栏会变得很时髦

如何更改导航栏后退按钮的字体和颜色