Xamarin表单导航没有动画

时间:2014-09-20 01:02:21

标签: xamarin xamarin.forms

我有一个应用程序,我想要显示页面A,用户可以从中导航到页面B或C,从B返回到A或C,从C返回到A,即使用户通过B到达C Pages Navigation

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

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

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

5 个答案:

答案 0 :(得分:5)

在iOS上,NavigationRenderer包含虚拟方法OnPopViewAsyncOnPushAsync(类似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);
}

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

  1. 导出自定义导航页面。
  2. 添加&#34;动画&#34;属性。
  3. 为自定义导航页面导出自定义导航渲染器。
  4. 使用&#34; Animated&#34;覆盖pop和push方法调用其基本方法。属性。
  5. 请注意,我还没有尝试过这种方法,但是,因为要完成一些工作。但是,禁用所有导航页面上的动画确实可以这样做。


    编辑:我花了几个小时才真正为自己的项目实施解决方案。因此,我将分享更多细节。 (我在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;
        }
    }
    

    自定义导航渲染器

    我的自定义导航页面的渲染器会覆盖两种转换方法,并将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);
        }
    }
    

    这适用于iOS。但在Android上几乎完全相同。

    示例应用程序

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

    App课只会创建一个包含在DemoPage中的新CustomNavigationPage。请注意,此示例必须可公开访问此示例。

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

    演示页面包含许多按钮,可以按不同的顺序推送和弹出页面。您可以为每次调用falsePushAsync添加或删除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(或派生词)的实例,而不是ContentPage&# 39; s Navigation!否则,立即调用两次或多次弹出或推送会导致奇怪的行为和崩溃。

答案 1 :(得分:2)

@Falko 您现在可以包含布尔参数:

class QuotesSpider(scrapy.Spider):
name = "dialpad"

def start_requests(self):
    urls = [
        'https://help.dialpad.com/hc/en-us/categories/201278063-User-Support',
        'https://www.domo.com/',
        'https://www.zenreach.com/',
        'https://www.trendkite.com/',
        'https://peloton.com/',
        'https://ting.com/',
        'https://www.cedar.com/',
        'https://tophat.com/',
        'https://www.bambora.com/en/ca/',
        'https://www.hoteltonight.com/'
    ]
    for url in urls:
        BASE_URL = url
        yield scrapy.Request(url=url, callback=self.parse)

def parse(self, response):
    page = response.url.split("/")[2]
    filename = 'quotes-thing-{}.csv'.format(page)
    BASE_URL = response.url

    # with open(filename, 'wb') as f:
    #     f.write(response.body)
    # # with open(filename, 'r') as f:
    with open(filename, 'w') as f:
      for selector in response.css('body').xpath('.//text()'):
        selector = selector.extract()
        f.write(selector)

value_counts()

答案 2 :(得分:0)

目前Xamarin Forms导航非常简洁,我怀疑有一种很好的方法可以实现这一目标。除了做和额外的&#34; Pop&#34;必要时。

答案 3 :(得分:0)

这里有一系列片段,我和其他一些细节一起掀起,以改善iOS版的NaviagationPage。 Link to comment and code on xamarin forums.

答案 4 :(得分:0)

如果我这样做,我会做的是将Page C推送到您的NavigationStack,然后将页面B从堆栈中取出。这样,当您从页面C弹出时,您将转到第A页。

Sub FilterNew()
Dim Cel, Rng As Range
Application.ScreenUpdating = False
Application.DisplayAlerts = False

Sheets.Add(After:=Sheets(Sheets.Count)).Name = "New"     'Adds a new Sheet to store unique values
Sheets(1).Rows("1:1").Copy Sheets("New").Rows("1:1")     'Copies the header row to the new sheet

Set Rng = Sheet(1).Range("B2:B" & Sheet(1).Range("B1").End(xlDown).Row)

For Each Cel In Rng
    If Cel.Value <> Sheet(2).Cells(Cel.Row, 2).Value Then Cel.EntireRow.Copy Sheets("New").Range("A" & Rows.Count).End(xlUp).Offset(1, 0) ' The only issue I have with this is that this doesn't actually tell you if the value is unique, it just tells you ins not on the same rows of the first and second sheet - Is this alright with you?
Next

Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub

或者,即使您从页面C弹出,也可以从堆栈中删除所有类型页面B的实例,然后弹回1.在这种情况下,页面B将保留在堆栈中,直到您要移回从第C页到第A页。