Xamarin.Forms:如何在数据加载期间 IsBusy 为真时至少显示一次 Lottie 动画? [英] Xamarin.Forms: how to display a Lottie animation at least one time when IsBusy is true during data loading?

查看:81
本文介绍了Xamarin.Forms:如何在数据加载期间 IsBusy 为真时至少显示一次 Lottie 动画?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的 Xamarin.Forms项目中,我想在 API调用期间或在网站中的 WebView 中.

On my Xamarin.Forms project, I would like to display a Lottie animation during API calls or during the loading of a website in a WebView.

为此,我将 Lottie动画 IsVisible 属性绑定到了 ViewModels IsBusy 属性:效果很好.

For this, I've bounded the IsVisible property of the Lottie animation to the IsBusy property of my ViewModels: this works well.

<lottie:AnimationView Animation="resource://lottie_loading.json?assembly=MyApp"
        AnimationSource="EmbeddedResource"
        BackgroundColor="Transparent"
        AutoPlay="True"
        RepeatMode="Infinite"
        IsVisible="{Binding IsBusy}">

但是加载时间有时很短,因此我想找到一种方法来完全显示一次Lottie动画,然后将其隐藏.

But the loading duration is sometimes very short, so I would like to found a way to display the Lottie animation once in full before to hidden it.

=>是否可以?有什么更好的方法来实现这一目标?

推荐答案

我发现了另一种可行的方法,即使该解决方案有点繁琐并且可以改进.

I've found another approach that works, even if this solution is a bit heavy and can be improved.

首先,按照建议,我已经创建了2个触发器:

Firstly, as recommended there, I've created 2 Triggers:

public class PlayLottieAnimationTriggerAction : TriggerAction<AnimationView>
{
    protected override void Invoke(AnimationView sender)
    {
        Debug.WriteLine($"PlayLottieAnimationTriggerAction()");
        sender.PlayAnimation();
    }
}

public class StopLottieAnimationTriggerAction : TriggerAction<AnimationView>
{
    protected override void Invoke(AnimationView sender)
    {
        Debug.WriteLine($"StopLottieAnimationTriggerAction()");
        sender.StopAnimation();
    }
}

我还使用了 EventToCommandBehaviors ,如.

在此之后,我可以像这样使用 Lottie动画:

After this I can use the Lottie animation like this:

<forms:AnimationView 
    x:Name="animationView" 
    BackgroundColor="Transparent"
    AutoPlay="True"
    IsVisible="{Binding ShowAnimation}"
    Animation="resource://lottie_4squares_apricot_blond.json?assembly=Example.Forms"
    AnimationSource="EmbeddedResource"
    VerticalOptions="FillAndExpand" 
    HorizontalOptions="FillAndExpand">
    <forms:AnimationView.Triggers>
        <MultiTrigger TargetType="forms:AnimationView">
            <MultiTrigger.Conditions>
                <BindingCondition Binding="{Binding ShowAnimation}" Value="True" />
            </MultiTrigger.Conditions>
            <MultiTrigger.EnterActions>
                <triggers:LottieTriggerAction />
            </MultiTrigger.EnterActions>
            <MultiTrigger.ExitActions>
                <actions:StopLottieAnimationTriggerAction />
            </MultiTrigger.ExitActions>
        </MultiTrigger>
    </forms:AnimationView.Triggers>
    <forms:AnimationView.Behaviors>
        <behaviors:EventToCommandBehavior
            EventName="OnFinishedAnimation"
            Command="{Binding OnFinishedAnimationCommand}"
            CommandParameter="{x:Reference animationView}"/>
    </forms:AnimationView.Behaviors>
</forms:AnimationView>

在我的 ViewModel 中,我声明了一个属性 ShowAnimation ,该属性与 IsBusy 和命令 OnFinishedAnimationCommand

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<object>(async (object sender) =>
        {
            if (sender != null)
            {
                await OnFinishedAnimation(sender);
            }
        });
    }
}

private Task OnFinishedAnimation(object sender)
{
    var view = sender as AnimationView;
    if (IsBusy)
    {
        view.PlayAnimation();
    }
    else
    {
        ShowAnimation = false;
    }
    return Task.CompletedTask;
}

如果 Loader WebView 相关,则 ShowLoadingView 属性设置如下:

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;
}

但是,由于在出现问题(超时,服务器无法访问,...)和重新加载/重试"按钮的情况下,我还显示了 ErrorView ,因此我不得不添加一些代码:

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();
}

如果Loader数据加载相关,ShowLoadingView属性设置如下:

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>(_news);
    }
    catch (Exception ex)
    {
        ErrorKind = ServiceErrorKind.ServiceIssue;
    }
    finally
    {
        IsBusy = false;
        await SetServiceError();
    }

}

然而,我注意到在某些情况下 SetServiceError() 没有被触发,因为 OnFinishedAnimation() 被同时调用.我尚未进行调查,但已通过在 OnFinishedAnimation()中将调用添加到 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.

这篇关于Xamarin.Forms:如何在数据加载期间 IsBusy 为真时至少显示一次 Lottie 动画?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