
Maui Animations
- 38 installs
- 163 repo stars
- Updated July 6, 2026
- davidortinau/maui-skills
Implements .NET MAUI view animations including custom animations, easing functions, rotation, scale, translation, and fade effects.
About
Covers .NET MAUI view animations, custom animations, easing functions, and rotation, scale, translation and fade effects. A developer uses it when adding motion and animated effects to a MAUI UI.
- View animations with easing functions
- Rotation, scale, translation, and fade effects
Maui Animations by the numbers
- 38 all-time installs (skills.sh)
- Ranked #641 of 1,039 Mobile Development skills by installs in the Skillselion catalog
- Data as of Aug 3, 2026 (Skillselion catalog sync)
npx skills add https://github.com/davidortinau/maui-skills --skill maui-animationsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 38 |
|---|---|
| repo stars | ★ 163 |
| Last updated | July 6, 2026 |
| Repository | davidortinau/maui-skills ↗ |
What it does
Implements .NET MAUI view animations including custom animations, easing functions, rotation, scale, translation, and fade effects.
Files
.NET MAUI Animations
Common Mistakes
❌ Forgetting to cancel before starting new animations
Running multiple animations on the same property causes visual glitches.
// ❌ If called rapidly, animations queue and overlap
async void OnButtonClicked()
{
await view.FadeTo(0, 500);
await view.FadeTo(1, 500);
}
// ✅ Cancel first, then animate
async void OnButtonClicked()
{
view.CancelAnimations();
await view.FadeTo(0, 500);
await view.FadeTo(1, 500);
}❌ Custom Animation repeat callback misconception
Returning true from a child animation's repeat callback does NOT repeat the parent. Only the repeat callback passed to Commit on the parent controls parent repetition.
// ❌ This does NOT loop the parent animation
parent.Add(0.0, 1.0, new Animation(v => view.Scale = v, 1, 2));
parent.Commit(view, "MyAnim", length: 1000,
repeat: () => false); // Parent won't loop
// ✅ Loop the parent by passing repeat to Commit
parent.Commit(view, "MyAnim", length: 1000,
repeat: () => true); // This loops the entire animation❌ AbortAnimation name mismatch
AbortAnimation("name") must match the exact string passed to Commit. A mismatch silently does nothing.
// ❌ Name mismatch — animation keeps running
parent.Commit(view, name: "MyAnimation", length: 1000);
view.AbortAnimation("myAnimation"); // Wrong case!
// ✅ Use a constant for the name
const string AnimName = "MyAnimation";
parent.Commit(view, name: AnimName, length: 1000);
view.AbortAnimation(AnimName);Accessibility: Respect Reduced Motion
Always check IsAnimationEnabled before running animations. It is false when the OS power-save / reduced-motion mode is active.
// ❌ Ignores user's accessibility preference
await view.FadeTo(1, 500);
// ✅ Respects reduced-motion settings
if (view.IsAnimationEnabled)
await view.FadeTo(1, 500);
else
view.Opacity = 1; // Jump to final state instantlyPerformance Tips
- Keep animation callbacks under 16ms — the default
rate: 16inCommitis one frame at 60fps. Complex callbacks cause jank. - Avoid animating layout-triggering properties (
WidthRequest,HeightRequest) — useTranslationX/YandScaleinstead. - Use `Task.WhenAll` for parallel animations — sequential
awaitchains are slower.
// ❌ Sequential — takes 1500ms total
await view.FadeTo(1, 500);
await view.ScaleTo(1.5, 500);
await view.RotateTo(360, 500);
// ✅ Parallel — takes 500ms total
await Task.WhenAll(
view.FadeTo(1, 500),
view.ScaleTo(1.5, 500),
view.RotateTo(360, 500));Easing Selection Guide
| Goal | Easing | Why |
|---|---|---|
| Button feedback | CubicOut | Quick deceleration feels responsive |
| Page transitions | CubicInOut | Smooth start and end |
| Bouncing elements | BounceOut | Playful, attention-grabbing |
| Spring effects | SpringOut | Natural, elastic feel |
| Loading indicators | Linear | Constant speed for continuous motion |
| Entry/exit | SinIn / SinOut | Subtle, non-distracting |
.NET MAUI Animations — API Reference
Built-in ViewExtensions
All animation methods are extension methods on VisualElement and return Task<bool> for await chaining.
| Method | Description |
|---|---|
FadeTo(opacity, length, easing) | Animate Opacity |
RotateTo(degrees, length, easing) | Animate Rotation |
RotateXTo(degrees, length, easing) | Animate RotationX (3D) |
RotateYTo(degrees, length, easing) | Animate RotationY (3D) |
ScaleTo(scale, length, easing) | Animate Scale uniformly |
ScaleXTo(scale, length, easing) | Animate ScaleX |
ScaleYTo(scale, length, easing) | Animate ScaleY |
TranslateTo(x, y, length, easing) | Animate TranslationX/TranslationY |
RelScaleTo(delta, length, easing) | Relative scale increment |
RelRotateTo(delta, length, easing) | Relative rotation increment |
lengthdefaults to 250 ms.easingdefaults toEasing.Linear.- Call
view.CancelAnimations()to stop all running animations on that view.
Composite Animations
// Parallel – all run at the same time
await Task.WhenAll(
view.FadeTo(1, 500),
view.ScaleTo(1.5, 500),
view.RotateTo(360, 500));
// Sequential – one after the other
await view.FadeTo(0, 250);
await view.TranslateTo(100, 0, 500);
await view.FadeTo(1, 250);Custom Animation Class
Use Animation for fine-grained control with child animations and timing ratios.
var parent = new Animation();
// Child animations with begin/end ratios (0.0–1.0)
parent.Add(0.0, 0.5, new Animation(v => view.Opacity = v, 0, 1));
parent.Add(0.5, 1.0, new Animation(v => view.Scale = v, 1, 2, Easing.SpringOut));
// Commit to run
parent.Commit(
owner: view,
name: "MyAnimation",
rate: 16, // ms per frame
length: 1000, // total duration ms
easing: Easing.Linear,
finished: (v, cancelled) => { /* cleanup */ },
repeat: () => false); // return true to loopConstructor
new Animation(
callback: v => view.Scale = v, // Action<double>
start: 0.0,
end: 1.0,
easing: Easing.CubicInOut);Cancelling
view.AbortAnimation("MyAnimation");AnimationExtensions.Animate
Animate any property on any object:
view.Animate<double>(
name: "opacity",
transform: v => v, // Func<double, T>
callback: v => view.Opacity = v,
rate: 16,
length: 500,
easing: Easing.SinInOut,
finished: (v, cancelled) => { });Easing Functions
| Easing | Curve |
|---|---|
Easing.Linear | Constant speed |
Easing.SinIn | Smooth accelerate |
Easing.SinOut | Smooth decelerate |
Easing.SinInOut | Smooth both |
Easing.CubicIn | Sharp accelerate |
Easing.CubicOut | Sharp decelerate |
Easing.CubicInOut | Sharp both |
Easing.BounceIn | Bounce at start |
Easing.BounceOut | Bounce at end |
Easing.SpringIn | Spring at start |
Easing.SpringOut | Spring at end |
Custom Easing
var customEase = new Easing(t => t * t * t);
await view.ScaleTo(2, 500, customEase);