Quantcast
Channel: Xamarin.Forms — Xamarin Community Forums
Viewing all articles
Browse latest Browse all 89864

Number from/to animation

$
0
0

Hey there, everyone. I made a simple behavior which provides number from/to animation (e.g. counter). I'm sharing the code below for whoever needs it and I'm looking to some suggestions on how to improve this code :).

https://youtube.com/watch?v=3ciQWIaARN0

using System;
using System.Threading;
using System.Threading.Tasks;
using Xamarin.Forms;

namespace MyApp.Behaviors
{
    public class NumericLabelFromToBehavior : Behavior<Label>
    {
        public static readonly BindableProperty TextProperty =
            BindableProperty.Create(
                nameof(Text),
                typeof(double),
                typeof(LabelHighlightAndStepOnChangeBehavior),
                null,
                propertyChanged: OnTextPropertyChanged);

        public double Text
        {
            get { return (double)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }

        public Label AssociatedObject { get; private set; }

        private static CancellationTokenSource cancellationTokenSource;

        private static long currentValue = 0;

        private static void OnTextPropertyChanged(BindableObject bindable, object oldValue, object newValue)
        {
            var behavior = (NumericLabelFromToBehavior)bindable;
            if (behavior.AssociatedObject == null)
            {
                return;
            }
            cancellationTokenSource?.Cancel();
            cancellationTokenSource = new CancellationTokenSource();
            Task.Run(() => AnimateText(behavior.AssociatedObject, currentValue, newValue, cancellationTokenSource.Token), cancellationTokenSource.Token);
        }

        private static async void AnimateText(BindableObject bindable, object fromValue, object toValue, CancellationToken cancellationToken)
        {
            long.TryParse(fromValue.ToString(), out long initialValue);
            long.TryParse(toValue.ToString(), out long finalValue);

            if (initialValue < finalValue)
            {
                var step = Math.Max(1, Convert.ToInt32((finalValue - initialValue) / 50.0) - 1);
                while (initialValue < finalValue)
                {
                    if (cancellationToken.IsCancellationRequested)
                        break;

                    if ((initialValue + step) <= finalValue)
                        initialValue += step;
                    else
                        initialValue = finalValue;

                    currentValue = initialValue;

                    Device.BeginInvokeOnMainThread(() => (bindable as Label).Text = initialValue.ToString("C"));

                    await Task.Delay(50);
                }
            }
            else if (initialValue > finalValue)
            {
                var step = -Math.Max(1, Convert.ToInt32((initialValue - finalValue) / 50.0) - 1);
                while (initialValue > finalValue)
                {
                    if (cancellationToken.IsCancellationRequested)
                        break;

                    if ((initialValue + step) >= finalValue)
                        initialValue += step;
                    else
                        initialValue = finalValue;

                    currentValue = initialValue;

                    Device.BeginInvokeOnMainThread(() => (bindable as Label).Text = initialValue.ToString("C"));

                    await Task.Delay(50);
                }
            }
        }

        protected override void OnAttachedTo(Label bindable)
        {
            base.OnAttachedTo(bindable);
            AssociatedObject = bindable;

            if (bindable.BindingContext != null)
            {
                BindingContext = bindable.BindingContext;
            }

            bindable.BindingContextChanged += OnBindingContextChanged;
        }

        protected override void OnDetachingFrom(Label bindable)
        {
            base.OnDetachingFrom(bindable);
            bindable.BindingContextChanged -= OnBindingContextChanged;
            AssociatedObject = null;

            cancellationTokenSource.Dispose();
        }

        private void OnBindingContextChanged(object sender, EventArgs e)
        {
            OnBindingContextChanged();
        }

        protected override void OnBindingContextChanged()
        {
            base.OnBindingContextChanged();
            BindingContext = AssociatedObject.BindingContext;
        }
    }
}

Viewing all articles
Browse latest Browse all 89864

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>