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

问题描述

在我的Xamarin.Forms项目上,我要在API调用加载网站WebView期间显示Lottie动画

为此,我已将Lottie动画IsVisible属性绑定到我的视图模型IsBusy属性:这很好用。

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

但加载持续时间有时很短,因此我希望找到一种方法在隐藏Lottie动画之前将其完全显示一次

有可能吗?实现这一目标的更好方法是什么?

推荐答案

我找到了另一种有效的方法,即使此解决方案有点笨重并且可以改进。

首先,按照推荐there,我已经创建了2Triggers

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,如所述的there

之后,我可以使用Lottie动画,如下所示:

<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中,我声明了一个与IsBusyOnFinishedAnimationCommand命令相关的属性ShowAnimation,如下所示:

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

如果加载器WebView相关,则ShowLoadingView属性设置如下:

private Task WebViewNavigatingAsync(WebNavigatingEventArgs eventArgs)
{
    IsBusy = true;
    ShowLoadingView = true;
    return Task.CompletedTask;
}

private async Task WebViewNavigatedAsync(WebNavigatedEventArgs eventArgs)
{
    IsBusy = false;
}

但是,如果出现问题(超时、无法访问服务器等...),我还会显示错误视图和一个重新加载/重试按钮,我必须添加一些代码:

private async Task WebViewNavigatedAsync(WebNavigatedEventArgs eventArgs)
{
    IsBusy = false;
    // for display loading animation on Refresh
    while (ShowLoadingView)
        await Task.Delay(50);
    SetServiceError();
}

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

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()的调用修复了这个问题:

private async Task OnFinishedAnimation(object sender)
{
    var view = sender as AnimationView;
    if (IsBusy)
    {
        view.PlayAnimation();
    }
    else
    {
        ShowLoadingView = false;
        // fix SetServiceError() call issue
        await SetServiceError();
    }
}

请毫不犹豫地告诉我们可以做些什么来优化这一点。

这篇关于在数据加载过程中,当IsBusy为True时,如何至少显示一次Lottie动画?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

11-03 12:57