Setting page transitions
Page transitions animate between two views. You typically use them with controls such as TransitioningContentControl or Carousel. Avalonia provides two built-in transitions and the ability to combine or create your own.
To assign a transition, set the PageTransition property on the host control:
<TransitioningContentControl PageTransition="{StaticResource MyTransition}"
Content="{Binding CurrentPage}" />
CrossFade
CrossFade fades out the current view and fades in the new view by animating opacity. This is a good default choice when you want a subtle, non-directional transition that works well for any content.
<CrossFade Duration="0:00:00.500" />
var transition = new CrossFade(TimeSpan.FromMilliseconds(500));
CrossFade works well for tab-style navigation where there is no inherent forward/back direction. If your views have very different heights, a crossfade avoids the jarring jump that a slide can produce.
PageSlide
PageSlide slides the old view out and the new view in. The Orientation property controls the slide axis (the default is horizontal). This transition conveys directional navigation, making it ideal for wizard-style flows or sequential pages.
<PageSlide Duration="0:00:00.500" Orientation="Vertical" />
var transition = new PageSlide(TimeSpan.FromMilliseconds(500),
PageSlide.SlideAxis.Vertical);
The forward parameter passed to the transition controls the slide direction. When you navigate backward (for example, pressing a "Back" button), set the parameter to false so the slide direction reverses automatically.
CompositePageTransition
CompositePageTransition combines two or more transitions into a single effect. Every child transition runs in parallel. The following example slides views diagonally (horizontal and vertical slide combined) while also crossfading:
<CompositePageTransition>
<CrossFade Duration="0:00:00.500" />
<PageSlide Duration="0:00:00.500" Orientation="Horizontal" />
<PageSlide Duration="0:00:00.500" Orientation="Vertical" />
</CompositePageTransition>
var transition = new CompositePageTransition();
transition.PageTransitions.Add(new CrossFade(TimeSpan.FromMilliseconds(500)));
transition.PageTransitions.Add(new PageSlide(TimeSpan.FromMilliseconds(500),
PageSlide.SlideAxis.Horizontal));
transition.PageTransitions.Add(new PageSlide(TimeSpan.FromMilliseconds(500),
PageSlide.SlideAxis.Vertical));
Keep the Duration values consistent across child transitions so they start and finish together. Mismatched durations can cause visual artifacts where one transition completes before the other.
Choosing the right transition
| Transition | Best for | Notes |
|---|---|---|
CrossFade | Tabs, settings panels, content that changes in place | Subtle, non-directional |
PageSlide (horizontal) | Wizard steps, forward/back navigation | Conveys sequential flow |
PageSlide (vertical) | Expanding sections, drill-down navigation | Suggests hierarchy |
CompositePageTransition | Rich, layered effects | Combine any of the above |
Custom page transitions
When the built-in transitions do not match your design, you can implement the IPageTransition interface to create your own. The interface has a single method:
public Task Start(Visual? from, Visual? to, bool forward,
CancellationToken cancellationToken)
{
// Animate from the old view (from) to the new view (to).
}
The from and to parameters can be null (for example, when the control first loads there is no outgoing view). The forward parameter indicates the navigation direction so you can reverse your animation accordingly. Always respect the cancellationToken to allow Avalonia to cancel the transition if the user navigates again before it completes.
The following example shrinks the old view vertically, then expands the new view:
using Avalonia.VisualTree;
public class CustomTransition : IPageTransition
{
public CustomTransition() { }
public CustomTransition(TimeSpan duration)
{
Duration = duration;
}
public TimeSpan Duration { get; set; }
public async Task Start(Visual from, Visual to, bool forward,
CancellationToken cancellationToken)
{
if (cancellationToken.IsCancellationRequested)
{
return;
}
var tasks = new List<Task>();
var scaleYProperty = ScaleTransform.ScaleYProperty;
if (from != null)
{
var animation = new Animation
{
FillMode = FillMode.Forward,
Children =
{
new KeyFrame
{
Setters = { new Setter { Property = scaleYProperty, Value = 1d } },
Cue = new Cue(0d)
},
new KeyFrame
{
Setters = { new Setter { Property = scaleYProperty, Value = 0d } },
Cue = new Cue(1d)
}
},
Duration = Duration
};
tasks.Add(animation.RunAsync(from, cancellationToken));
}
if (to != null)
{
to.IsVisible = true;
var animation = new Animation
{
FillMode = FillMode.Forward,
Children =
{
new KeyFrame
{
Setters = { new Setter { Property = scaleYProperty, Value = 0d } },
Cue = new Cue(0d)
},
new KeyFrame
{
Setters = { new Setter { Property = scaleYProperty, Value = 1d } },
Cue = new Cue(1d)
}
},
Duration = Duration
};
tasks.Add(animation.RunAsync(to, cancellationToken));
}
await Task.WhenAll(tasks);
if (from != null && !cancellationToken.IsCancellationRequested)
{
from.IsVisible = false;
}
}
}
See also
- Animations: Overview of animation types in Avalonia.
- Keyframe animations: Multi-step keyframe animations.
- Control transitions: Animating property changes.
- Navigate between views: Common patterns for switching between views.