Bartek Chyży
Bartek Chyży

Reputation: 541

Display text while Page is loading in Xamarin Forms

I have a page that is quite heavy and its loading for about 1-2 sec after click. During this time I see loading page header and old page content, it looks so irresponsive. All I want to achive is to display temporary Label with content like "Loading..." or activityindicator as long as new page is loading but I have no idea how to do this. What is the better way to achive this? Thanks in advance

Upvotes: 2

Views: 6936

Answers (4)

James Lin
James Lin

Reputation: 21

Try https://github.com/aritchie/userdialogs, It's make you easily to implement loading

for example:

 using (this.Dialogs.Loading("Loading text"))
    {
         //Do something i.e: await Task.Delay(3000);
    }   

OR

this.Dialogs.ShowLoading("Loading text");
//Do something i.e: await Task.Delay(3000);
this.Dialogs.HideLoading();    

OR https://github.com/aritchie/userdialogs/blob/master/src/Samples/Samples/ViewModels/ProgressViewModel.cs

Upvotes: 1

TaiT's
TaiT's

Reputation: 3216

Based on your comments on other answer - instead of ActivityIndicator - you could use a simple frame that covers all the layout and make it visible only when data are loading i.e. Binding IsVisible to IsBusy property. Then set IsBusy to true before doing the heavy load job and set back to false afterwards as shown in previous answer.

For instance, assuming your UI is based on a Grid layout (in this example 3 rows/2 columns):

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="auto" />
        <RowDefinition Height="*" />
        <RowDefinition Height="auto" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>

    <!-- Some XAML for the grid content -->

    <!-- Here, Frame covers all the possible space defined using RowSpan/ColumnSpan -->
    <Frame Grid.RowSpan="3" Grid.ColumnSpan="2" IsVisible="{Binding IsBusy}" BackgroundColor="LightGray">
       <Label VerticalOptions="Center" HorizontalOptions="Center" Text="Loading Samples..." />
    </Frame>
</Grid>

See result

-------------------------------------------------

EDIT based on OP comments:

Bases on the code you provided (better paste it in SO next time ;)), you could try this:

Add a grid layout and a frame to the xaml page:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MyApp.Namespace"    
             xmlns:tabView="clr-namespace:Syncfusion.XForms.TabView;assembly=Syncfusion.SfTabView.XForms"
             xmlns:sfPopup="clr-namespace:Syncfusion.XForms.PopupLayout;assembly=Syncfusion.SfPopupLayout.XForms" 
             BackgroundColor="#d4d4d4">

    <ContentPage.ToolbarItems>
        <ToolbarItem Icon="search_white_90.png"/>
    </ContentPage.ToolbarItems>
    <ContentPage.Content>
        <Grid>
            <tabView:SfTabView x:Name="ProductsTabView" VisibleHeaderCount="3" TabHeaderBackgroundColor="#A74B40" Items="{Binding}">
                <tabView:SfTabView.SelectionIndicatorSettings>
                    <tabView:SelectionIndicatorSettings
                        Color="#fff" StrokeThickness="3"/>
                </tabView:SfTabView.SelectionIndicatorSettings>
            </tabView:SfTabView>
            <Frame x:Name="theFrame" BackgroundColor="White">
               <Label VerticalOptions="Center" HorizontalOptions="Center" Text="Loading Samples..." />
            </Frame>
        </Grid>
    </ContentPage.Content>
</ContentPage>

ProductsTabView and theFrame will cover the same space on screen and frame will be available in code behind. Then you can show/hide theFrame before/afrer the hard work using IsVisible property:

public partial class ProviderPage : ContentPage
    {
        public ProviderPage()
        {
            InitializeComponent();            
            theFrame.IsVisible = true; // Show the Frame on top of tabView
            ProductsTabView.Items = GetTabItemCollection();    
            theFrame.IsVisible = false; // Hide the Frame
        }
        ...

As a side note, you don't use ViewModel at all. I strongly recommand you to check about what a ViewModel is and how to use them with MVVM pattern. It will make your life easier in the long run using Binding!

HIH & Happy coding!

Upvotes: 2

chkn
chkn

Reputation: 717

I have a project for advanced page transitions in Xamarin.Forms that may help you. Try this:

  1. Install this nuget: http://www.nuget.org/packages/Xamarin.Forms.Segues (it is currently only prerelease, so you'll need to check the box to see it)
  2. Add this sample to your project: https://github.com/chkn/Xamarin.Forms.Segues/blob/master/Sample/Shared/Custom%20Segues/SpinnerSegue.cs
  3. In the DoWork method of SpinnerSegue add the code to load the data.
  4. In your code that navigates to the other page, replace Navigiation.PushAsync(new MyNewPage()) with new SpinnerSegue().ExecuteAsync(this, new MyNewPage())

Upvotes: 0

NKR
NKR

Reputation: 2943

Based on your comments, you just want to display Busy indicator while you are loading the Data from your Api. You didn't posted your UI but I hope you understand how to use the below:

<Grid>
     <YOUR-UI>
         .....
         .........
     </YOUR-UI>

     <ActivityIndicator VerticalOptions="Center" IsVisible="{Binding IsBusy}" IsRunning="{Binding IsBusy}"/>
</Grid>

In your ViewModel, Add IsBusy Property as below:

private bool _isBusy;
public bool IsBusy
{
    get{return _isBusy;}
    set { _isBusy=value; RaisePropertyChanged(); }
}

Then when you are Calling the API to load your Data do something like:

public async void LoadDataFromApi()
{
    IsBusy=true;  //Show the Indicator
    var response= await YourService.Method();  //this is where you calling your api
    //do other stuffs if you need to do;
    IsBusy=false;   //Hide the Indicator
}

Let me know if you need anymore help.

Upvotes: 2

Related Questions