On my Xamarin.Forms project, I would like to display a Lottie animation during API calls or during the loading of a we
I've found another approach that works, even if this solution is a bit heavy and can be improved.
Firstly, as recommended there, I've created 2 Triggers:
public class PlayLottieAnimationTriggerAction : TriggerAction
{
protected override void Invoke(AnimationView sender)
{
Debug.WriteLine($"PlayLottieAnimationTriggerAction()");
sender.PlayAnimation();
}
}
public class StopLottieAnimationTriggerAction : TriggerAction
{
protected override void Invoke(AnimationView sender)
{
Debug.WriteLine($"StopLottieAnimationTriggerAction()");
sender.StopAnimation();
}
}
I also used EventToCommandBehaviors, like described there.
After this I can use the Lottie animation like this:
And in my ViewModel, I've declared a property ShowAnimation that is related to IsBusy and the Command OnFinishedAnimationCommand like this:
private bool _showAnimation;
public bool ShowAnimation
{
get => _showAnimation;
set => Set(ref _showAnimation, value);
}
public ICommand OnFinishedAnimationCommand
{
get
{
return new Xamarin.Forms.Command
In case of the Loader is related to a WebView, the ShowLoadingView property is set like this:
private Task WebViewNavigatingAsync(WebNavigatingEventArgs eventArgs)
{
IsBusy = true;
ShowLoadingView = true;
return Task.CompletedTask;
}
private async Task WebViewNavigatedAsync(WebNavigatedEventArgs eventArgs)
{
IsBusy = false;
}
But, as I also display an ErrorView in case of issues (timeout, unreachable server, ...) and a Reload/Retry button, I had to add some code:
private async Task WebViewNavigatedAsync(WebNavigatedEventArgs eventArgs)
{
IsBusy = false;
// for display loading animation on Refresh
while (ShowLoadingView)
await Task.Delay(50);
SetServiceError();
}
In case of the Loader is related to Data loading, the ShowLoadingView property is set like this:
private async Task GetNewsAsync(bool forceRefresh = false)
{
try
{
ShowErrorView = false;
ErrorKind = ServiceErrorKind.None;
IsBusy = true;
ShowLoadingView = true;
var _news = await _dataService.GetNews(forceRefresh);
News = new ObservableCollection(_news);
}
catch (Exception ex)
{
ErrorKind = ServiceErrorKind.ServiceIssue;
}
finally
{
IsBusy = false;
await SetServiceError();
}
}
However, I noticed that in some cases the SetServiceError() was not fired, as OnFinishedAnimation() was called in the same time. I haven't yet investigated, but I've fixed this by adding the call to SetServiceError() in in OnFinishedAnimation():
private async Task OnFinishedAnimation(object sender)
{
var view = sender as AnimationView;
if (IsBusy)
{
view.PlayAnimation();
}
else
{
ShowLoadingView = false;
// fix SetServiceError() call issue
await SetServiceError();
}
}
Don't hesitate to tell what could be done to optimize this.