Skip to main content
Avalonia enables you to build native mobile applications for iOS and Android using the same codebase as your desktop applications.

Supported Platforms

iOS

iPhone, iPad, and tvOS support with Metal and OpenGL rendering

Android

Android phones and tablets with Vulkan and OpenGL rendering

iOS Support

Platform Requirements

  • Minimum Version: iOS 10.0+
  • Development: Requires macOS and Xcode
  • Architectures: ARM64 (arm64), ARM64 simulator
  • Devices: iPhone, iPad, iPod Touch
  • Other: tvOS support available

iOS Configuration

Configure your iOS application in AppDelegate.cs:
using Avalonia;
using Avalonia.iOS;
using Foundation;
using UIKit;

[Register("AppDelegate")]
public class AppDelegate : AvaloniaAppDelegate<App>
{
    protected override AppBuilder CustomizeAppBuilder(AppBuilder builder)
    {
        return builder
            .UseiOS()
            .UseSkia();
    }
}
Source: src/iOS/Avalonia.iOS/Platform.cs:50

iOS Platform Options

Configure rendering options for iOS:
using Avalonia;

protected override AppBuilder CustomizeAppBuilder(AppBuilder builder)
{
    return builder
        .With(new iOSPlatformOptions
        {
            RenderingMode = new[]
            {
                iOSRenderingMode.Metal,   // Preferred: Metal rendering
                iOSRenderingMode.OpenGl   // Fallback: OpenGL ES (EAGL)
            }
        })
        .UseiOS()
        .UseSkia();
}
Source: src/iOS/Avalonia.iOS/Platform.cs:34

Rendering Modes

// Metal rendering (recommended)
// - Best performance on modern devices
// - Hardware-accelerated
// - Supported on iOS 8.0+
RenderingMode = new[] { iOSRenderingMode.Metal }
Source: src/iOS/Avalonia.iOS/Platform.cs:109

iOS UI Integration

Embed Avalonia views in iOS applications:
using Avalonia.iOS;
using UIKit;

public class ViewController : UIViewController
{
    private AvaloniaView _avaloniaView;

    public override void ViewDidLoad()
    {
        base.ViewDidLoad();
        
        // Create Avalonia view
        _avaloniaView = new AvaloniaView
        {
            Content = new MyAvaloniaControl()
        };
        
        View.AddSubview(_avaloniaView);
    }
    
    public override void ViewDidLayoutSubviews()
    {
        base.ViewDidLayoutSubviews();
        _avaloniaView.Frame = View.Bounds;
    }
}

iOS Features

  • Touch Input: Multi-touch gesture support
  • Keyboard: On-screen keyboard integration
  • Text Input: iOS text input method support
  • Screen Info: Device screen and orientation detection
  • Safe Areas: Notch and safe area support
  • File Picker: iOS document picker integration
  • Clipboard: iOS pasteboard integration
  • Orientation: Portrait and landscape support
  • Status Bar: Status bar control
Source: src/iOS/Avalonia.iOS/iOSScreens.cs:10

Safe Area Insets

Handle safe areas for modern iOS devices:
using Avalonia.Controls;
using Avalonia.Platform;

public class MainView : UserControl
{
    protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
    {
        base.OnAttachedToVisualTree(e);
        
        var insetsManager = TopLevel.GetTopLevel(this)
            ?.InsetsManager;
            
        if (insetsManager != null)
        {
            // React to safe area changes (notch, etc.)
            insetsManager.SafeAreaChanged += OnSafeAreaChanged;
        }
    }
    
    private void OnSafeAreaChanged(object? sender, SafeAreaChangedArgs e)
    {
        // Adjust UI for safe areas
        Padding = new Thickness(
            e.SafeAreaPadding.Left,
            e.SafeAreaPadding.Top,
            e.SafeAreaPadding.Right,
            e.SafeAreaPadding.Bottom
        );
    }
}

Android Support

Platform Requirements

  • Minimum Version: Android 5.0 (API 21)+
  • Target Version: Android 13.0 (API 33)+ recommended
  • Architectures: ARM64 (arm64-v8a), ARMv7 (armeabi-v7a), x86_64
  • Development: Windows, macOS, or Linux with Android SDK

Android Configuration

Configure your Android application:
using Android.App;
using Android.Content.PM;
using Avalonia;
using Avalonia.Android;

