Migrating to Uno Platform 7.0 — Skia-only rendering
Uno Platform 7.0 removes the native UI rendering backends (native Android Views, native iOS/tvOS/macCatalyst UIKit, and the native WebAssembly DOM renderer) and makes Skia the single, implicit rendering engine on every target.
Skia already runs on every platform — desktop (Win32, WPF, X11, GTK, macOS, FrameBuffer),
Skia-on-Android, Skia-on-iOS, and Skia-on-WebAssembly. In 7.0 it becomes the only UI
rendering path: a UIElement is a plain managed object backed by a Composition.Visual
on all platforms, drawn into a single Skia surface.
This does not drop platform support: Android, iOS, macOS, Windows, Linux, and WebAssembly all remain supported — they now all render with Skia.
Important
This is a hard removal in a single major version — there is no [Obsolete] interim.
Plan to recompile every Uno library against 7.0 and update your application heads.
Who is affected
- Apps that opted out of the Skia renderer on mobile by omitting
<UnoFeatures>skiarenderer</UnoFeatures>and relying on native rendering. - Apps that used the native WebAssembly DOM renderer (
Uno.WinUI.WebAssembly). - Code that referenced native rendering types, native element hosting, or native-only
FeatureConfigurationflags (see below).
Apps already running on Skia on every target need only recompile against 7.0 and remove native bootstrap/heads.
What changed
Rendering is Skia everywhere
The NativeRenderer Uno Feature and the renderer-selection logic are gone — Skia is
always used. skiarenderer is now implicit and mandatory for
android/ios/tvos/maccatalyst; it is kept as a no-op for back-compat, so you can
leave <UnoFeatures>skiarenderer</UnoFeatures> in place or remove it — either way Skia
renders.
WebAssembly renders to a canvas through Skia; there is no per-element DOM tree, no
Uno.UI.css styling layer, and no WindowManager.ts.
If your project was created before Uno Platform 6.0 and still selects a renderer, follow the Uno 6.0 migration guide first to move to the Uno.SDK single-project model.
Packages
| Removed / changed | Migration |
|---|---|
Uno.WinUI.WebAssembly package removed (and the older Uno.WinUI.Runtime.WebAssembly) |
Use Uno.WinUI.Runtime.Skia.WebAssembly.Browser. The UI renders to a canvas; there is no DOM tree. With the Uno.SDK, the Skia browser head is referenced implicitly — there is nothing to add. |
Uno.WinUI.Skia.X11, Uno.WinUI.Skia.MacOS, and Uno.WinUI.Skia.Linux.FrameBuffer bootstrapper packages removed |
These were empty meta-packages that only redirected to the real head. With the Uno.SDK, remove the reference — the matching Uno.WinUI.Runtime.Skia.* head is referenced implicitly for executable heads. For a hand-rolled (non-Uno.SDK) head, replace it with the corresponding Uno.WinUI.Runtime.Skia.<variant> package. |
Uno.UI.BindingHelper.Android assembly removed |
Remove the reference; Skia-on-Android needs no Java/JNI binding. |
Uno.UniversalImageLoader no longer injected (Android) |
Skia handles image loading internally. If you initialized it manually, remove the ConfigureUniversalImageLoader(); call. |
Uno.UI.Maps AddIn removed |
The native Google Maps control has no core Skia equivalent — use a third-party/Skia map or custom rendering. |
Uno.WinUI UI assemblies for net*-android/ios/tvos/maccatalyst are now the Skia binaries |
Same TFM string, but binary-incompatible with previously native-built consumers. Recompile all libraries against 7.0 and remove native bootstrap. |
Xamarin.AndroidX.* transitive deps removed (AppCompat, RecyclerView, Activity, Browser, SwipeRefreshLayout) |
If your own code uses AndroidX, add explicit PackageReferences. |
Note
Referencing Uno.WinUI.WebAssembly (or the older Uno.WinUI.Runtime.WebAssembly)
alongside the Skia browser head raises the UNOB0017 build diagnostic. Removing the
explicit reference resolves it.
Public API removed
- Native base classes / identity:
BindableView(andBindable*widget wrappers),BindableUIView(andBindableUI*).UIElementno longer inherits a nativeView/UIView/DOM element. Remove casts toAndroid.Views.View/UIKit.UIView; useUIElement.Visual(Composition) and reach platform APIs via theUno.UI.Runtime.Skia.*hosts andUno.Foundation. - Native element hosting:
Uno.UI.NativeElementHosting.BrowserHtmlElement,Uno.UI.Runtime.WebAssembly.HtmlElementAttribute, andContentPresenterhosting of a nativeView/UIView/DOM element asContent. UseWebView2for HTML content, or redesign with Uno controls. On iOS, opt-in native embedding remains viaUIKitNativeElementHostingExtension(overlay-composited, reduced performance). - Native control / host types:
NativeListViewBase,NativePagedView,NativeScrollContentPresenter,NativeFramePresenter,NativePopup,RootViewController,Window : UIWindowidentity,NativeRenderTransformAdapter,IShadowChildrenProvider,CompositorThread,Uno.UI.Composition.ICompositionRoot. Use the WinUI control (ListView/Frame/Popup/…) — everything renders via Skia. - Composition:
Uno.CompositionConfiguration.Options.UseCompositorThread(the Android RenderNode compositor thread). Remove the flag; Skia composition needs no dedicated native render thread. - Legacy WebAssembly JavaScript interop:
Uno.Foundation.Interop.IJSObject,IJSObjectMetadata,JSObjectHandle,JSObject, andWebAssemblyRuntime.InvokeJSWithInterop(FormattableString)— the Uno-only managed-to-JavaScript object-marshalling mechanism (no WinUI counterpart). Migrate to the standard .NET WebAssembly interop, JSImport/JSExport fromSystem.Runtime.InteropServices.JavaScript— the recommended, source-generated path (thread-safe, CSP-compliant, noeval). The string-basedWebAssemblyRuntime.InvokeJS(string)is not removed, but it is a legacy eval-based API and is not recommended for new code.
FeatureConfiguration flags removed
The native-only flags below no longer exist; delete the calls — behavior is the unified Skia/WinUI behavior:
- Android:
ComboBox.AllowPopupUnderTranslucentStatusBar,FrameworkElement.AndroidUseManagedLoadedUnloaded,FrameworkElement.InvalidateNativeCacheOnRemeasure,Popup.UseNativePopup,NativeListViewBase.*,NativeFramePresenter.AndroidUnloadInactivePages,TextBox.UseLegacyInputScope,UIElement.UseLegacyClipping,UIElement.AlwaysClipNativeChildren,ScrollViewer.AndroidScrollbarFadeDelay,WebView.ForceSoftwareRendering,PointerRoutedEventArgs.AllowRelativeTimeStamp,TextBlock.IsJavaStringCachedEnabled/JavaStringCachedCapacity,AppBarButton.EnableBitmapIconTint,TimePickerFlyout.UseLegacyTimeSetting,NavigationView.EnableUno19516Workaround,AndroidSettings.IsEdgeToEdgeEnabled. - iOS:
Image.LegacyIosAlignment,FrameworkElement.IOsAllowSuperviewNeedsLayoutWhileInLayoutSubViews,CommandBar.AllowNativePresenterContent,DatePicker.UseLegacyStyle,TimePicker.UseLegacyStyle. - WebAssembly:
Interop.ForceJavascriptInterop,UIElement.AssignDOMXamlName,UIElement.AssignDOMXamlProperties,TextBlock.IsMeasureCacheEnabled,Cursors.UseHandForInteraction(the "hand" cursor for interactive controls is now never used). - Native (Android + iOS):
ListViewBase.AnimateScrollIntoView. - Native styling:
Style.UseUWPDefaultStyles,Style.ConfigureNativeFrameNavigation(). - Skia overlay:
TextBox.UseOverlayOnSkia.
WebView2.IsInspectable is also removed; it was an obsolete alias, so switch to
WebView2.EnableDevTools instead.
If a single codebase must target both pre-7.0 and 7.0, guard the calls with #if.
Behavioral changes (same API, different result)
Because rendering moves from Canvas/CALayer/CSS to Skia, expect subtle differences and
re-baseline visual tests:
- Rendering: gradients, corner radii, shadows/elevation, and anti-aliasing render via Skia — minor pixel differences are possible.
- Text: measurement, line-breaking, bidi, kerning, and
MaxLinesgo through HarfBuzz + SkiaSharp instead ofStaticLayout/UIKit text/DOM — possible layout shifts in text-dense UI. - Lists / scrolling: managed virtualization and scrolling replace
RecyclerView/UICollectionView/CSS overflow — fling curves, edge glows, and snap points may differ. - IME / keyboard: canvas-rendered text input with a platform IME bridge replaces the
native
EditText/UITextField— re-test CJK/emoji composition and selection visuals. - Pickers / command bars / Frame: Skia/WinUI-styled rather than native-styled — appearance changes on Android/iOS.
- Animation timing: Skia interpolation replaces
CABasicAnimation— standard easing matches; exotic timing may not.
Type-hierarchy changes (WinUI parity)
7.0 realigns several types to their WinUI base classes. Most code is unaffected — the change only breaks code that used the Uno-only members leaked by the wrong base.
MediaPlayerPresenternow derives directly fromFrameworkElement(matching WinUI) instead ofBorder, removing the extraBorderlevel. TheBorder-only surface it used to expose —Child,BorderBrush,BorderThickness,CornerRadius,Padding,BackgroundSizing,ChildTransitions— is gone, andis Borderis no longertruefor a presenter. The video surface is hosted internally, so playback andStretchare unchanged.MediaPlayerElementsets its ownBackground(black) on the template root, so letterbox bars stay black.ImageBrushnow derives from a realTileBrush(Brush → TileBrush → ImageBrush, matching WinUI) instead of directly fromBrush.AlignmentX,AlignmentY, andStretchbehave the same for callers but are now declared onTileBrush— code that referenced the static DPs by their declaring type (ImageBrush.StretchProperty,AlignmentXProperty,AlignmentYProperty) still resolves via inheritance, andis TileBrushis nowtruefor anImageBrush. Instance usage (imageBrush.Stretch, XAMLStretch="…") is unaffected.
XAML changes
The WPF-style
clr-namespace:xmlns form is no longer accepted. WinUI only supportsusing:; Uno used to also acceptclr-namespace:MyApp.Controls;assembly=MyLiband silently strip the prefix and the;assembly=token. Replace each declaration with theusing:form — the assembly is inferred, so the;assembly=part is simply dropped:- xmlns:local="clr-namespace:MyApp.Controls;assembly=MyLib" + xmlns:local="using:MyApp.Controls"This is enforced at build time (the
UXAML0006diagnostic) and at run time byXamlReader.Loadand Hot Reload, which throw aXamlParseException. The declaration itself is rejected whether or not the prefix is used, so unusedclr-namespace:declarations must also be removed — the only exemption is a prefix listed inmc:Ignorableon the root element.
Templates and project heads
New apps get Skia heads only. Existing apps should drop native *.Mobile / native
*.Wasm (DOM) heads in favor of the Skia heads (Skia.netcoremobile,
Skia.WebAssembly.Browser, and the desktop Skia head) and remove native bootstrap code.
Migration checklist
- Remove
<UnoFeatures>skiarenderer</UnoFeatures>(now implicit) — and any native-only feature switches. - Recompile every Uno-dependent library against 7.0.
- Remove references to the deleted assemblies/types and to native element hosting.
- Delete native-only
FeatureConfigurationcalls. - Replace the WASM DOM head with the Skia WebAssembly Browser head; remove any DOM/CSS
customization and
HtmlElementusage. - Remove manual
ConfigureUniversalImageLoader();(Android) and other native bootstrap. - Convert every
xmlns:…="clr-namespace:…"declaration in your XAML to theusing:form. - Re-baseline visual/snapshot tests and re-test text, lists/scroll, IME, pickers, and safe-area/notch handling on devices.
See the Uno 6.0 migration guide for the full Android/iOS/WebAssembly Skia bootstrapping steps.