Xamarin Forms Navigation(不含动画) [英] Xamarin Forms Navigation without animation

查看:68
本文介绍了Xamarin Forms Navigation(不含动画)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个要在其中显示页面A的应用程序,用户可以从中导航到页面B或C,从B导航回A或C,仅从C导航回A,即使用户通过B去C

I have an app where I want to show page A, from which the user can navigate to page B or C, from B back to A or to C, and from C only back to A, even if the user when through B to get to C

当前,当我执行B-> C转换时,我先PopAsync返回A,然后再执行PushAsync到达C,所以'

问题是:是否有一种文明的方式来设置此导航方案,同时仍然依靠内置的Navigation来跟踪导航堆栈-我不想自己这样做并使用PushModalAsync.

Currently when I'm executing the B->C transition I first PopAsync to get back to A and then I do PushAsync to get to C, so that the '

The question is: is there a civilized way to set up this navigation scheme while still relying on the built-in Navigation to keep track of navigation stack - I don't want to do that myself and use PushModalAsync.

请注意(如图所示)A和C并不是整个导航堆栈的终点,在A之前和C之后都有页面,因此必须保留堆栈.

Note that (as reflected in the image) A and C aren't the end points of the whole navigation stack, there are pages before A and after C, so the stack has to be preserved.

推荐答案

在iOS上,NavigationRenderer具有虚拟方法OnPopViewAsyncOnPushAsync(类似在Android上):

On iOS the NavigationRenderer has virtual methods OnPopViewAsync and OnPushAsync (similar on 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);
}

它们使用两个参数调用相应的基本方法,即页面和是否为过渡设置动画.因此,您可以使用以下方法启用或禁用动画:

They call the corresponding base method with two arguments, the page and whether to animate the transition. Thus, you might be able to enable or disable the animation using the following approach:

  1. 派生自定义导航页面.
  2. 添加动画"属性.
  3. 为您的自定义导航页面导出自定义导航渲染器.
  4. 使用"Animated"属性覆盖调用其基本方法的pop和push方法.

请注意,我还没有尝试过这种方法,因为这需要做很多工作.但是在所有导航页面上禁用动画确实可以这种方式工作.

Note that I haven't tried this approach, yet, since it is quite some work to do. But disabling animations on all navigation pages did work this way.

编辑:我花了几个小时才能真正为自己的项目实施解决方案.因此,我将分享更多细节. (我在Xamarin.Forms 1.2.3-pre4上进行了开发和测试.)

It took me several hours to actually implement my solution for my own project. Therefore, I'll share some more details. (I developed and tested on Xamarin.Forms 1.2.3-pre4.)

除了上面提到的Animated属性,我的导航页面还重新实现了两个转换函数,并添加了可选参数animated,默认情况下为true.这样,我们将能够保留所有现有代码,并仅在需要的地方添加false.

Besides the above-mentioned Animated property my navigation page re-implements the two transition functions and adds an optional argument animated, which is true by default. This way we'll be able to keep all existing code and only add a false where needed.

此外,这两种方法在推入/弹出页面后都会休眠很短的时间(10毫秒).没有这种延迟,我们就会遇到连续通话的麻烦.

Furthermore, both method will sleep for a very short time (10 ms) after pushing/popping the page. Without this delay we'd ran into trouble with consecutive calls.

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;
    }
}

自定义导航渲染器

我的自定义导航页面的渲染器会覆盖这两种转换方法,并将Animated属性传递给它们的基本方法. (以这种方式插入标志有点丑陋,但我找不到更好的解决方案.)

The custom navigation renderer

The renderer for my custom navigation page overrides both transition methods and passes the Animated property to their base methods. (It's kind of ugly to inject a flag this way, but I couldn't find a better solution.)

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);
    }
}

这是针对iOS的.但是在Android上几乎完全相同.

This is for iOS. But on Android it's almost identically.

为了演示连续推送和弹出页面的可能性,我编写了以下应用程序.

To demonstrate the possibilities of consecutively pushing and popping pages, I wrote the following application.

App类仅创建包裹在CustomNavigationPage中的新的DemoPage.请注意,此实例必须是可公开访问的.

The App class simply creates a new DemoPage wrapped into a CustomNavigationPage. Note that this instance must be publicly accessible for this example.

public static class App
{
    public static CustomNavigationPage NavigationPage;

    public static Page GetMainPage()
    {    
        return NavigationPage = new CustomNavigationPage(new DemoPage("Root"));
    }
}

演示页面包含许多按钮,这些按钮可以按不同的顺序推送和弹出页面.您可以为每次对PushAsyncPopAsync的调用添加或删除false选项.

The demo page contains a number of buttons that push and pop pages in different orders. You can add or remove the false option for each call to PushAsync or 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();
                    }),
                },
            },
        };
    }
}

重要提示:花了我几个小时的调试时间才能发现您需要使用NavigationPage(或派生)实例而不是ContentPageNavigation!否则,立即调用两次或多次弹出或按下会导致奇怪的行为并崩溃.

Important hint: It cost me hours of debugging to find out that you need to use an instance of NavigationPage (or a derivative) rather than the ContentPage's Navigation! Otherwise the immediate call of two or more pops or pushes leads to strange behaviour and crashes.

这篇关于Xamarin Forms Navigation(不含动画)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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