[Activity(
    Label = "MyApp",
    Theme = "@style/MyTheme.NoActionBar",
    Icon = "@drawable/icon",
    MainLauncher = true,
    ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize)]
public class MainActivity : AvaloniaMainActivity<App>
{
    protected override AppBuilder CustomizeAppBuilder(AppBuilder builder)
    {
        return builder
            .UseAndroid()
            .UseSkia();
    }
}
Source: src/Android/Avalonia.Android/AndroidPlatform.cs:22

Android Platform Options

Configure rendering for Android:
using Avalonia;

protected override AppBuilder CustomizeAppBuilder(AppBuilder builder)
{
    return builder
        .With(new AndroidPlatformOptions
        {
            RenderingMode = new[]
            {
                AndroidRenderingMode.Vulkan,    // Best: Vulkan
                AndroidRenderingMode.Egl,       // Good: OpenGL ES
                AndroidRenderingMode.Software   // Fallback: CPU
            }
        })
        .UseAndroid()
        .UseSkia();
}
Source: src/Android/Avalonia.Android/AndroidPlatform.cs:53

Rendering Modes

// Vulkan rendering (recommended)
// - Best performance on modern devices
// - Android 7.0+ (API 24+)
// - Hardware-accelerated
AndroidRenderingMode.Vulkan
Source: src/Android/Avalonia.Android/AndroidPlatform.cs:35

Android Features

  • Touch Input: Multi-touch and gesture support
  • Keyboard: Software keyboard with IME
  • Back Button: Android back button handling
  • Navigation Bar: System navigation integration
  • Status Bar: Status bar customization
  • Orientation: Portrait/landscape support
  • File System: Android storage provider
  • Clipboard: Android clipboard integration
  • Notifications: Local notification support
  • Permissions: Runtime permission handling
  • Dark Mode: System theme detection
Source: src/Android/Avalonia.Android/Platform/AndroidPlatformSettings.cs:13

System Navigation

Handle Android system navigation:
using Avalonia.Android.Platform;
using Avalonia.Platform;

public class MainView : UserControl
{
    protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
    {
        base.OnAttachedToVisualTree(e);
        
        var systemNav = TopLevel.GetTopLevel(this)
            ?.SystemNavigationManager;
            
        if (systemNav != null)
        {
            // Handle back button
            systemNav.BackRequested += OnBackRequested;
        }
    }
    
    private void OnBackRequested(object? sender, BackRequestedEventArgs e)
    {
        if (CanGoBack())
        {
            GoBack();
            e.Handled = true;  // Prevent default back behavior
        }
    }
}

System Insets

Handle Android system insets (notches, navigation bars):
using Avalonia.Controls;
using Avalonia.Platform;

public class MainView : UserControl
{
    protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
    {
        base.OnAttachedToVisualTree(e);
        
        var insetsManager = TopLevel.GetTopLevel(this)
            ?.InsetsManager;
            
        if (insetsManager != null)
        {
            // System UI insets changed
            insetsManager.SystemBarInsets += OnSystemBarInsetsChanged;
        }
    }
    
    private void OnSystemBarInsetsChanged(object? sender, SystemBarInsetsChangedArgs e)
    {
        // Adjust for system bars
        Padding = new Thickness(
            e.Insets.Left,
            e.Insets.Top,
            e.Insets.Right,
            e.Insets.Bottom
        );
    }
}
Source: src/Android/Avalonia.Android/Platform/AndroidInsetsManager.cs:14

Mobile Application Lifetime

Mobile apps use an activatable lifetime:
using Avalonia.Controls.ApplicationLifetimes;

public override void OnFrameworkInitializationCompleted()
{
    if (ApplicationLifetime is IActivatableLifetime activatable)
    {
        // Handle app activation/deactivation
        activatable.Activated += OnActivated;
        activatable.Deactivated += OnDeactivated;
    }

    base.OnFrameworkInitializationCompleted();
}

private void OnActivated(object? sender, ActivatedEventArgs e)
{
    // App came to foreground
}

private void OnDeactivated(object? sender, ActivatedEventArgs e)
{
    // App went to background - save state
}

Touch and Gestures

Mobile platforms have full touch support:
using Avalonia.Input;

