【问题标题】:Show ActivityIndicator when pushing new page to navigation将新页面推送到导航时显示 ActivityIndi​​cator
【发布时间】:2016-07-25 13:10:14
【问题描述】:

我在实现一个在页面加载时显示 ActivityIndi​​cator 这样简单的功能时遇到了一些麻烦,事实证明这非常困难。

这是我在 App.xaml.cs 上使用的代码:

public partial class App : Application
    {
        public App()
        {
            InitializeComponent();

            MainPage = new NavigationPage(new LoginPage());
        }
    }

这是我的登录页面

public partial class LoginPage : ContentPage
    {
        public LoginPage()
        {
            InitializeComponent();

            btnLogin.Clicked += BtnLogin_Clicked;
        }

        protected async void BtnLogin_Clicked(object sender, EventArgs e)
        {
    loadingView.IsVisible = true;
    activityIndicator.IsRunning = true;

            await Navigation.PushAsync(new SchedulePage());

    loadingView.IsVisible = false;
    activityIndicator.IsRunning = false;
        }
    }

没有详细说明,loadingView 是我在 xaml 文件中的一个视图,其中包含我的 ActivityIndi​​cator。我的主要问题是,当我调用 Navigation.PushAsync() 时,ActivityIndi​​cator 的动画会停止。根据我读到的内容,这是因为这两个操作都发生在主线程上,所以一个会中断另一个。

我需要显示指示器的原因是因为我的 SchedulePage 需要大量时间来呈现,因为它有一个 XLabs 日历控件。

您将如何实施这样的事情?

【问题讨论】:

  • UI 必须在主线程上初始化,所以你不能把它排除在外。您可以做的是确保数据加载和填充日历控件以异步方式发生。
  • 这将涉及浏览 CalendarView 源代码中的所有复杂类,并弄清楚它们是如何组合在一起的,而我并不精通 C#。我正在寻找一种更简单的方法来避免任何可能的头痛,我在这里的日程安排很紧:S 现在,我将保持原样,活动指示器的简单存在,即使不是旋转,应该足以让用户知道正在发生的事情,我希望......
  • 也许确保数据加载异步发生(也就是不要在构造函数或导航到)就足够了,但基本上,是的,这就是它的意思。复杂数据的性能对于紧凑的时间表来说不是一件容易的事。 :P
  • 这可能对你有帮助,这解决了我的问题。 'forums.xamarin.com/discussion/50338/…'

标签: c# xamarin xamarin.android xamarin.forms xlabs


【解决方案1】:

您应该尝试将您的页面导航包装成这样:

Device.BeginInvokeOnMainThread (async() => {
await Navigation.PushAsync(new SchedulePage());
});

这允许流程启动并保持您的 UI 元素响应。

【讨论】:

  • 感谢您的建议,我会尝试一下,然后告诉您。
  • 不幸的是它没有解决问题,我仍然让活动指示器的动画停止。无论如何感谢您的时间;)
【解决方案2】:

昨天我正在调查这个案例,因为我有一个 ActivityIndi​​cator,当我在 PushAsync 之前激活它时它没有显示。我在这里看到了 stackoverflow 和所有解决方案都指向在 Task.Run 中的 Device.BeginInvokeOnMainThread 中运行 PushAsync,我尝试过但没有任何改变。

然后我意识到我需要的只是另一个异步任务,它在 PushAsync 运行之前为 ActivityIndi​​cator 提供时间。所以这是我项目中的代码:

public partial class MyActivities : ContentPage
{
    private bool _isLoading;

    public bool IsLoading //Binded to ActivityIndicator
    {
        get { return _isLoading; }
        private set
        {
            _isLoading = value;
            OnPropertyChanged("IsLoading");
        }
    }

    public MyActivities()
    {
        BindingContext = this;
        InitializeComponent();

        btnNavitage.Clicked += async (s,a) => 
        {
            IsLoading = true;
            var animateEnd = await aiControl.FadeTo(1d); //aiControl is the ActivityIndicator, animate it do the trick
            try
            {
                await Navigation.PushAsync(new CheckInForm()); //when the code reach the PushAsync, ActivityIndicator is already running
            }
            finally
            {
                IsLoading = false;
            }
        }
    }
}

【讨论】:

  • var animateEnd = await aiControl.FadeTo(1d); /// 此行将播放指标,但在完成之前不会执行 PushAsync 方法。
  • @AhmedSalah FadeTo 有一个参数来指示持续时间。我试过FadeTo 没有await 但它没有显示指标。
【解决方案3】:

//作为jotade的后续
//无需设置其他属性,只需在 XAML 中将 IsRunning 设置为 True 并执行以下操作即可

        -- code remove for brevity

        ActivityIndicator.IsVisible = true;

        await Task.Delay(500); 
        try
        {
            await Navigation.PushAsync(new TransactionCalculationPage(), true);
        }
        finally
        {
            ActivityIndicator.IsVisible = false;
        }   

【讨论】:

  • 您的答案格式不正确,请在发布前更新格式并阅读 SO 指南。
  • 我最终在我的代码库中做了类似的事情。但是我用Task.Yield()而不是Task.Delay()
  • 啊,但后来我在速度较慢的设备(Galaxy Tab A)上运行了代码。半秒的延迟使 ActivityIndi​​cator 在停止之前可以动画一小段时间!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-14
  • 1970-01-01
相关资源
最近更新 更多