1

I've created a control in Xamarin.Forms, allowing me to display a reusable error view, with ContentView and Lottie animations.

My view contains: the Lottie animation, 2 Labels (a title and a description) and a "Retry" Button.

The Lotie animation is set like this, cause I want that the animation is only displayed once:

<lottie:AnimationView
    x:Name="networkErrorAnimationView"
    Animation="resource://lottie_error_no_network.json?assembly=ShellAppSample"
    AnimationSource="EmbeddedResource"
    BackgroundColor="Transparent"
    AutoPlay="True"
    HeightRequest="200" WidthRequest="200"
    VerticalOptions="Center" HorizontalOptions="Center"
    Clicked="NetworkErrorAnimationView_Clicked"/>

The problem is that the animation is already played when I display the error control from the parent view:

<ctrl:ErrorView IsVisible="{Binding ShowErrorView, Converter={StaticResource BoolToVisibilityConverter}}"
                Title="{Binding ErrorTitle}"
                Description="{Binding ErrorDescription}"
                ErrorKind="{Binding ErrorKind}"
                RetryButtonCommand="{Binding RetryCommand}" />

I would like to know if there is a way to bind an event to the IsVisible property of the Control, to relaunch the corresponding animation at this moment?

Cfun
  • 8,442
  • 4
  • 30
  • 62
Gold.strike
  • 1,269
  • 13
  • 47
  • Could this be helpful? [How to bind animationview play with LottieForms in a MVVM architecture \[Xamarin forms\]?](https://stackoverflow.com/questions/52636061/how-to-bind-animationview-play-with-lottieforms-in-a-mvvm-architecture-xamarin) – Cfun Nov 09 '20 at 16:55
  • Hi @Cfun thank your for your suggestion. I think my issue is more related to the use of control/`ContentView` than to the `LottieAnimation` itself. I've already implemented a similar solution to display a loading view on the parent view as you can see [there](https://stackoverflow.com/questions/64704116/xamarin-forms-how-to-display-a-lottie-animation-at-least-one-time-when-isbusy-i). – Gold.strike Nov 09 '20 at 17:07

2 Answers2

2

You can add an property for your ctrl:ErrorView, then set the AutoPlay to false at the begining.

Here is ctrl:ErrorView's layout.

<ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:forms="clr-namespace:Lottie.Forms;assembly=Lottie.Forms" 
              x:Name="MyErrorView"
             x:Class="App13.ErrorView">
    <ContentView.Content>
      <StackLayout>
          

            <forms:AnimationView
                x:Name="animationView"
                Animation="1.json"
                AnimationSource="AssetOrBundle"
                RepeatCount="1"
                AutoPlay="False"
                WidthRequest="100"
                HeightRequest="100"/>
            <Label x:Name="title" Text="test" />
            <Label Text="Hello Xamarin.Forms!" />
        </StackLayout>
  </ContentView.Content>
</ContentView>

Here is ctrl:ErrorView's background code. Then I add IsStartAnimationView property. if the IsStartAnimationView's binding value to true. Then play the Animation.

   public partial class ErrorView : ContentView
    {

     

        public string TitleText
        {
            get { return (string)GetValue(TitleTextProperty); }
            set { SetValue(TitleTextProperty, value); }
        }
        public static readonly BindableProperty TitleTextProperty = BindableProperty.Create(
                                                          propertyName: "TitleText",
                                                          returnType: typeof(string),
                                                          declaringType: typeof(ErrorView),
                                                          defaultValue: "",
                                                          defaultBindingMode: BindingMode.TwoWay,
                                                          propertyChanged: TitleTextPropertyChanged);

        private static void TitleTextPropertyChanged(BindableObject bindable, object oldValue, object newValue)
        {
           // var control = (ErrorView)bindable;
          //  control.title.Text = newValue.ToString();
        }


        public bool IsStartAnimationView
        {
            get { return (bool)GetValue(IsStartAnimationViewProperty); }
            set { SetValue(IsStartAnimationViewProperty, value); }
        }
        public static readonly BindableProperty IsStartAnimationViewProperty = BindableProperty.Create(
                                                          propertyName: "IsStartAnimationView",
                                                          returnType: typeof(bool),
                                                          declaringType: typeof(ErrorView),
                                                          defaultValue: false,
                                                          defaultBindingMode: BindingMode.TwoWay,
                                                          propertyChanged: IsStartAnimationViewChanged);

        private static void IsStartAnimationViewChanged(BindableObject bindable, object oldValue, object newValue)
        {
            // throw new NotImplementedException();
            var MyValue =(bool) newValue;
            if (MyValue == true) {
                 var control = (ErrorView)bindable;
                  control.animationView.PlayAnimation();
            }

        }

        public ErrorView()
        {
            InitializeComponent();

            this.Content.BindingContext = this;
        }
    }
}

Use this control in the Contentpage.

 <ctrl:ErrorView IsVisible="{Binding Isfavourite}" TitleText="{Binding Name}" IsStartAnimationView="{Binding IsStart}" ></ctrl:ErrorView>

I use button click event to make a test.

 private async void Button_Clicked(object sender, System.EventArgs e)
        {
           
                 myViewModel.IsStart = !myViewModel.IsStart;
        }

Here is running gif.

enter image description here

Leon
  • 8,404
  • 2
  • 9
  • 52
  • If the reply is helpful, please accept it as answer(click the “✔” in the upper left corner of this answer), it will help others who have similar issue – Leon Nov 10 '20 at 06:13
  • 1
    Hi @Leon Lu, I've implemented a lighter solution that was given to me. Thank for your for your time. – Gold.strike Nov 10 '20 at 08:42
1

The solution was given to me on another forum. I just have to add this code in the control's code behind:

protected override void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
    base.OnPropertyChanged(propertyName);
    if (propertyName == nameof(IsVisible))
    {
        if (this.IsVisible)
        {
            networkErrorAnimationView.PlayAnimation();
        }
        else
        {
                networkErrorAnimationView.StopAnimation();
        }
    }
}
Gold.strike
  • 1,269
  • 13
  • 47
  • That’s same with my answer! Please see the answer carefully – Leon Nov 10 '20 at 12:55
  • @LeonLu-MSFT - IMHO, this answer is very DIFFERENT from (and much simpler than) your answer. Your answer requires an ADDED PROPERTY. This answer detects the standard Xamarin Forms `IsVisible` property change. – ToolmakerSteve Apr 19 '22 at 18:30