uid |
---|
Uno.Development.HowItWorks |
How does Uno Platform make the same application code run on all platforms?
On Windows (the Windows head project), an Uno Platform application isn't using Uno.UI at all. It's compiled just like a single-platform WinUI application, using Microsoft's own tooling.
The rest of this article discusses how the Uno.UI tooling allows WinUI-compatible XAML and C# applications to run on non-Windows platforms.
The Uno.UI
library completely reproduces the WinUI API surface: all namespaces (Microsoft.UI.Xaml
, Windows.Foundation
, Windows.Storage
, etc), all classes, all class members. Insofar as possible, the same look and behavior as on Windows are replicated on all other platforms.
Note that, as the API surface is very large, some parts of it are included but not implemented. These features are marked with the Uno.NotImplementedAttribute
attribute, and a code analyzer included with the Uno.UI package will generate a warning for any such features that are referenced. You can see a complete list of supported APIs here.
As an application developer, you normally don't need to worry about exactly how Uno.UI renders your visual tree to the screen on each platform. For every platform, the public API - panels, control templates, measurement and arranging, etc - is the same. However, it's sometimes useful to know what's going on at render-time, for example if you're intermixing native views with XAML views on a platform-specific basis.
On the web, each XAML element is converted into an appropriate HTML element. Panels, controls, and other 'intermediate' elements in the visual tree are converted to <div/>
elements, whereas 'leaf' elements like TextBlock
, Image
etc get converted into more specific tags (<p/>
, <img/>
etc).
On iOS and Mac Catalyst, all types that inherit from Microsoft.UI.Xaml.FrameworkElement
, also inherit from the native UIView
type. That is to say, on iOS, all XAML visual elements are also native views.
When rendered at runtime, certain FrameworkElement
types implicitly create inner views that inherit from higher-level native view types. For example, Image
implicitly creates an inner NativeImage
view, where NativeImage
is an Uno-defined internal type that inherits directly from the native UIKit.UIImageView
type.
On Android, all types that inherit from Microsoft.UI.Xaml.FrameworkElement
, also inherit from the native ViewGroup
type. That is to say, on Android, all XAML visual elements are also native views.
When rendered at runtime, certain FrameworkElement
types implicitly create inner views that inherit from higher-level native view types. For example, Image
implicitly creates an inner NativeImage
view, where NativeImage
is an Uno-defined internal type that inherits directly from the native Android.Widget.ImageView
type.
On macOS, all types that inherit from Windows.UI.Xaml.FrameworkElement
, also inherit from the native NSView
type. That is to say, on macOS, all XAML visual elements are also native views.
When rendered at runtime, certain FrameworkElement
types implicitly create inner views that inherit from higher-level native view types. For example, Image
implicitly creates an inner NativeImage
view, where NativeImage
is an Uno-defined internal type that inherits directly from the native AppKit.NSImageView
type.
On Linux, XAML visual elements are rendered directly to a Skia canvas. Unlike the other target platforms, there's no 'native view type' to speak of. The Skia canvas is hosted inside of a Gtk shell, but it's just that, a shell - there aren't any Gtk widgets used. (The Gtk and WPF APIs are used by Uno to handle pointer input, however.)
The codebase of an Uno Platform application is a mix of XAML markup, C# code, images, string resources, and miscellaneous other assets. At build time, Uno.UI takes the shared codebase and creates a native application for the target being built, including binaries, properly named and packaged assets, etc. How does it happen?
The C# code is the easy part - .NET runs pretty much everywhere. On iOS, Android, macOS and Mac Catalyst, Uno.UI is using .NET for Mobile (previously known as Xamarin Native, and is not Xamarin.Forms or MAUI). On the web, it's using .NET running in WebAssembly, and on Linux it's running under .NET 6 or later.
The compiled binaries also include the output of the XAML parser, as described in the next section.
Uno.UI parses XAML files at build time. XAML markup is automatically converted into equivalent C# code, which is then compiled in the usual manner. This process is normally transparent to the application developer.
Images are copied by Uno.UI into the target project according to the directory structure and naming conventions of the target platform. Similarly, string resources (.resw
files) are converted into the native target format. Read more here. Again, this conversion process is normally transparent to the application developer.