SkiaUi.Maui
1.11.0
dotnet add package SkiaUi.Maui --version 1.11.0
NuGet\Install-Package SkiaUi.Maui -Version 1.11.0
<PackageReference Include="SkiaUi.Maui" Version="1.11.0" />
<PackageVersion Include="SkiaUi.Maui" Version="1.11.0" />
<PackageReference Include="SkiaUi.Maui" />
paket add SkiaUi.Maui --version 1.11.0
#r "nuget: SkiaUi.Maui, 1.11.0"
#:package SkiaUi.Maui@1.11.0
#addin nuget:?package=SkiaUi.Maui&version=1.11.0
#tool nuget:?package=SkiaUi.Maui&version=1.11.0
SkiaUi
.NET MAUI library of SkiaSharp-drawn UI. Controls are drawn on one GPU surface instead of each owning a platform view, in two layers you can mix in one tree: SkUi* controls that replace MAUI's by changing the XAML prefix, and a lightweight Core layer for building controls of your own. WebView, maps, media and other native views stay native, as overlays in SkUiMauiContentView.
1.0.0 is the first stable release. Its public API is kept by every
1.xrelease; prereleases of the next version (1.1.0-PrereleaseNN) are published from thedevelbranch. What's next: roadmap.
Who it's for
Apps whose MAUI screens are slow. Long forms, dashboards, lists of rich rows: on a screen with hundreds of controls, MAUI spends seconds creating handlers and platform views before the first frame. SkUi* controls are drop-in replacements that keep MAUI's API (the same properties, XAML, bindings, styles, VisualStateManager and layout rules), so a slow page moves to drawn controls by changing <Label> to <sk:SkUiLabel> and <Grid> to <sk:SkUiGrid>, one page or one hot spot at a time. On a 2018 Android phone a page of 1,000 buttons is ready in 0.4 s instead of 6.4 s (stress results). The migration guide and the migration skills for AI coding agents cover the rest.
Developers who build custom Skia-drawn controls. Drawing a control on a bare SKCanvasView means writing its layout, text, hit-testing, gestures, accessibility and animations yourself. With Core, a custom control is composed from drawn building blocks (labels, buttons, shapes, borders, images, toggles, text fields, layouts) that are plain objects with fluent setters, no BindableObject and no handler, and it gets SkiaUi's text engine, gesture arena, keyboard focus, screen-reader support, render-thread animations, looks and color schemes for free. Host it in any page with SkUiCoreHost, or wrap it in a thin SkUi* view to use it from XAML (Core guide, samples).
Apps that need richer UI than MAUI offers. Skeleton loading screens, chips that wrap, carousels with cover-flow effects, lists with sticky and collapsible groups, numeric and date-and-time fields, text that shrinks to fit, one consistent look on every platform: with MAUI alone these mean third-party packages, platform renderers or custom drawing. SkiaUi ships them as drawn controls that work like MAUI's, in XAML or in code, the same on Android, iOS, Mac Catalyst and Windows (what SkiaUi adds).
Why SkiaUi
.NET MAUI is a strong piece of engineering. On a complex screen its cost shows up in two places.
Speed. Each visual update crosses from .NET into the native UI runtime. That boundary is fine for a handful of controls and becomes significant when a screen holds a large tree.
Memory. Every MAUI control owns a handler and a platform view, and every platform view has a native object on the other side. Leak tracking is difficult because it is often unclear whether the platform view is held by the native object, or the native object is held by the platform view.
SkiaUi draws most of the tree on one Skia surface, so those controls do not each allocate a handler and a platform view. Native views stay only where the platform must own them (WebView, maps, media, and similar); text fields are drawn, with the platform keyboard and input methods typing into them.
Two layers
| Layer | What it is | When to use it |
|---|---|---|
SkUi* (MAUI-compatible) |
Drop-in style controls and layouts (SkUiLabel, SkUiButton, SkUiGrid, …) with XAML, bindable properties, styles, and MAUI measure/arrange |
Replace slow native MAUI visual trees while keeping familiar authoring |
Core (SkUiCore*) |
Low-level fluent nodes (no BindableObject / MAUI View per cell); hosted under SkUiCoreHost |
Author new controls or complex / high-count UI where allocation and add-to-tree cost matter |
Both share one Skia surface under a root host (SkUiContentView / SkUiLayout). Drawn children paint together; system widgets appear as overlays. The MAUI-compatible tree is fully authorable in XAML; Core is code-first (fluent + INotifyPropertyChanged).
MAUI page
└── SkUiContentView / SkUiLayout ← one Skia surface
├── SkUiGrid / SkUiButton / … ← SkUi* (replace native MAUI)
└── SkUiCoreHost
└── SkUiCore* tree ← Core (compose / dense UI)
Beyond MAUI
Parity with MAUI is the starting point. What drawn controls add on top of it:
- The same pixels on every platform, or the platform's own look. The default look draws each control the same on Android, iOS, Mac Catalyst and Windows. The platform looks (iOS 26, Material 2 and Material 3, Mac Catalyst, Windows) are measured against MAUI's native controls. Shapes, sizes, state transitions and colors come from one
SkUiLookandSkUiColorSchemeyou customise once for the whole app (control look, color scheme). - Motion off the UI thread.
AnimateAsync, scroll flings, indeterminate progress and shimmer run on the render thread and keep going while the UI thread is busy. Moving, fading, scrolling or transforming a view with shadows and clips records and blurs nothing again (rendering pipeline). - Text MAUI doesn't have: shrink and grow to fit, tightening, custom line breaking, HTML parsed the same on every platform with tappable links, justified text and synthetic bold / italic everywhere, rounded backgrounds and borders on labels themselves (SkUiLabel).
- Controls MAUI doesn't have: numeric entries with typed values, multi-column and date-and-time pickers, shimmer skeletons of your own views, wrap layouts for chips and tags, stacks whose children shrink to fit, a stack that keeps a bar's title centered, content switches with animations, virtualized stacks; the Community Toolkit's avatar, expander and state container built in, drawn.
- More from the controls MAUI has: a collection view with collapsible groups, sticky group headers, sticky header and footer, load more and pull-to-refresh built in; a carousel that loops without an end, shows the next cards peeking and draws item effects (cover flow, scaling, your own) on the compositor; snap points and overscroll on scroll views; vertical sliders, indeterminate progress bars, steppers with stacked buttons and typed values; pickers whose lists open on your app's popup system (all controls).
- One gesture model. A per-pointer gesture arena decides between nested taps, long presses, swipes and scrolls the same way on every platform; MAUI's
TapGestureRecognizerworks on drawn views (event mechanism). - Fewer leaks to chase. Drawn controls have no handler and no native peer to keep them alive, long-lived sources are listened to weakly, and leak scenarios run headless with every test run and on devices.
Install
Package on nuget.org: SkiaUi.Maui.
Requirements: .NET 10 with .NET MAUI 10.0.130 or a later 10.x (SDK 10.0.402 or newer); Android 5.0 (API 21), iOS 15, Mac Catalyst 17 and Windows 10 1809 or newer. iOS and Mac Catalyst builds work with Xcode 26.6 (workload set 10.0.401), Xcode 27.1 (workload set 10.0.402.1) or Xcode 27.2 (workload set 10.0.404), macOS 26.6 or newer for Xcode 27; apps built with Xcode 27 must use the UIKit scene lifecycle (migration guide). SkiaUi 1.0.x builds with MAUI 10.0.110, Mac Catalyst 15 and Xcode 26.
dotnet add package SkiaUi.Maui
Register in MauiProgram:
builder.UseSkiaUi();
Using CommunityToolkit.Maui? SkiaUi.Maui.CommunityToolkit opens drawn pickers' lists in the toolkit's Popup (without it, they open in MAUI's action sheet, or on any popup system through an ISkUiPopupPresenter of yours):
dotnet add package SkiaUi.Maui.CommunityToolkit
builder.UseMauiCommunityToolkit().UseSkiaUi().UseSkiaUiCommunityToolkit();
Showing Markdown? SkiaUi.Maui.Markdown draws a document on both layers, and SkiaUi.Maui.Markdown.Math adds formulas. Nothing a document says happens by itself: SkUiMarkdownView.
Quick start
xmlns:sk="clr-namespace:MauiSkiaUi;assembly=MauiSkiaUi"
A drawn page, with MAUI's controls under the sk: prefix:
<sk:SkUiContentView Background="White">
<sk:SkUiScrollView Padding="16">
<sk:SkUiGrid RowDefinitions="Auto,Auto,Auto" RowSpacing="12">
<sk:SkUiLabel Text="Observations" FontSize="24" />
<sk:SkUiImage Grid.Row="1" Source="earth.jpg" HeightRequest="200" />
<sk:SkUiButton Grid.Row="2" Text="Add observation" Command="{Binding AddCommand}" />
</sk:SkUiGrid>
</sk:SkUiScrollView>
</sk:SkUiContentView>
A list that shows a shimmering skeleton while it loads:
<sk:SkUiShimmer IsLoading="{Binding IsLoading}" AfterStateChangeAnimation="FadeIn 250">
<sk:SkUiCollectionView ItemsSource="{Binding Contacts}" SelectionMode="Single">
<DataTemplate x:DataType="local:Contact">
<sk:SkUiGrid ColumnDefinitions="Auto,*" ColumnSpacing="12" Padding="16,8">
<sk:SkUiAvatarView Text="{Binding Name}" WidthRequest="40" HeightRequest="40" CornerRadius="20" />
<sk:SkUiVerticalStackLayout Grid.Column="1" Spacing="2" VerticalOptions="Center">
<sk:SkUiLabel Text="{Binding Name}" FontAttributes="Bold" />
<sk:SkUiLabel Text="{Binding Email}" FontSize="13" TextColor="Gray" />
</sk:SkUiVerticalStackLayout>
</sk:SkUiGrid>
</DataTemplate>
</sk:SkUiCollectionView>
</sk:SkUiShimmer>
No second layout for the skeleton: while IsLoading is true, the still-empty list fills itself with placeholder rows made from its own item template, and each control in them draws as bones (the avatar a circle, each label a bar). The bones shimmer on the render thread, and when the contacts arrive and IsLoading turns false, the rows fade in (SkUiShimmer, SkUiCollectionView).
Migrating a MAUI app
docs/Migration.md walks through moving existing MAUI screens to drawn controls: where the drawn surface goes, the control mapping, styles, gestures, custom controls and what has no drawn equivalent yet. For AI coding agents, the SkiaUi migration skills audit an app and convert pages by the same rules (Claude Code: /plugin marketplace add rafalka/MauiSkiaUi, then /plugin install skiaui-migration@skiaui). To drive a SkiaUi app's drawn controls with .NET MAUI DevFlow, see docs/DevFlow.md and the skiaui-devflow skill.
Controls
SkUi* (replace native MAUI)
| Area | Types |
|---|---|
| Hosts & layout | SkUiContentView, SkUiLayout, SkUiGrid, stacks, SkUiAbsoluteLayout, SkUiFlexLayout, SkUiBorder; SkUiDragger, SkUiGridSplitter, SkUiWrapLayout, SkUiTileLayout, shrink stacks, SkUiHorizontalAlignStackLayout |
| Scrolling & lists | SkUiScrollView, SkUiRefreshView, SkUiCollectionView, SkUiCarouselView, SkUiIndicatorView, SkUiSwipeView, virtual stacks |
| Text & chrome | SkUiLabel, SkUiButton, SkUiImage, SkUiImageButton, SkUiAvatarView, SkUiActivityIndicator, SkUiProgressBar |
| Toggles & values | SkUiSwitch, SkUiCheckBox, SkUiRadioButton, SkUiSlider, SkUiStepper |
| Text input | SkUiEntry, SkUiEditor, SkUiSearchBar, SkUiNumericEntry / SkUiNumericEntry<T> |
| Pickers | SkUiPicker, SkUiMultiColumnPicker, SkUiDatePicker, SkUiTimePicker, SkUiDateTimePicker |
| Content & loading | SkUiContentPresenter, SkUiAlternateContentView, SkUiExpander, SkUiStateContainer, SkUiShimmer |
| Shapes | SkUiBox (BoxView), MAUI's shapes with brushes, dashes and stretch: SkUiEllipse, SkUiLine, SkUiRectangle, SkUiRoundRectangle, SkUiPath, SkUiPolygon, SkUiPolyline; SkUiBorder.StrokeShape takes any of them |
| Native overlay | SkUiMauiContentView (WebView, maps, …) |
Core (compose / custom controls)
| Area | Types |
|---|---|
| Bridge | SkUiCoreHost |
| Layouts | SkUiCoreAbsoluteLayout, stacks, overlay, SkUiCoreGrid / SkUiCoreTable, wrap and shrink layouts, SkUiCoreContentView / SkUiCoreBorder, SkUiCoreScrollView |
| Controls | SkUiCoreLabel, SkUiCoreButton, toggles, SkUiCoreSlider, SkUiCoreProgressBar, image / image button, SkUiCoreAvatar, activity indicator, shapes, SkUiCoreShimmer, SkUiCoreIndicatorView |
| Text input & pickers | SkUiCoreEntry / SkUiCoreEditor / SkUiCoreSearchBar / SkUiCoreNumericEntry / SkUiCoreStepper; SkUiCorePicker, SkUiCoreMultiColumnPicker, SkUiCoreDatePicker, SkUiCoreTimePicker, SkUiCoreDateTimePicker |
Per-control guides (behavior vs MAUI, XAML samples, limits): docs/controls/ · Core overview: docs/controls/SkUiCore.md.
Essentials
- Coordinates are MAUI DIPs; the handler maps to surface pixels.
HwAcceleratedis set before the handler attaches (ContentView/Layout default GPU; leaves default software). Hosted children ignore it.- Gestures use SkiaUi’s gesture arena (
Tapped/TappedCommand,LongPressed,Swiped,PanUpdated, …). MAUI'sTapGestureRecognizerworks on drawn views; other recognizers and platform behaviors such asTouchBehaviorare converted to those events (migration guide). - Styles / VisualStateManager work on bindable
SkUi*properties like other MAUI views, with MAUI's states:Normal,Disabled,PointerOver(mouse / trackpad / pen / iPad pointer hover), buttons'Pressed, CheckBoxIsChecked, SwitchOn/Off, RadioButtonChecked/Unchecked,Focused/Unfocusedfrom keyboard focus. StartUpdating/EndUpdatingbatch layout and paint invalidation when changing many properties.- Fluent
Set*setters are the property setters in chainable form: they write the bindable store, so bindings and triggers see them. - Accessibility: drawn controls are read by TalkBack, VoiceOver and Narrator (MAUI's
SemanticProperties/AutomationPropertiesapply), take keyboard focus (MAUI'sFocus(), Tab order, Space / Enter, a focus ring), and text follows the system text size (FontAutoScalingEnabled). Native overlays keep their platform accessibility (docs). - Trimming and Native AOT: the library is trimmable and AOT-compatible (no reflection; trim / AOT analyzers fail its build). Checked with Native AOT on iOS and Mac Catalyst and full trimming on Android. Android Native AOT (experimental in .NET 10): software surfaces (
HwAccelerated = false) fail, because SkiaSharp's AndroidSKCanvasViewneeds an assembly that build doesn't include; GPU surfaces work.
Sample app
MauiSkiaUiDemo in this repo is a component gallery (editors, native side-by-side comparisons, look/color playground, stress pages). It is for exploration and verification, not published with the NuGet package.
Prebuilt apps: every GitHub release has the demo and samples apps attached: an Android APK (arm64, signed with a debug key: allow installing from unknown sources) and a Mac Catalyst app in a zip (not signed: right-click it and choose Open the first time).
samples/MauiSkiaUiSamples shows how to build things with SkiaUi, e.g. a custom look with its own check-box transition. Each example page explains what it presents and how to achieve it, lists the things to know, and shows its own source (samples/README.md).
Stress results (device)
The demo's Stress page: 1,000 buttons in a two-column grid under one scroll view, animation off; SkUi* and Core on a GPU surface. Release builds of each line, with MAUI's visual tree diagnostics off (why): .NET 10 (SDK 10.0.404, MAUI 10.0.120, Mono) and .NET 11 (SDK 11.0.100, MAUI 11.0.10, CoreCLR), measured in November 2026; average of 12 rounds (4 launches × 3 rounds after a warm-up round; the two lines alternated, each run once first). Times in milliseconds.
The Galaxy S9 (2018) and iPhone 8 (2017) were chosen to represent old, slow devices: a UI that is fast on them is fast on the phones most apps support.
| Device | Layer | .NET | Generate UI | Add to page | First frame | Overall (start → UI idle) | Scrolling |
|---|---|---|---|---|---|---|---|
| Galaxy S9 (Android 10) | Native MAUI | 10 | 429 | 4,831 | 780 | 6,040 | — |
| 11 | 217 | 3,287 | 822 | 4,327 | — | ||
| SkUi* | 10 | 224 | 48 | 151 | 426 | 59 fps | |
| 11 | 171 | 40 | 216 | 427 | 60 fps | ||
| Core | 10 | 68 | 9 | 189 | 267 | 59 fps | |
| 11 | 81 | 17 | 146 | 245 | 60 fps | ||
| iPhone 8 (iOS 16) | Native MAUI | 10 | 223 | 1,639 | 941 | 2,803 | — |
| 11 | 104 | 1,689 | 1,024 | 2,816 | — | ||
| SkUi* | 10 | 109 | 14 | 42 | 165 | 60 fps | |
| 11 | 80 | 27 | 26 | 133 | 60 fps | ||
| Core | 10 | 50 | 3 | 39 | 92 | 60 fps | |
| 11 | 42 | 5 | 37 | 84 | 60 fps |
The drawn tree is ready 14× (SkUi*) and 23× (Core) faster than native MAUI on the S9 on .NET 10 (10× and 18× on .NET 11, where native MAUI itself gains more than a quarter), and 17× and 30× faster on the iPhone 8 (21× and 34× on .NET 11), and scrolls at the display's 60 fps on both lines. On .NET 11 the iPhone 8 builds and shows the SkUi* tree faster (133 ms instead of 165 ms), and on the S9 the render thread spends less per scrolled frame (3.7 ms instead of 6.5 ms). What gradients, shadows, clips, shaped borders and animated content cost while scrolling, and which of them to avoid in long lists: docs/Performance.md.
Contributing / developing SkiaUi
How to report bugs, request features and open pull requests: CONTRIBUTING.md. Questions go to Discussions (SUPPORT.md); security problems are reported privately (SECURITY.md).
Build, test and CI: Development.md. Architecture, requirements and the roadmap: docs.
Changes
CHANGELOG.md — the same notes nuget.org shows for each SkiaUi.Maui version.
License
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-android36.0 is compatible. net10.0-browser was computed. net10.0-ios was computed. net10.0-ios26.0 is compatible. net10.0-maccatalyst was computed. net10.0-maccatalyst26.0 is compatible. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. net10.0-windows10.0.19041 is compatible. net11.0 is compatible. net11.0-android37.0 is compatible. net11.0-ios27.2 is compatible. net11.0-maccatalyst27.2 is compatible. net11.0-windows10.0.19041 is compatible. |
-
net10.0
- Microsoft.Maui.Controls (>= 10.0.130)
- SkiaSharp (>= 4.154.0)
- SkiaSharp.HarfBuzz (>= 4.154.0)
-
net10.0-android36.0
- Microsoft.Maui.Controls (>= 10.0.130)
- SkiaSharp (>= 4.154.0)
- SkiaSharp.HarfBuzz (>= 4.154.0)
- SkiaSharp.Views.Maui.Controls (>= 4.154.0)
-
net10.0-ios26.0
- Microsoft.Maui.Controls (>= 10.0.130)
- SkiaSharp (>= 4.154.0)
- SkiaSharp.HarfBuzz (>= 4.154.0)
- SkiaSharp.Views.Maui.Controls (>= 4.154.0)
-
net10.0-maccatalyst26.0
- Microsoft.Maui.Controls (>= 10.0.130)
- SkiaSharp (>= 4.154.0)
- SkiaSharp.HarfBuzz (>= 4.154.0)
- SkiaSharp.Views.Maui.Controls (>= 4.154.0)
-
net10.0-windows10.0.19041
- Microsoft.Maui.Controls (>= 10.0.130)
- SkiaSharp (>= 4.154.0)
- SkiaSharp.HarfBuzz (>= 4.154.0)
- SkiaSharp.Views.Maui.Controls (>= 4.154.0)
-
net11.0
- Microsoft.Maui.Controls (>= 11.0.10)
- SkiaSharp (>= 4.154.0)
- SkiaSharp.HarfBuzz (>= 4.154.0)
-
net11.0-android37.0
- Microsoft.Maui.Controls (>= 11.0.10)
- SkiaSharp (>= 4.154.0)
- SkiaSharp.HarfBuzz (>= 4.154.0)
- SkiaSharp.Views.Maui.Controls (>= 4.154.0)
-
net11.0-ios27.2
- Microsoft.Maui.Controls (>= 11.0.10)
- SkiaSharp (>= 4.154.0)
- SkiaSharp.HarfBuzz (>= 4.154.0)
- SkiaSharp.Views.Maui.Controls (>= 4.154.0)
-
net11.0-maccatalyst27.2
- Microsoft.Maui.Controls (>= 11.0.10)
- SkiaSharp (>= 4.154.0)
- SkiaSharp.HarfBuzz (>= 4.154.0)
- SkiaSharp.Views.Maui.Controls (>= 4.154.0)
-
net11.0-windows10.0.19041
- Microsoft.Maui.Controls (>= 11.0.10)
- SkiaSharp (>= 4.154.0)
- SkiaSharp.HarfBuzz (>= 4.154.0)
- SkiaSharp.Views.Maui.Controls (>= 4.154.0)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on SkiaUi.Maui:
| Package | Downloads |
|---|---|
|
SkiaUi.Maui.CommunityToolkit
CommunityToolkit.Maui integration for SkiaUi.Maui: drawn pickers (and other drawn controls with popups) show their popups in the toolkit's Popup, and drawn counterparts of the toolkit's DockLayout and UniformItemsLayout. |
|
|
SkiaUi.Maui.Markdown
A drawn Markdown view for SkiaUi.Maui: headings, lists, tables, code, quotes, alerts, footnotes and images, the same on every platform, without a platform view per paragraph. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.11.0 | 0 | 11/14/2026 |
| 1.10.3 | 65 | 11/12/2026 |
| 1.10.2 | 119 | 11/11/2026 |
| 1.10.1 | 93 | 11/11/2026 |
| 1.10.0 | 78 | 11/11/2026 |
| 1.9.0 | 126 | 11/10/2026 |
| 1.8.0 | 204 | 11/6/2026 |
| 1.7.0 | 125 | 11/5/2026 |
| 1.6.0 | 110 | 11/4/2026 |
| 1.5.1 | 177 | 11/3/2026 |
| 1.5.0 | 125 | 11/3/2026 |
| 1.4.0 | 176 | 10/29/2026 |
| 1.3.0 | 159 | 10/28/2026 |
| 1.2.0 | 157 | 10/27/2026 |
| 1.1.0 | 129 | 10/26/2026 |
| 1.0.0 | 172 | 10/22/2026 |
| 1.0.0-Prerelease15 | 144 | 10/20/2026 |
| 1.0.0-Prerelease14 | 116 | 10/19/2026 |
| 1.0.0-Prerelease13 | 136 | 10/16/2026 |
| 1.0.0-Prerelease12 | 124 | 10/15/2026 |
Full release notes: https://github.com/rafalka/MauiSkiaUi/blob/v1.11.0/CHANGELOG.md#1110
New features
- .NET 11 and MAUI 11
Breaking changes
- The net10 assets need MAUI 10.0.130: all four packages' net10.0-* assets now reference MAUI 10.0.130 (was 10.0.120). A .NET 10 app with its own Microsoft.Maui.Controls reference below 10.0.130 must raise it, or restore fails with NU1605 (package downgrade). MAUI 10.0.130 leaves room for a shape's stroke only when it has one (dotnet/maui#37319): a drawn shape without Stroke (both layers) now fills its bounds and measures without StrokeThickness, as MAUI's shapes do, and a stroke appearing or going measures it again.