我目前正在使用Xamarin.Forms开发应用程序。我在iOS中面临一些严重的问题。我的根页面是TabbedPage,我想使我的标签在整个应用程序中可见。因此,我将MainPage设置如下
App.cs
MainPage = new NavigationPage(new MyTabbedPage());
MyTabbedPage.cs
Children.Add(new NavigationPage(new FirstTabbedPage()));
Children.Add(new NavigationPage(new SecondTabbedPage()));
Children.Add(new NavigationPage(new ThirdTabbedPage()));
FirstTabbedPage和SecondTabbedPage均显示使用DevExpress.Mobile的DataGrid。在从网格的任何行中点击时,我都导航到另一个ContentPage,在Root选项卡中说MyContentPage。
SecondTabbePage.cs
private async void Grid_RowTap(object sender, RowTapEventArgs e)
{
//Some code logic, to get data from server
await Navigation.PushAsync(new MyContentPage());
}
例如,我要从SecondTabbedPage导航到MyContentPage。从ContentPage,我导航到FirstTabbedPage。现在,如果我单击SecondTabbedPage,将显示MyContentPage,但我不希望出现这种情况,因此我正在使用MyContentPage的OnDisappearing方法从NavigationStack中删除页面,如下所示:
MyContentPage.cs
protected override void OnDisappearing()
{
base.OnDisappearing();
//Clear Navigation Stack, clicking on tab page should always
//go to corresponding page
try
{
var existingPages = Navigation.NavigationStack.ToList();
foreach (var page in existingPages)
{
//existingPages count should be greater than 1, so that this will never be root page. Otherwise removing root page will throw exception
if (string.Compare(page.GetType().Name, "MyContentPage", StringComparison.OrdinalIgnoreCase) == 0 && existingPages.Count > 1)
{
Navigation.RemovePage(page);
}
}
//Just to check whether page was removed or not, but still was able to see MyContentPage even after removing it from Navigation Stack
var existingPages = Navigation.NavigationStack.ToList();
}
catch(Exception ex)
{
}
}
现在的问题是:
与Android生命周期相同,相同的代码在Android中也能正常工作 在调试模式下可以看到的不同
我尝试过的一些事情是
答案 0 :(得分:1)
正如您所说,由于Android生命周期不同于iOS,我建议您通过在iOS中使用自定义渲染器来达到要求。
您应该为MyTabbedPage
创建自定义渲染器,然后在ViewControllerSelected
事件中,从ContentPage
中删除NavigationStack
。
[assembly: ExportRenderer(typeof(MainPage), typeof(myTabbarRenderer))]
namespace TabbedPageWithNavigationPage.iOS
{
class myTabbarRenderer : TabbedRenderer
{
private MainPage _page;
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
_page = (MainPage)e.NewElement;
}
else
{
_page = (MainPage)e.OldElement;
}
try
{
var tabbarController = (UITabBarController)this.ViewController;
if (null != tabbarController)
{
tabbarController.ViewControllerSelected += OnTabbarControllerItemSelected;
}
}
catch (Exception exception)
{
Console.WriteLine(exception);
}
}
private async void OnTabbarControllerItemSelected(object sender, UITabBarSelectionEventArgs eventArgs)
{
if (_page?.CurrentPage?.Navigation != null && _page.CurrentPage.Navigation.NavigationStack.Count > 0)
{
await _page.CurrentPage.Navigation.PopToRootAsync();
}
}
}
}
对于Android,请添加Device.RuntimePlatform == Device.Android
以确保代码仅在Android平台上有效:
protected override void OnDisappearing()
{
base.OnDisappearing();
//Clear Navigation Stack, clicking on tab page should always
//go to corresponding page
if (Device.RuntimePlatform == Device.Android)
{
try
{
var existingPages = Navigation.NavigationStack.ToList();
foreach (var page in existingPages)
{
//existingPages count should be greater than 1, so that this will never be root page. Otherwise removing root page will throw exception
if (string.Compare(page.GetType().Name, "UpcomingAppointmentsPage", StringComparison.OrdinalIgnoreCase) == 0 && existingPages.Count > 1)
{
Navigation.RemovePage(page);
}
}
}
catch (Exception ex)
{
}
}
}
我编写了一个演示here,您可以检查它。让我知道它是否有效。
答案 1 :(得分:0)
我尝试了@Jackhua解决方案。它也完美。但是我使用下面的方法来解决Xamarin论坛中建议的上述问题。
参考:https://forums.xamarin.com/discussion/comment/375638#Comment_375638
MyTabbedPage.cs
Page page1 = null;
Page page2 = null;
Page page3 = null;
public MainPage()
{
InitializeComponent();
page1 = new NavigationPage(new FirstTabbedPage());
page1.Title = "Page1";
page2 = new NavigationPage(new SecondTabbedPage());
page2.Title = "Page2";
page3 = new NavigationPage(new ThirdTabbedPage());
page3.Title = "Page3";
Children.Add(page1);
Children.Add(page2);
Children.Add(page3);
}
protected override void OnCurrentPageChanged()
{
base.OnCurrentPageChanged();
int index = Children.IndexOf(CurrentPage);
if (index == 0)
{
if (Children.Count > 1)
{
page2 = Children[1] as NavigationPage;
page2.Navigation.PopToRootAsync();
page3 = Children[2] as NavigationPage;
page3.Navigation.PopToRootAsync();
}
}
else if (index == 1)
{
if (Children.Count > 1)
{
page1 = Children[0] as NavigationPage;
page1.Navigation.PopToRootAsync();
page3 = Children[2] as NavigationPage;
page3.Navigation.PopToRootAsync();
}
}
else if (index == 2)
{
if (Children.Count > 1)
{
page1 = Children[0] as NavigationPage;
page1.Navigation.PopToRootAsync();
page2 = Children[1] as NavigationPage;
page2.Navigation.PopToRootAsync();
}
}
}
上述解决方案不需要自定义渲染器,并且适用于Android和iOS。
也不需要MyContentPage.cs下的代码块。即 在OnDisappearing方法下删除现有页面的迭代