{"id":27049,"date":"2016-08-09T12:09:02","date_gmt":"2016-08-09T19:09:02","guid":{"rendered":"https:\/\/blog.xamarin.com\/?p=27049"},"modified":"2019-04-04T09:03:34","modified_gmt":"2019-04-04T16:03:34","slug":"building-custom-animations-in-xamarin-forms","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/xamarin\/building-custom-animations-in-xamarin-forms\/","title":{"rendered":"Building Custom Animations in Xamarin.Forms"},"content":{"rendered":"<p>\t\t\t\tXamarin.Forms includes its own animation infrastructure that allows for easy creation of simple animations, while also being versatile enough to create complex animations.\u00a0Previously, we <a href=\"https:\/\/blog.xamarin.com\/creating-animations-with-xamarin-forms\/\" target=\"_blank\">explored creating and cancelling animations using the <code>ViewExtensions<\/code> class<\/a>, and saw it in action in an app.<\/p>\n<p>In this blog post, I\u2019ll explore using the <code>Animation<\/code> class to create and cancel animations, synchronize multiple animations, and create custom animations that animate properties that aren\u2019t animated by the existing animation methods.\u00a0The <code>Animation<\/code> class is the building block of all Xamarin.Forms animations, with the animation methods in the <code>ViewExtensions<\/code> class, creating one or more <code>Animation<\/code> objects.<\/p>\n<h2>Introduction to the Animations Class<\/h2>\n<p>A number of parameters must be specified when creating an <code>Animation<\/code> object, including start and end values of the property being animated, and a callback that changes the value of the property. The following code example demonstrates creating an <code>Animation<\/code> object:<\/p>\n<pre class=\"lang:c# decode:true \" title=\"Animation object\">var animation = new Animation (v =&gt; image.Scale = v, 1, 2);<\/pre>\n<p>This code defines an animation of the <code>Scale<\/code> property of an <code>Image<\/code> instance from a value of 1 to a value of 2. The animated value, which is derived by Xamarin.Forms, is passed to the callback specified as the first argument, where it&#8217;s used to change the value of the <code>Scale<\/code> property.<\/p>\n<p>Running an animation created with the <code>Animation<\/code> class is achieved by calling the <code>Commit<\/code> method, as demonstrated in the following code example:<\/p>\n<pre class=\"lang:c# decode:true \" title=\"Running an animation\">animation.Commit (this, \"SimpleAnimation\", 16, 2000, Easing.Linear, (v, c) =&gt; image.Scale = 1, () =&gt; true);<\/pre>\n<p>This method specifies the duration of the animation, and amongst other items, a callback that controls whether to repeat the animation. Note that the <code>Commit<\/code> method does not return a <code>Task<\/code> object. Instead, notifications are provided through callback methods.<\/p>\n<p>The overall effect is to create an animation that increases the <code>Scale<\/code> property of an <code>Image<\/code> from 1 to 2, over 2 seconds (2000 milliseconds), using the <code>Linear<\/code> easing function. Each time the animation completes, its <code>Scale<\/code> property is reset to 1 and the animation repeats.<\/p>\n<h2>Cancelling an Animation<\/h2>\n<p>An application can cancel an animation with a call to the <code>AbortAnimation<\/code> extension method, as demonstrated in the following code example:<\/p>\n<pre class=\"lang:c# decode:true \" title=\"Animation cancellation\">this.AbortAnimation (\"SimpleAnimation\");<\/pre>\n<p>Note that animations are uniquely identified by a combination of the animation owner and the animation name. Therefore, the owner and name specified when running the animation must be used\u00a0to cancel the animation. Thehe code example will then immediately cancel the animation named <code>SimpleAnimation<\/code> that&#8217;s owned by the page.<\/p>\n<h2>Synchronizing Multiple Animations<\/h2>\n<p>The <code>Animation<\/code> class also supports child animations, which involves creating an <code>Animation<\/code> object to which other <code>Animation<\/code> objects are added. This enables a series of animations to be run and synchronized. The following code example from the <a href=\"https:\/\/developer.xamarin.com\/samples\/xamarin-forms\/UserInterface\/Animation\/Custom\/\">sample application<\/a> demonstrates creating and running child animations:<\/p>\n<pre class=\"lang:c# decode:true \" title=\"Animation synchronisation\">var parentAnimation = new Animation ();\nvar scaleUpAnimation = new Animation (v =&gt; image.Scale = v, 1, 2, Easing.SpringIn);\nvar rotateAnimation = new Animation (v =&gt; image.Rotation = v, 0, 360);\nvar scaleDownAnimation = new Animation (v =&gt; image.Scale = v, 2, 1, Easing.SpringOut);\n\n\nparentAnimation.Add (0, 0.5, scaleUpAnimation);\nparentAnimation.Add (0, 1, rotateAnimation);\nparentAnimation.Add (0.5, 1, scaleDownAnimation);\n\nparentAnimation.Commit (this, \"ChildAnimations\", 16, 4000, null, (v, c) =&gt; SetIsEnabledButtonState (true, false));<\/pre>\n<p>This code creates a parent <code>Animation<\/code> object to which additional <code>Animation<\/code> objects are then added. The first two arguments to the <code>Add<\/code> method specify when to begin and finish the child animation. The argument values must be between 0 and 1 and represent the relative period within the parent animation that the specified child animation will be active. In this example the\u00a0<code>scaleUpAnimation<\/code> will be active for the first half of the animation, the <code>scaleDownAnimation<\/code> will be active for the second half of the animation, and the <code>rotateAnimation<\/code> will be active for the entire duration.<\/p>\n<p>The overall effect is that the animation occurs over 4 seconds (4000 milliseconds). The <code>scaleUpAnimation<\/code> animates the <code>Scale<\/code> property from 1 to 2 over 2 seconds. The <code>scaleDownAnimation<\/code> then animates the <code>Scale<\/code> property from 2 to 1 over 2 seconds. While both scale animations are occurring, the <code>rotateAnimation<\/code> animates the <code>Rotation<\/code> property from 0 to 360 over 4 seconds. Note that the scaling animations also use easing functions.<\/p>\n<h2>Creating a Custom Animation<\/h2>\n<p>The advantage of the <code>Animation<\/code> class is that it has access to the callback method that&#8217;s executed when the animated value changes. This allows the callback to implement any desired animation. For example, a <code>ColorTo<\/code> extension method can be created that animates a color from one value to another by using a callback method that\u00a0passes the interpolated <code>Color<\/code> value back to the caller.\u00a0The following code example from the <a href=\"https:\/\/developer.xamarin.com\/samples\/xamarin-forms\/UserInterface\/Animation\/Custom\/\">sample application<\/a> shows the code for the <code>ColorTo<\/code> method:<\/p>\n<pre class=\"lang:c# decode:true\" title=\"ColorTo method\">public static class ViewExtensions\n{\n\u00a0 public static Task&lt;bool&gt; ColorTo(this VisualElement self, Color fromColor, Color toColor, Action&lt;Color&gt; callback, uint length = 250, Easing easing = null)\n\u00a0 {\n\u00a0\u00a0\u00a0 Func&lt;double, Color&gt; transform = (t) =&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0 Color.FromRgba(fromColor.R + t * (toColor.R - fromColor.R),\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 fromColor.G + t * (toColor.G - fromColor.G),\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 fromColor.B + t * (toColor.B - fromColor.B),\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 fromColor.A + t * (toColor.A - fromColor.A));\n\n\u00a0\u00a0\u00a0 return ColorAnimation(self, \"ColorTo\", transform, callback, length, easing);\n\u00a0 }\n\n\u00a0 public static void CancelAnimation(this VisualElement self)\n\u00a0 {\n\u00a0\u00a0\u00a0 self.AbortAnimation(\"ColorTo\");\n\u00a0 }\n\n\u00a0 static Task&lt;bool&gt; ColorAnimation(VisualElement element, string name, Func&lt;double, Color&gt; transform, Action&lt;Color&gt; callback, uint length, Easing easing)\n\u00a0 {\n\u00a0\u00a0\u00a0 easing = easing ?? Easing.Linear;\n\u00a0\u00a0\u00a0 var taskCompletionSource = new TaskCompletionSource&lt;bool&gt;();\n\n\u00a0\u00a0\u00a0 element.Animate&lt;Color&gt;(name, transform, callback, 16, length, easing, (v, c) =&gt; taskCompletionSource.SetResult(c));\n\n\u00a0\u00a0\u00a0 return taskCompletionSource.Task;\n\u00a0 }\n}<\/pre>\n<p>The <code>Animate<\/code> method requires a transform argument, which is a callback method. The input to this callback is always a double ranging from 0 to 1. Thus, the <code>ColorTo<\/code> method defines its own transform <code>Func<\/code> that accepts a double ranging from 0 to 1 and that returns a <code>Color<\/code> value corresponding to that value. The <code>Color<\/code> value is calculated by interpolating the <code>R<\/code>, <code>G<\/code>, <code>B<\/code>, and <code>A<\/code> values of the two supplied <code>Color<\/code> arguments. The <code>Color<\/code> value is then passed to the callback method for application to a particular property.<\/p>\n<p>This approach allows the <code>ColorTo<\/code> method to animate any <code>Color<\/code> property, as demonstrated in the following code example from the <a href=\"https:\/\/developer.xamarin.com\/samples\/xamarin-forms\/UserInterface\/Animation\/Custom\/\">sample application<\/a>:<\/p>\n<pre class=\"lang:c# decode:true\" title=\"Using the ColorTo method\">await Task.WhenAll(\n\u00a0 label.ColorTo(Color.Red, Color.Blue, c =&gt; label.TextColor = c, 5000),\n\u00a0 label.ColorTo(Color.Blue, Color.Red, c =&gt; label.BackgroundColor = c, 5000));\n\nawait this.ColorTo(Color.FromRgb(0, 0, 0), Color.FromRgb(255, 255, 255), c =&gt; BackgroundColor = c, 5000);\nawait boxView.ColorTo(Color.Blue, Color.Red, c =&gt; boxView.Color = c, 4000);<\/pre>\n<p>In this example, the <code>ColorTo<\/code> method animates the <code>TextColor<\/code> and <code>BackgroundColor<\/code> properties of a <code>Label<\/code>, the <code>BackgroundColor<\/code> property of a <code>Page<\/code>, and the <code>Color<\/code> property of a <code>BoxView<\/code>.<\/p>\n<h2>Wrapping Up<\/h2>\n<p>The <code>Animation<\/code> class is the building block of all Xamarin.Forms animations and can be used to create and cancel animations, synchronize multiple animations, and create custom animations that animate properties that aren&#8217;t animated by the existing animation methods. For more information, see <a href=\"https:\/\/developer.xamarin.com\/guides\/xamarin-forms\/user-interface\/animation\/custom\/\">Custom Animations<\/a>.\t\t<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Xamarin.Forms includes its own animation infrastructure that allows for easy creation of simple animations, while also being versatile enough to create complex animations.\u00a0Previously, we explored creating and cancelling animations using the ViewExtensions class, and saw it in action in an app. In this blog post, I\u2019ll explore using the Animation class to create and cancel [&hellip;]<\/p>\n","protected":false},"author":543,"featured_media":39167,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[2],"tags":[4,16],"class_list":["post-27049","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-developers","tag-xamarin-platform","tag-xamarin-forms"],"acf":[],"blog_post_summary":"<p>Xamarin.Forms includes its own animation infrastructure that allows for easy creation of simple animations, while also being versatile enough to create complex animations.\u00a0Previously, we explored creating and cancelling animations using the ViewExtensions class, and saw it in action in an app. In this blog post, I\u2019ll explore using the Animation class to create and cancel [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/27049","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/users\/543"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/comments?post=27049"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/27049\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/media\/39167"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/media?parent=27049"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/categories?post=27049"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/tags?post=27049"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}