Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to improve loading performance in Tabbed Page xamarin forms

I am trying to create bottom tabbed page in Xamarin forms and i am doing this for Android.

here i am using latest version of Xamarin Forms.

My sample Bottom tabbed page like below.

<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:views="clr-namespace:SampleTabbedPage.Views"
            xmlns:android="clr-namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core"
            android:TabbedPage.ToolbarPlacement="Bottom"
            android:TabbedPage.BarItemColor="Gray"
            android:TabbedPage.BarSelectedItemColor="Blue"
             mc:Ignorable="d"
             x:Class="SampleTabbedPage.Views.SampleTabbed">
  <!--Pages can be added as references or inline-->

    <NavigationPage
        Title="Main"
        NavigationPage.HasNavigationBar="False">
        <x:Arguments>
            <views:SampleDetailsPage/>
        </x:Arguments>
    </NavigationPage>

    <ContentPage Title="Tab 1" />
  <ContentPage Title="Tab 2" />
</TabbedPage>

My sample details page like

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="SampleTabbedPage.Views.SampleDetailsPage"
             BackgroundColor="Gray">
    <ContentPage.Content>
        <StackLayout>
            <ListView BackgroundColor="White" ItemTapped="ListView_ItemTapped">
                <ListView.ItemsSource>
                    <x:Array Type="{x:Type x:String}">
                        <x:String>Mango</x:String>
                        <x:String>Banana</x:String>
                        <x:String>Pinaple</x:String>
                        <x:String>Apple</x:String>
                        <x:String>Avacado</x:String>
                        <x:String>Coconut</x:String>
                        <x:String>Dragan Fruit</x:String>
                        <x:String>Pomaganate</x:String>
                        <x:String>Wood Apple</x:String>
                    </x:Array>
                </ListView.ItemsSource>
            </ListView>

        </StackLayout>
    </ContentPage.Content>
</ContentPage>

And the navigation i am doing as follows

in App.xamal.cs

MainPage = new NavigationPage(new FirstPage());

I have simple first page

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="SampleTabbedPage.Views.FirstPage">
    <ContentPage.Content>
        <StackLayout>
            <Button Text="Click Me!" Clicked="Button_Clicked"
                VerticalOptions="CenterAndExpand" 
                HorizontalOptions="CenterAndExpand" />
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

here in button click event i do the navigation to "Sample Tabbed Page"

await Navigation.PushAsync(new SampleTabbed());

This is working fine. but there is a performance issue.

if i run this and click on button in First page it is taking 3 seconds to load tabbed page.

if i remove list view in sample detail page it take 2 seconds to load.

but if i add just a content page to click event it take only milliseconds to load.

Am i doing some thing wrong with implementing tabbed page?

or

is there any way to improve the loading performance with tabbed pages.

like image 723
Chandu Ranwala Avatar asked Oct 27 '25 14:10

Chandu Ranwala


1 Answers

A solution is to make the heavy pages load their content in a lazy manner, only when their tab becomes selected. This way, since these pages are now empty when TabbedPage is created, navigating to the TabbedPage suddenly becomes very fast!

1.create a behavior for the TabbedPage page, called ActivePageTabbedPageBehavior.

class ActivePageTabbedPageBehavior : Behavior<TabbedPage>
{
 protected override void OnAttachedTo(TabbedPage tabbedPage)
  {
    base.OnAttachedTo(tabbedPage);
    tabbedPage.CurrentPageChanged += OnTabbedPageCurrentPageChanged;
  }

 protected override void OnDetachingFrom(TabbedPage tabbedPage)
  {
    base.OnDetachingFrom(tabbedPage);
    tabbedPage.CurrentPageChanged -= OnTabbedPageCurrentPageChanged;
  }

 private void OnTabbedPageCurrentPageChanged(object sender, EventArgs e)
  {
    var tabbedPage = (TabbedPage)sender;

    // Deactivate previously selected page
    IActiveAware prevActiveAwarePage = tabbedPage.Children.OfType<IActiveAware>()
        .FirstOrDefault(c => c.IsActive && tabbedPage.CurrentPage != c);
    if (prevActiveAwarePage != null)
    {
        prevActiveAwarePage.IsActive = false;
    }

    // Activate selected page
    if (tabbedPage.CurrentPage is IActiveAware activeAwarePage)
    {
        activeAwarePage.IsActive = true;
    }
  }
}

2.define IActiveAware interface

interface IActiveAware
  {
    bool IsActive { get; set; }
    event EventHandler IsActiveChanged;
  }

3.create a base generic abstract class called LoadContentOnActivateBehavior

abstract class LoadContentOnActivateBehavior<TActivateAwareElement> : Behavior<TActivateAwareElement>
   where TActivateAwareElement : VisualElement
 {
  public DataTemplate ContentTemplate { get; set; }

  protected override void OnAttachedTo(TActivateAwareElement element)
   {
     base.OnAttachedTo(element);
     (element as IActiveAware).IsActiveChanged += OnIsActiveChanged;
   }

  protected override void OnDetachingFrom(TActivateAwareElement element)
   {
     (element as IActiveAware).IsActiveChanged -= OnIsActiveChanged;
     base.OnDetachingFrom(element);
   }

  void OnIsActiveChanged(object sender, EventArgs e)
   {
     var element = (TActivateAwareElement)sender;
     element.Behaviors.Remove(this);
     SetContent(element, (View)ContentTemplate.CreateContent());
   }

  protected abstract void SetContent(TActivateAwareElement element, View contentView);
}

4.the specialized LazyContentPageBehavior

class LazyContentPageBehavior : LoadContentOnActivateBehavior<ContentView>
 {
   protected override void SetContent(ContentView element, View contentView)
    {
      element.Content = contentView;
    }
 }

then we can use in xaml like this:

<TabbedPage>
  <TabbedPage.Behaviors>
    <local:ActivePageTabbedPageBehavior />
  </TabbedPage.Behaviors>

<ContentPage Title="First tab">
    <Label Text="First tab layout" />
</ContentPage>

<local:LazyLoadedContentPage Title="Second tab">
    <ContentPage.Behaviors>
        <local:LazyContentPageBehavior ContentTemplate="{StaticResource ContentTemplate}" />
    </ContentPage.Behaviors>
    <ContentPage.Resources>
        <ResourceDictionary>
            <DataTemplate x:Key="ContentTemplate">
                <!-- Complex and slow to render layout -->
                <local:SlowContentView />
            </DataTemplate>
        </ResourceDictionary>
    </ContentPage.Resources>
</local:LazyLoadedContentPage>
</TabbedPage>

we moved the ContentPage complex layout to become a DataTemplate.

Here's the custom LazyLoadedContentPage page which is activation aware:

class LazyLoadedContentPage : ContentPage, IActiveAware
{
  public event EventHandler IsActiveChanged;

  bool _isActive;
  public bool IsActive
   {
     get => _isActive;
     set
      {
        if (_isActive != value)
        {
            _isActive = value;
            IsActiveChanged?.Invoke(this, EventArgs.Empty);
        }
      }
   }
 }

SlowContentView do some complex things

 public partial class SlowContentView : ContentView
{
    public SlowContentView()
    {
        InitializeComponent();

        // Simulating a complex view
        ...
    }
}
like image 141
Leo Zhu - MSFT Avatar answered Oct 30 '25 04:10

Leo Zhu - MSFT