Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Show ActivityIndicator when pushing new page to navigation

I'm having quite some trouble implementing a functionality as simple as showing an ActivityIndicator while a page is loading, it's been proving very difficult.

This is the code I'm using on App.xaml.cs:

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

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

And this is my 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;
        }
    }

Without getting into much detail, the loadingView is a view I have on the xaml file, which houses my ActivityIndicator. My main problem here is that when I call Navigation.PushAsync(), the animation of the ActivityIndicator is halted. According to what I've read this happens because both operations happen on the Main thread, so one interrupts the other.

The reason I need to show the indicator, is because my SchedulePage takes a lot of time to render, since it has an XLabs calendar control.

How would you go about implementing something like this?

like image 230
Tharkius Avatar asked Jul 25 '16 13:07

Tharkius


2 Answers

You should try wrapping your Page Navigation in something like this:

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

This allows the process to start and keeps your UI elements responsive.

like image 168
Ravi L Avatar answered Sep 22 '22 07:09

Ravi L


yesterday I was investigating this case because I have an ActivityIndicator that doesn't show when I activated it before a PushAsync. I saw here and stackoverflow and all solutions points to run the PushAsync inside a Device.BeginInvokeOnMainThread inside a Task.Run, I tried it but nothing change.

Then I realized that all I needed was another async task that gaves ActivityIndicator time before PushAsync ran. So here is the code works in my project:

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;
            }
        }
    }
}
like image 20
jotade Avatar answered Sep 20 '22 07:09

jotade