Posted 27 September 2017, 11:39 pm EST
I’m using the C1 calendar component in a Xamarin Forms app to display someones schedule. This is done by displaying colors which represent different schedule types.
On iOS the page with the calendar performs as It should but on Android the performance is very poor. I’ve stripped most unnecessary markup from the page and only enable 6 months in the future and past to improve performance but It’s still way to slow. The colorcodes I get from a webservice, but I store this data in a local database to avoid multiple calls to the webservice, also to increase performance. The data then gets updated once a day.
Even navigating to the page is very slow, I’m using a MasterDetail page structure and when I click the link which navigates me to the detail page which holds the calendar It takes 2 seconds for the page to display and then the rendering of the component still has to be done. Even after the calendar has rendered navigating to another month/year is very sluggish.
Is there any way I can improve the performance of the calendar component?
- "
-
“Rendering of the calendar is slow”
-
“Navigating in the calendar is slow (Switching months/years)”
-
"
C1.Android.Calendar version: v2.3.20172.189
Xamarin Forms version: v2.3.4.270
XAML
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:c1="clr-namespace:C1.Xamarin.Forms.Calendar;assembly=C1.Xamarin.Forms.Calendar"
xmlns:controls="clr-namespace:UIBApp.Controls;assembly=UIBApp"
xmlns:converters="clr-namespace:UIBApp.Converters;assembly=UIBApp"
x:Class="UIBApp.Views.PlanboardPage"
Title="Planbord">
<ContentPage.Resources>
<ResourceDictionary>
<converters:NegateBooleanConverter x:Key="inverter"/>
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout>
<ActivityIndicator Grid.Row="0" Color="#14437b" IsRunning="{Binding IsBusy}" IsVisible="{Binding IsBusy}" Margin="0,15"/>
<c1:C1Calendar
x:Name="calendar"
VerticalOptions="FillAndExpand"
BackgroundColor="White"
FontSize="12"
HeaderFontSize="16"
DayOfWeekBackgroundColor="#eaeef3"
TextColor="Black"
TodayFontAttributes="Bold"
MaxSelectionCount="1"
SelectionChanged="OnSelectionChanged"
HeaderTextColor="#14437b"
SelectionBackgroundColor="#5C8DC7"
SelectionTextColor="White"
IsVisible="{Binding IsBusy, Converter={StaticResource inverter}}"
>
<c1:C1Calendar.DaySlotTemplate>
<DataTemplate>
<Grid HorizontalOptions="FillAndExpand" VerticalOptions="Center">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="8" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Text="{Binding Day}" Margin="0,18,0,0" HorizontalTextAlignment="Center" HorizontalOptions="FillAndExpand" VerticalOptions="Center" FontSize="12"/>
<controls:ColorCodeRepeater ItemsSource="{Binding ColorCodes}"
BackgroundColor="Transparent"
Margin="{Binding Margin}"
WidthRequest="8"
Rotation="270"
HorizontalOptions="Center"
VerticalOptions="FillAndExpand"
Grid.Row="1"
Grid.Column="0">
<controls:ColorCodeRepeater.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout>
<StackLayout>
<BoxView Color="{Binding Code}" HorizontalOptions="Center" VerticalOptions="Center" WidthRequest="8" HeightRequest="8" />
</StackLayout>
<BoxView Color="Transparent" HorizontalOptions="Center" VerticalOptions="Center" HeightRequest="2"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</controls:ColorCodeRepeater.ItemTemplate>
</controls:ColorCodeRepeater>
</Grid>
</DataTemplate>
</c1:C1Calendar.DaySlotTemplate>
</c1:C1Calendar>
</StackLayout>
</ContentPage.Content>
</ContentPage>
Codebehind
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class PlanboardPage : ContentPage
{
PlanboardViewModel viewModel;
public PlanboardPage()
{
InitializeComponent();
BindingContext = viewModel = new PlanboardViewModel(this);
BindEvents();
switch (Device.RuntimePlatform)
{
case Device.iOS:
calendar.FontFamily = "OpenSans-Regular";
calendar.HeaderFontFamily = "OpenSans-Bold";
break;
case Device.Android:
calendar.FontFamily = "OpenSans-Regular.ttf#OpenSans-Regular";
calendar.HeaderFontFamily = "OpenSans-Bold.ttf#OpenSans-Bold";
break;
}
calendar.ViewModeAnimation.AnimationMode = CalendarViewModeAnimationMode.ZoomOutIn;
calendar.ViewModeAnimation.ScaleFactor = 1.1;
calendar.ViewModeAnimation.Duration = TimeSpan.FromMilliseconds(150);
calendar.NavigateAnimation.Duration = TimeSpan.FromMilliseconds(150);
calendar.MinDate = DateTime.Now.AddMonths(-6);
calendar.MaxDate = DateTime.Now.AddMonths(6);
}
/// <summary>
/// Handle dayslotloading event
/// </summary>
public void OnDaySlotLoading(object sender, CalendarDaySlotLoadingEventArgs e)
{
if(e.Date >= calendar.ActualMinDate && e.Date <= calendar.ActualMaxDate)
{
if (viewModel.PlanboardItems != null && viewModel.PlanboardItems.Count > 0)
UpdateDaySlot(e.DaySlot, e.Date);
}
}
/// <summary>
/// Update dayslot binding context
/// </summary>
private void UpdateDaySlot(View daySlot, DateTime date)
{
var colorCodes = viewModel.GetColorCodesForDay(date);
if (colorCodes != null && colorCodes.Count > 0)
{
var margin = new Thickness(20, -20, 0, 0);
var height = 8;
switch (colorCodes.Count)
{
case 2:
height = 24;
margin = new Thickness(5, -20, 0, 0);
break;
case 3:
height = 40;
margin = new Thickness(-11, -20, 0, 0);
break;
}
daySlot.BindingContext = new
{
date.Day,
ColorCodes = colorCodes,
Height = height,
Margin = margin
};
}
else
{
daySlot.BindingContext = new
{
date.Day
};
}
}
}