How do I animate image on image click

zasah16zasah16 ZAMember ✭✭

Does anyone know how to animate inside a event handler for an image?

I used the following code to associate a event to the image:

        var tapImage = new TapGestureRecognizer();

         tapImage.Tapped += TapImage_Tapped;

        btn_print.GestureRecognizers.Add(tapImage);

The method TapImage_Image:
public void TapImage_Tapped(object sender, EventArgs e)

    {
        // handle the tap  

        btn_print.FadeTo(0.3, 10);



        btn_print.FadeTo(1, 500);

}

The animation does not show because there is no delay between the two animations. I can't add a thread delay and adding await to the method shows error that the return type of TapImage is not what is expected....

var tapImage = new TapGestureRecognizer();

         tapImage.Tapped += TapImage_TappedAsync;

        btn_print.GestureRecognizers.Add(tapImage);

public async Task TapImage_TappedAsync(object sender, EventArgs e)

    {
        // handle the tap  

        await btn_print.FadeTo(0.3, 10);


        await btn_print.FadeTo(1, 500);

}

Any ideas would be great!

Posts

  • zasah16zasah16 ZAMember ✭✭

    Thanks so much Sean!!

    Why would an anonymous function work as apposed to my async Function?

    thanks,

  • seanydaseanyda GBMember ✭✭✭✭✭

    @zasah16 said:
    Thanks so much Sean!!

    Why would an anonymous function work as apposed to my async Function?

    thanks,

    Hmm I'm not sure. I've just tested this, and it works too. I think it might have been the amount of MS that was being used to be honest. 10ms would be unnoticeable to the human eye, I think it was the fact I've tweaked it to 500 that the animation is now working.

    The below also works for me.

    async void AnimationTap_Tapped(object sender, EventArgs e)
            {
                await profileInfo.FadeTo(0.3, 500);
                await profileInfo.FadeTo(1, 500);
            }
    
  • zasah16zasah16 ZAMember ✭✭

    I see the difference. My method definition:

    public async Task TapImage_TappedAsync(object sender, EventArgs e)

    yours:
    async void AnimationTap_Tapped(object sender, EventArgs e)

  • zasah16zasah16 ZAMember ✭✭
    edited October 2017

    OK, I this worked but if when I clicked on the image quickly in succession, an exception was fired.

    I had to add debouncing to the function to stop the user from firing event before animation had finished:

    async void TapImage_Tapped(object sender, EventArgs e)

        {
            if (!isClicked)
            {
                isClicked = true;
    
        isIn = !isIn;
    
                await btn_print.FadeTo(0.3, 150);
                await btn_print.FadeTo(1, 150);
    
                InOutIcon.Source = (isIn) ? "bagfilledwhite.png" : "sleepingwhite.png";
    
                isClicked = false;
    
            }
    
    
    
        }
    

    Thanks again for your help Sean!

  • zasah16zasah16 ZAMember ✭✭

    Now to add a click sound...

  • DanielLDanielL PLInsider ✭✭✭✭

    I would recommend using Behaviors for thing like that:

    public class ViewTappedButtonBehavior : Behavior<View>
    {
        protected override void OnAttachedTo(View bindable)
        {
            var exists = bindable.GestureRecognizers.FirstOrDefault() as TapGestureRecognizer;
    
            if (exists != null)
                exists.Tapped += View_Tapped;
    
            base.OnAttachedTo(bindable);
        }
    
        protected override void OnDetachingFrom(View bindable)
        {
            var exists = bindable.GestureRecognizers.FirstOrDefault() as TapGestureRecognizer;
    
            if (exists != null)
                exists.Tapped -= View_Tapped;
    
            base.OnDetachingFrom(bindable);
        }
    
        bool _isAnimating = false;
    
        void View_Tapped(object sender, EventArgs e)
        {
            if (_isAnimating)
                return;
    
            _isAnimating = true;
    
            var view = (View)sender;
    
            Device.BeginInvokeOnMainThread(async () =>
            {
                try
                {
                    Color oldColor = default(Color);
                    var labelView = sender as Label;
                    if (labelView != null)
                    {
                        oldColor = labelView.TextColor;
                        labelView.TextColor = Color.Black;
                    }
    
                    await view.ScaleTo(0.85d, Configuration.ClickFadeDuration/2, Easing.SinIn);
                    await view.ScaleTo(1d, Configuration.ClickFadeDuration / 2, Easing.SinIn);
    
                    if (labelView != null)
                    {
                        labelView.TextColor = oldColor;
                    }
                }
                finally
                {
                    _isAnimating = false;
                }
            });
        }
    }
    

    Then use it like that:

    <Image Source="image.png">
        <Frame.GestureRecognizers>
            <TapGestureRecognizer Command="{Binding CustomCommand}"/>
        </Frame.GestureRecognizers>
        <Image.Behaviors>
            <local:ViewTappedButtonBehavior/>
        </Image.Behaviors>
    </Image>
    
  • zasah16zasah16 ZAMember ✭✭

    Thanks Daniel, I'm new to Xamarin so I will have to take some time to work out how your code works. Thanks for the info, will try it out.

  • DanielLDanielL PLInsider ✭✭✭✭
    edited October 2017

    Just noticed a minor typo, should be:

    <Image Source="image.png">
        <Image.GestureRecognizers>
            <TapGestureRecognizer Command="{Binding CustomCommand}"/>
        </Image.GestureRecognizers>
        <Image.Behaviors>
            <local:ViewTappedButtonBehavior/>
        </Image.Behaviors>
    </Image>
    
Sign In or Register to comment.