Avalonia for mobile

Avalonia draws every control itself on iOS and Android, so the phone build comes out of the same project, and the same XAML, as the desktop one.

Platform support

iOS and Android out of the project you already ship.

Mobile is a target on the same Avalonia project rather than a separate product. The views, the view models, the styles and the custom controls are the ones your desktop build already uses.

Windowing

Native iOS and Android integration

One Avalonia view hosted by each platform, not a web view.

Rendering

Skia, on the device GPU

Every control is drawn by Avalonia, so it matches your desktop build.

Architectures

ARM64, ARM32 and x64

iOS is ARM64; Android adds ARM32 and x64 for emulators.

Runtime

.NET 10.0

Mobile follows the .NET MAUI support lifecycle for OS versions.

Drawn by Avalonia

Every pixel here is ours. None of it is a native widget.

These are Avalonia views running on a phone. The controls aren’t UIKit or Android widgets with a .NET wrapper around them, which is why the same XAML produces the same result on both operating systems and on the desktop.

An Avalonia mobile interface showing a list view with rich cells
An Avalonia mobile interface showing a detail screen with imagery and controls
An Avalonia mobile interface showing a data and chart screen

How it works

Avalonia doesn’t wrap the native toolkits. It replaces them.

Both paths below start with your code and end at the same GPU, and they differ on exactly one row.

Your code

The framework

What draws a button

The device

Wrapping a native toolkit

XAML and view models
An abstraction over both
UIKit
Android widgets
GPU

Two widget sets to keep in step, and a shim whose job is hiding the differences between them.

Avalonia

XAML and view models
Avalonia
Skia
GPU

One widget set, drawn by us, identical on both operating systems and on the desktop.

Only the third row differs. A wrapped toolkit has to answer “what draws a button” twice and reconcile the two answers forever; every OS release adds to that list. Avalonia answers it once, which is why a fix on the desktop is a fix on the phone.

Design

Your brand, at full strength, on both stores.

Because Avalonia owns every pixel, a colour, a corner radius or an animation curve lands the way the design team specified it, on both operating systems, without a per-platform theming API standing in the way.

A single style set covers iOS, Android and the desktop. Changing the design system is a commit rather than a sprint of platform-by-platform re-skinning, and the screenshots in the app store match the screenshots in the desktop release notes because they came out of the same renderer.

Two screens of one Avalonia phone application: an account overview with balance and transactions, and a settings screen with brightness, dark mode and text size controls
Two screens of one Avalonia application, styled entirely from the project’s own resources.

Native to the phone

Drawing your own controls doesn’t mean ignoring the device.

A phone has opinions about notches, back gestures, deep links and what belongs in front of what. Avalonia gives you the hooks for all of them, on both operating systems, from the same code.

var insets = TopLevel.GetTopLevel(this)!.InsetsManager!;
insets.DisplayEdgeToEdge = true;
insets.SafeAreaChanged += (_, e) =>
    Root.Padding = e.SafeAreaPadding;

Notches, home bars, and edge-to-edge

Since 11.1 Avalonia pads the root view to the safe area on its own, so the default is already correct. When you want the layout to run under the status bar, InsetsManager hands you edge-to-edge display and tells you where the unsafe regions are as they change; TopLevel.AutoSafeAreaPadding turns the automatic behaviour off.

lifetime.Activated += (_, e) =>
{
    if (e is ProtocolActivatedEventArgs { Kind: ActivationKind.OpenUri } p)
        Router.Navigate(p.Uri);
};

Deep links and universal links

Register a scheme in Info.plist or the Android manifest and IActivatableLifetime.Activated delivers the URI, so a link from an email opens the right screen instead of the launch screen.

protected override IPlatformHandle CreateNativeControlCore(
    IPlatformHandle parent)
{
    var web = new WebView(((AndroidViewControlHandle)parent).View.Context);
    return new AndroidViewControlHandle(web);
}

The controls we don’t draw

A WebView, a MapView or a platform media player has no Avalonia equivalent and shouldn’t have one. NativeControlHost hosts the real native view inside your layout, wrapped in a platform handle.

Where native views stop

Worth knowing before you design around one: an embedded native view always renders on top of the Avalonia surface, takes no transforms and no transparency, and can’t have Avalonia controls overlaid on it. Plan the screen so nothing needs to float above it.

One app, three Apple targets

The same project builds for iOS, for iPadOS, and for macOS through Mac Catalyst on net10.0-maccatalyst, which is a second route onto the Mac alongside the native desktop backend.

dotnet workload install android ios

The prerequisites are the .NET ones

The Android and iOS workloads, a JDK for Android, and Xcode for provisioning a physical device. These are Microsoft’s mobile prerequisites rather than a parallel set of ours, so a team already shipping .NET mobile has them installed.

New in 12

Scene-based lifecycle

Avalonia 12 adopts the scene-based lifecycle on iOS, which is what modern iPadOS multitasking and state restoration are built on, rather than the legacy single-window assumptions.

Setup, provisioning and store submission are documented for both platforms.

Android and iOS guides

Getting it shipped

The build and store path is the .NET one.

Avalonia mobile builds are ordinary .NET mobile builds, so the toolchain, the signing and the store submission are the ones Microsoft documents rather than ones we invented.

ipa, apk and aab

Standard output for both stores, produced by the same .NET mobile tooling that builds your desktop app.

Simulators and devices

Run and debug on a simulator or a physical device from Rider, Visual Studio or VS Code, with breakpoints through async code.

Reuse MAUI packages

MAUI-compatible packages can be hosted inside an Avalonia view, so you keep the existing MAUI component ecosystem instead of losing it.

Follows the .NET lifecycle

Mobile OS support tracks the .NET MAUI support policy, so the versions we keep working are the versions Microsoft keeps working.

Worth knowing up front

Mobile is the youngest of Avalonia’s targets. The rendering engine and tooling are the same ones desktop already ships with, but the third-party control ecosystem is deeper there than on phones.

The mobile templates install with the same SDK as the desktop ones, so trying it costs an afternoon rather than a decision.

Start a mobile project

Every target

Phones are two targets of six.

A team that builds a desktop application in Avalonia already has most of a mobile application, and the reverse holds too. The shared part is the part you wrote.

Add the phone build your design system already supports.

The mobile templates install with the same .NET SDK as the desktop ones. Build the iOS and Android heads from your existing solution and see how much of it you already had.