public class TouchableControl : Control
{
    protected override void OnPointerPressed(PointerPressedEventArgs e)
    {
        base.OnPointerPressed(e);
        
        var props = e.GetCurrentPoint(this).Properties;
        
        if (props.IsLeftButtonPressed)
        {
            // Handle touch/tap
            var position = e.GetPosition(this);
            Console.WriteLine($"Touch at {position}");
        }
    }
    
    protected override void OnPointerMoved(PointerEventArgs e)
    {
        base.OnPointerMoved(e);
        
        // Handle drag/pan
        var position = e.GetPosition(this);
    }
}

Virtual Keyboard

Control the on-screen keyboard:
using Avalonia.Input;
using Avalonia.Platform;

public class LoginView : UserControl
{
    private void ShowKeyboard()
    {
        var inputPane = TopLevel.GetTopLevel(this)
            ?.InputPane;
            
        if (inputPane != null)
        {
            // Show keyboard
            inputPane.Show();
            
            // Listen for keyboard visibility changes
            inputPane.StateChanged += (s, e) =>
            {
                if (e.NewState == InputPaneState.Closed)
                {
                    // Keyboard was hidden
                }
            };
        }
    }
}

File System Access

Access device storage on mobile:
using Avalonia.Platform.Storage;

public async Task PickImageAsync()
{
    var topLevel = TopLevel.GetTopLevel(this);
    var files = await topLevel.StorageProvider.OpenFilePickerAsync(
        new FilePickerOpenOptions
        {
            Title = "Select an image",
            AllowMultiple = false,
            FileTypeFilter = new[]
            {
                FilePickerFileTypes.ImageAll
            }
        });
    
    if (files.Count > 0)
    {
        await using var stream = await files[0].OpenReadAsync();
        // Load image from stream
    }
}
Source: src/Android/Avalonia.Android/Platform/Storage/AndroidStorageProvider.cs:8

Screen Orientation

Handle device orientation:
using Avalonia.Platform;

public class ResponsiveView : UserControl
{
    protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
    {
        base.OnAttachedToVisualTree(e);
        
        var screens = TopLevel.GetTopLevel(this)?.Screens;
        if (screens?.ScreenFromVisual(this) is Screen screen)
        {
            UpdateLayoutForOrientation(screen.CurrentOrientation);
            
            // Listen for orientation changes
            screens.Changed += (s, args) =>
            {
                if (screens.ScreenFromVisual(this) is Screen currentScreen)
                {
                    UpdateLayoutForOrientation(currentScreen.CurrentOrientation);
                }
            };
        }
    }
    
    private void UpdateLayoutForOrientation(ScreenOrientation orientation)
    {
        if (orientation == ScreenOrientation.Portrait ||
            orientation == ScreenOrientation.PortraitFlipped)
        {
            // Portrait layout
        }
        else
        {
            // Landscape layout
        }
    }
}
Source: src/iOS/Avalonia.iOS/iOSScreens.cs:25

Platform-Specific Code

Conditionally execute mobile-specific code:
using System.Runtime.InteropServices;

if (RuntimeInformation.IsOSPlatform(OSPlatform.Create("IOS")))
{
    // iOS-specific code
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Create("ANDROID")))
{
    // Android-specific code
}

Performance Tips

Optimize for Mobile

  • Use GPU Rendering: Prefer Vulkan/Metal over software rendering
  • Minimize Layout Passes: Avoid nested layouts
  • Virtualize Lists: Use VirtualizingStackPanel for long lists
  • Optimize Images: Use appropriate resolutions
  • Reduce Overdraw: Minimize overlapping UI elements

Memory Management

// Mobile devices have limited memory
public override void OnFrameworkInitializationCompleted()
{
    if (ApplicationLifetime is IActivatableLifetime activatable)
    {
        activatable.Deactivated += (s, e) =>
        {
            // Clear caches when app goes to background
            GC.Collect();
            GC.WaitForPendingFinalizers();
        };
    }
}

Deployment

iOS Deployment

  1. Configure Info.plist for iOS requirements
  2. Add required device permissions
  3. Sign with Apple Developer certificate
  4. Test on physical devices
  5. Submit to App Store via Xcode

Android Deployment

  1. Configure AndroidManifest.xml
  2. Request necessary permissions
  3. Sign with keystore
  4. Create release APK/AAB
  5. Upload to Google Play Console

Next Steps

Platform-Specific Features

Access native mobile APIs

Web Platform

Deploy to browsers with WebAssembly

Build docs developers (and LLMs) love