Ste*_*rov 4 xamarin xamarin.forms
我有一个应用程序,我想要显示页面A,用户可以从中导航到页面B或C,从B返回到A或C,从C返回到A,即使用户通过B获取到C.

目前,当我执行B-> C转换时,我首先PopAsync回到A,然后我做到PushAsync了C,所以'
问题是:有没有一种文明的方式来设置这个导航方案,同时仍然依靠内置的导航来跟踪导航堆栈 - 我不想自己这样做并使用PushModalAsync.
请注意(如图中所示)A和C不是整个导航堆栈的终点,在A之前和之后都有页面,因此必须保留堆栈.
在iOS上NavigationRenderer有虚拟方法OnPopViewAsync和OnPushAsync(类似于Android):
protected override Task<bool> OnPopViewAsync(Page page, bool animated)
{
return base.OnPopViewAsync(page, animated);
}
protected override Task<bool> OnPushAsync(Page page, bool animated)
{
return base.OnPushAsync(page, animated);
}
Run Code Online (Sandbox Code Playgroud)
他们使用两个参数调用相应的基本方法,即页面以及是否为过渡设置动画.因此,您可以使用以下方法启用或禁用动画:
请注意,我还没有尝试过这种方法,因为要完成一些工作.但是在所有导航页面上禁用动画确实以这种方式工作.
编辑:我花了几个小时来实际为我自己的项目实现我的解决方案.因此,我将分享更多细节.(我在Xamarin.Forms 1.2.3-pre4上开发和测试.)
除了上面提到的Animated属性,我的导航页面重新实现了两个转换函数,并添加了一个可选参数animated,true默认情况下.这样,我们就可以保留所有现有代码,只需添加false所需的代码.
此外,在推送/弹出页面后,两种方法都会睡眠很短的时间(10毫秒).如果没有这个延迟,我们就会遇到连续通话的麻烦.
public class CustomNavigationPage: NavigationPage
{
public bool Animated { get; private set; }
public CustomNavigationPage(Page page) : base(page)
{
}
// Analysis disable once MethodOverloadWithOptionalParameter
public async Task PushAsync(Page page, bool animated = true)
{
Animated = animated;
await base.PushAsync(page);
await Task.Run(delegate {
Thread.Sleep(10);
});
}
// Analysis disable once MethodOverloadWithOptionalParameter
public async Task<Page> PopAsync(bool animated = true)
{
Animated = animated;
var task = await base.PopAsync();
await Task.Run(delegate {
Thread.Sleep(10);
});
return task;
}
}
Run Code Online (Sandbox Code Playgroud)
我的自定义导航页面的渲染器会覆盖两种转换方法,并将Animated属性传递给它们的基本方法.(以这种方式注入旗帜有点难看,但我找不到更好的解决方案.)
public class CustomNavigationRenderer: NavigationRenderer
{
protected override Task<bool> OnPopViewAsync(Page page, bool animated)
{
return base.OnPopViewAsync(page, (Element as CustomNavigationPage).Animated);
}
protected override Task<bool> OnPushAsync(Page page, bool animated)
{
return base.OnPushAsync(page, (Element as CustomNavigationPage).Animated);
}
}
Run Code Online (Sandbox Code Playgroud)
这适用于iOS.但在Android上它几乎完全相同.
为了演示连续推送和弹出页面的可能性,我编写了以下应用程序.
将App类简单地创建一个新的DemoPage包裹成一个CustomNavigationPage.请注意,此示例必须可公开访问此实例.
public static class App
{
public static CustomNavigationPage NavigationPage;
public static Page GetMainPage()
{
return NavigationPage = new CustomNavigationPage(new DemoPage("Root"));
}
}
Run Code Online (Sandbox Code Playgroud)
演示页面包含许多按钮,这些按钮以不同的顺序推送和弹出页面.您可以false为每次调用PushAsync或添加或删除选项PopAsync.
public class DemoPage: ContentPage
{
public DemoPage(string title)
{
Title = title;
Content = new StackLayout {
Children = {
new Button {
Text = "Push",
Command = new Command(o => App.NavigationPage.PushAsync(new DemoPage("Pushed"))),
},
new Button {
Text = "Pop",
Command = new Command(o => App.NavigationPage.PopAsync()),
},
new Button {
Text = "Push + Pop",
Command = new Command(async o => {
await App.NavigationPage.PushAsync(new DemoPage("Pushed (will pop immediately)"));
await App.NavigationPage.PopAsync();
}),
},
new Button {
Text = "Pop + Push",
Command = new Command(async o => {
await App.NavigationPage.PopAsync(false);
await App.NavigationPage.PushAsync(new DemoPage("Popped and pushed immediately"));
}),
},
new Button {
Text = "Push twice",
Command = new Command(async o => {
await App.NavigationPage.PushAsync(new DemoPage("Pushed (1/2)"), false);
await App.NavigationPage.PushAsync(new DemoPage("Pushed (2/2)"));
}),
},
new Button {
Text = "Pop twice",
Command = new Command(async o => {
await App.NavigationPage.PopAsync(false);
await App.NavigationPage.PopAsync();
}),
},
},
};
}
}
Run Code Online (Sandbox Code Playgroud)
重要提示:我需要花费数小时的调试时间才能发现你需要使用NavigationPage(或衍生物)的实例而不是ContentPage's Navigation!否则,立即调用两个或多个弹出或推送会导致奇怪的行为和崩溃.
小智 5
@Falko 您现在可以包含一个布尔参数:
Navigation.PushAsync (new Page2Xaml (), false);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8616 次 |
| 最近记录: |