dotnet/maui

[Spec] Slim Renderer Architecture

StephaneDelcroix opened this issue · 87 comments

WARNING: this spec is still a WIP, we're still experimenting with this concept

Description

Slim renderers architecture benefits from multi-targetting and single-project features.

Example

EntryRenderer.cs

public partial class EntryRenderer {
   public static PropertyMapper<IView> ViewMapper = new PropertyMapper<IView> {
	
     // Add your own method to map to any property         
     [nameof(IView.BackgroundColor)] = MapBackgroundColor

   };
}

EntryRenderer.iOS.cs

// You don’t need to register a new renderer.
public partial class EntryRenderer
{
     // You know what method to call because you named it!
   public static void MapBackgroundColor (IViewRenderer renderer, IView view)
     {
        // You don’t need to call any base methods here or worry about order.
   
        // Every renderer is consistent; you know where the native view is.
          var nativeView = (NativeView)renderer.NativeView;
          var color = view.BackgroundColor;

          if (color != null) {

            // Phew! That was easy!	        
            nativeView.BackgroundColor = UIColor.FromRGB (204, 153, 255);
          }
     }
}

Standardization of renderers

All the default renderers will be ported to this architecture, for all platforms

Registration of renderers

The rendererRegistrar will exists on the dependency service and be accessed by serviceCollection.Get<IRendererRegistrar>(), allowing control to which renderer is associated to which control

Interfaces on renderers

Mapper concept

The property mapper is responsible for triggering actions in response property changes. A slim renderer itself does not subscribe to the property changes, but some declared actions are executed in response to changes.

The property mapper property of a control is public static and can be extended by user code.

The property mapper plays no role in the feedback loop (button clicked, text entered)

TODO: discuss what to use for mapper key. string or object ? It'd be nice to avoid string comparison in case when we can compare references (in case of BindableProperties)

How to use legacy custom renderers

How to use third-party controls depending on old renderers

How to complement existing renderers

The new extensibility model for this architecture is based on the property mapper. When you want to add support for a new property, it only requires mapping the new property. For the property to exists, subclassing the control is necessary, but subclassing the renderer is not.

Backward Compatibility

Wether we want to keep backward compatibility with existing custom renderers, or subclasses of old renderers will influence the architecture of this

Difficulty : very high

Xamarin forms wpf renderers and some of android renderers such as ButtonRenderer are fast, and we know what does "fast" mean here.
Are these renderers will be fast or not?
Thanks in advance.

@ysmoradi Yep! These new renderers will follow the fast renderer pattern (i.e., no wrapper view around the main view). We plan to do this for all platforms, not just Android and WPF.

Please don't try to stay backwards compatible at all costs. This is something new. It does not have to be compatible with XF. You can make something better.

Why not to make UI framework with own set of controls without any kind of mappings and behavioral logic fully written on c# that would be rendered with Skia graphics library? As people use strongly customized design there is no need in trying to match platform design guidelines. The only need is possibility of flexible customizations. Please correct me if i'm missing something, but i don't understand why benefit is over Renderer architecture.

With this approach, is it possible to write a cross-platform renderer instead of the platform-specific renderer? Like mapping Button control with skia-sharp control .

Platform renderer is a bad design. As you see, there are lots of xamarin control libs that don't support UWP due to the platform limit.
Take an example, the shadow in UWP. You can't get a corner shadow from a corner button (of course, you can change the button template to do this, but that's another thing).

I know it is very difficult to build a cross platform render. But flutter told us this is feasible. In the long term, a cross-platform renderer is the best solution.

I think render entire app as custom 2d canvas might work seamlessly for mobile app.

But it might not work for desktop app or complex app because there are so many user actions that need to be re-implemented like drag-drop, text selection, keyboard shortcut to manipulate text and so on.

Why not to make UI framework with own set of controls without any kind of mappings and behavioral logic fully written on c# that would be rendered with Skia graphics library? As people use strongly customized design there is no need in trying to match platform design guidelines. The only need is possibility of flexible customizations. Please correct me if i'm missing something, but i don't understand why benefit is over Renderer architecture.

I think render entire app as custom 2d canvas might work seamlessly for mobile app.

But it might not work for desktop app or complex app because there are so many user actions that need to be re-implemented like drag-drop, text selection, keyboard shortcut to manipulate text and so on.

Why not to make UI framework with own set of controls without any kind of mappings and behavioral logic fully written on c# that would be rendered with Skia graphics library? As people use strongly customized design there is no need in trying to match platform design guidelines. The only need is possibility of flexible customizations. Please correct me if i'm missing something, but i don't understand why benefit is over Renderer architecture.

You're absolutely right about all of this stuff, but the team is not forced to choose the only one approach. I think this all about lack of time. I mean they just need to release a "brand new" fully crossplatform ui framework in a year together with .net 6. And and it's much less risky to take good old time-tested framework as the basis. It's ok and it should be. But i believe that in long time run custom 2d canvas rendering have much more benefits and really deserves to be called "cross platform". Xamarin forms is really good thing and it has a huge progress for today. But it's time to move on. Microsoft and xamarin teams have very clever engineers and they probably considering such an approach or maybe even have some connections with http://avaloniaui.net/ as a trump card

Why not to make UI framework with own set of controls without any kind of mappings and behavioral logic fully written on c# that would be rendered with Skia graphics library? As people use strongly customized design there is no need in trying to match platform design guidelines. The only need is possibility of flexible customizations. Please correct me if i'm missing something, but i don't understand why benefit is over Renderer architecture.

It could be cool to have 4-th render default grey one for Skia developers will 100% change it for sure to deliver rich design,
For back combability would leave those 3 as they are but add " draw it yourself dear developer"_skia_render and take 90% responsibility for it developer.

If the concept of renderers is to be maintained, can thought be given to eliminating the bridge between shared UI code and renderers via INotifyPropertyChanged and event handlers? i.e.

  • Instead of setting a property on the shared control and a PropertyChanged event being propagated, can the property be mapped and set directly on the platform renderer?
  • Instead of calling a method on the shared control and an event being fired and handled by the renderer, can the method be mapped and involved directly on the platform renderer?

INotifyPropertyChanged is great for MVVM design and loosely-couple view models, but has always felt clunky as a bridge mechanism between the shared UI code and platform renderers. This in turn would lead to better performance, less 'chattiness' between the shared UI and renderer layer and a better developer experience.

This is long but worth watching for some "inside baseball" on Maui.
https://www.youtube.com/watch?v=_MGh3xipWm4

It sounds like the architecture of Maui will support both platform-rendered controls and canvas-drawn controls, and furthermore that the noble @Clancey will be continuing to work on a skia-based render set for Maui which will not only work in the MVU flavour of Maui but also for the MVVM pattern.

At first glance Maui seemed like a rebranding of Forms, but on closer inspection it is a restructuring of the Forms architecture to make its layers more loosely coupled and thereby support many of the things we are asking about in this thread. Fun times ahead.

This is slightly off topic, but is something I've wanted to ask just because of its relevance to this exact thing:

How does memory work with SKCanvasView (or Skia in general)? Does each one always take up memory proportional to its size? Does this change if it overlaps others?

If, for example I had a gradient control (renderer written in Skia) and over the top of that I had a semi transparent button (renderer written in Skia) would that take up twice as much memory, or is the graphics context somehow shared? How about if Skia controls overlapped non-Skia controls?

I've considered implementing some fancy graphics controls in Forms using Skia before, but not understanding how the memory works has always caused enough concern that I haven't.

@GalaxiaGuy I think using a skia control overlapped on a non-skia control, just like a winform control hosted on a wpf control. You can do this, but not the best.
If you have two controls rendered by SKCanvasView, the graphics context will not be shared. The best way is to composite the two rendered and draw it on a single canvas.
In my test, the SkiaSharp performance is not so bad if you just do some static things. And I try to do some animations, the CPU usage is a little high on my laptop.

Why are so many people obsessed with Skia? A good rendering spec would be agnostic to the rendering engine used at the low level. If a particular platform renderer wants to use Skia (or Direct2D or OpenGL or whatever) that shouldn't be something the application layer should have to worry about.

The biggest promise of XAML with WPF ages ago, was the idea of Lookless Controls where the actual graphics of the controls were deferred to templates. Xamarin Forms used XAML without this ability, and this was its weakest point, only years later partially fixed by the Drawing spec.
I don't think that we need yet another set of interfaces and abstractions over existing components in various OSs and frameworks, but a XAML-based truly lookless controls - templated with platform-agnostic visual primitives and platform-specific graphic rendering backends. And sure, the default template may as well be the actual native control, but the holy grail is the define-once-use-everywhere graphic templates.

The biggest promise of XAML with WPF ages ago, was the idea of Lookless Controls where the actual graphics of the controls were deferred to templates. Xamarin Forms used XAML without this ability, and this was its weakest point, only years later partially fixed by the Drawing spec.

Agreed! And you really need a very small number of rendering primitives to accomplish probably 99% of everything an app needs:

  • Borders (incl. options for drop shadow and rounded edges)
  • Lines/Ellipses/Rectangles
  • Plain text rendering
  • Plain text input
  • Rich text rendering
  • Rich text input
  • HTML rendering
  • Image presenter
  • Audio/Video presenter
  • Solid and Linear / Radial Gradient brushes

The XF rendering platforms have become so bloated because whenever a new type of control is added to the framework it's done with a new renderer rather than building on top of existing primitives within the framework.

Yes a lot more logic would have to be moved into the framework layer, the most challenging being when it comes to items controls (VirtualizingStackPanel is critical to having a scalable items viewer but has to my knowledge never been effectively ported outside of WPF because it's so complex). But with WPF being open source a lot of that can be ported over into MAUI now and I think this is finally the time when that should start happening.

you really need a very small number of rendering primitives to accomplish probably 99% of everything an app needs.

Uno platform is using this approach.

@velocitysystems

Instead of setting a property on the shared control and a PropertyChanged event being propagated, can the property be mapped and set directly on the platform renderer?

That's a big goal of this change as well. Once we're on the other side of these changes the renderers will have no idea what a BindableObject or INPC means

That's a big goal of this change as well. Once we're on the other side of these changes the renderers will have no idea what a BindableObject or INPC means

So a method on the renderer will get invoked by the framework whenever a BindableProperty value changes instead of the renderer having to subscribe to PropertyChanged?

@legistek right

This basically inverts the dependencies

So the renderers will just work against IButton.

And then System.Maui will add a reference to the renderers project opposed to right now how the renderers have a references to Xamarin.Forms.Core

I checked in a spike we have here
#66

So you can see what this might look like

I'll be doing a stream today at 3:30 PDT time with @davidortinau and we'll be talking about the slim renderers

https://www.twitch.tv/microsoftdeveloper

Join us! Check it out! And ask questions!

@PureWeen Unfortunately I missed it. Will there be a recording available on YouTube?

That's a big goal of this change as well. Once we're on the other side of these changes the renderers will have no idea what a BindableObject or INPC means.

That is huge, a real substantial improvement. No doubt too with the move to Maui, the complex inheritance model used in many of the renderers will be removed in favour of a more compositional approach?

Going to review #66 today.

Looking at #66, it is nice to see the slim renderers are built and invoked with 'bait-and-switch' rather than using reflection. Just a few thoughts:

  • Will Slim renderers address the GC issues, especially on Android where there is a mismatch between the managed and native control lifecycle? This is especially noticeable in child views in virtualized layouts leading to the dreaded ObjectDisposedException.
  • Will Slim renderers lead to the deprecation of Effect? Effects can be useful, but ultimately they add complexity and yet another potential for latency to the layout lifecycle.
  • How would a 'two-way' property work with the new renderer design? E.g. Let's say I have a MediaElement with a Position (TimeSpan) property. Setter updates the current position, and the getter retrieves the current position from the native media player i.e. AVPlayer, MediaPlayer. Is there a design for mapping a getter with slim renderers?

Will Slim renderers address the GC issues, especially on Android where there is a mismatch between the managed and native control lifecycle? This is especially noticeable in child views in virtualized layouts leading to the dreaded ObjectDisposedException.

We do have some ideas here!! We want to rework the disposal strategies a bit to hopefully resolve most if not all of the ODE exceptions. Right now we super aggressively dispose of everything in android/iOS but I'm fairly certain we can just rely on the GC to do what the GC does. If we just make sure to dereference everything and let the GC do the work that should help in a lot of these cases

Will Slim renderers lead to the deprecation of Effect? Effects can be useful, but ultimately they add complexity and yet another potential for latency to the layout lifecycle.

This is definitely a good thing to look into as we evolve this idea. Once we reach a final design for all this we'll take a look at effects. But, yes I could see effects being obsoleted as they are intended as a way to tap into native elements without having to go full renderer. Mappers basically obsolete effects

How would a 'two-way' property work with the new renderer design? E.g. Let's say I have a MediaElement with a Position (TimeSpan) property. Setter updates the current position, and the getter retrieves the current position from the native media player i.e. AVPlayer, MediaPlayer. Is there a design for mapping a getter with slim renderers?

We're still working this one out a bit. Correct me if I'm wrong @Clancey but the ActionMapper was our current approach for this yes? https://github.com/dotnet/maui/blob/slim-renderers/Maui.Core/PropertyMapper.cs#L91

How would a 'two-way' property work with the new renderer design? E.g. Let's say I have a MediaElement with a Position (TimeSpan) property. Setter updates the current position, and the getter retrieves the current position from the native media player i.e. AVPlayer, MediaPlayer. Is there a design for mapping a getter with slim renderers?

We're still working this one out a bit. Correct me if I'm wrong @Clancey but the ActionMapper was our current approach for this yes? https://github.com/dotnet/maui/blob/slim-renderers/Maui.Core/PropertyMapper.cs#L91

Not exactly. So the ActionMapper is the same thing as a PropertyMapper with the exception, they are not called during the SetElement phase. So, for things like WebView, GoBack. You don't want to call that during initialization but it's still something you need to communicate with the Renderer.

We already support 2 way mapping. i.e Entry. When the text value chances on the entry. the IEntry has a string Text {get;set;} and we simply set the value. So for media elements you have 2 options. One is simply set back the position/time when it changes. If you want to make it something you query instead. You can do that. The xplat views have access to the renderer. view.Renderer.NativeView as NativeMediaView You can now pull off any properties you want!

Here are some videos from our streams during Build

@Clancey 's here will be more in depth
https://www.youtube.com/watch?v=_MGh3xipWm4

I touch on them a little bit here with David
https://www.youtube.com/watch?v=lAmwjfZY1IM

How would a 'two-way' property work with the new renderer design? E.g. Let's say I have a MediaElement with a Position (TimeSpan) property. Setter updates the current position, and the getter retrieves the current position from the native media player i.e. AVPlayer, MediaPlayer. Is there a design for mapping a getter with slim renderers?

We're still working this one out a bit. Correct me if I'm wrong @Clancey but the ActionMapper was our current approach for this yes? https://github.com/dotnet/maui/blob/slim-renderers/Maui.Core/PropertyMapper.cs#L91

Not exactly. So the ActionMapper is the same thing as a PropertyMapper with the exception, they are not called during the SetElement phase. So, for things like WebView, GoBack. You don't want to call that during initialization but it's still something you need to communicate with the Renderer.

We already support 2 way mapping. i.e Entry. When the text value chances on the entry. the IEntry has a string Text {get;set;} and we simply set the value. So for media elements you have 2 options. One is simply set back the position/time when it changes. If you want to make it something you query instead. You can do that. The xplat views have access to the renderer. view.Renderer.NativeView as NativeMediaView You can now pull off any properties you want!

Another thing to consider here are Records which are coming in C#9. The speciality being the they are immutable and have init property accessor. So to make them useable in a two-way binding the mapper needs to be able to return a new instance using the with operator.

I really hope for views to be bindable to records, because this makes lot of thing easier when it comes to pure MVVM or even pure MVU.

Question: the diagram you posted has the Windows controls being rendered by Windows.UI.*, but as I understand it, that is now in the process of being deprecated and will not see any updates: all improvements to the fluent design renders are taking place in Microsoft.UI.* as part of the WinUI project. Can you please comment on this?

I think mapping to native controls is a big mistake, this is the terrible part of Xamarin.Forms, you can’t make unique and beautiful layouts easily, you had to follow the concept and approach of WPF and Flutter controls without appearances with a render engine written in C ++ using OpenGL / DirectX / Metal, as this facilitates portability, performance and flexibility in addition to not depending on platform structures that are continually changing.

The issue is here to talk about the new Architecture/ Property Mappers. Not what they map against. Just to re-iterate. Slim Render Architecture for native does not mean we will never, and can never do a drawn control approach. But this does allow us to mix and match native vs non-native controls where if you go purely drawn, it's more difficult. I plan to continue working on Skia based controls which follow the same Slim Renderer Architecture, including the drawing layer. https://github.com/Clancey/Comet/tree/dev/src/Comet.Skia/Handlers.

wjk commented

My 2¢ on this renderer thing (which I admit I don't entirely understand, TBH):

I had an idea about how we could implement both platform-rendered controls (e.g. wrapping UIButton) and lookless controls (a la WPF) using the same control class. It's quite simple, honestly: Have the Maui Button class use a control template, and remove all platform-specific renderer code from it. Then, provide an in-box template for Button that contains a ButtonRenderer. The ButtonRenderer is what talks to Cocoa/UIKit/UWP/etc, with platform-specific code for each UI toolkit, and the Button class used by the app developer simply forwards its properties to it. If the user wants to use a custom-drawn button, then they can simply override the template and use drawing classes (whatever that ends up looking like) instead of the ButtonRenderer, just as we do in WPF. I honestly don't know if this is already possible (or even already used) in Maui today, as I never took the time to understand Xamarin.Forms as deeply as I understand WPF.

Tell me what you think!

I'm trying to understand what Slim renderers would mean for different app models (MVVM, MVU, ...).

The initial diagram seems to tell that each different app model will have its own set of renderers.
But in my opinion, it would be better to have one set of renderers per type of rendering (e.g. render to native controls like XF, render to canvas, etc.).
The renderer doesn't need to be aware of the app model, it only needs to know what value is map to which property so it can apply the correct update to the underlying control.
Only the IButton will be implemented differently for each app model and will be responsible for calling the mapped functions of its renderer.

This is important because 3rd party libraries like Fabulous won't have the manpower of Microsoft to implement (with all the bugs coming with it) all the appropriate renderers for each control on each platform.

Another point is: the control interfaces (IButton) should be getter-only to be consumed by the renderers.
Renderers don't set values and each app model will shape the controls differently (BindableProperty, BindingObject, etc.).
For instance, Fabulous will have immutable views. Only internally, will it be authorized to set the mutation to the instance of IButton.

That way, Fabulous could directly use the IButton interface as a reader-view over its internal dictionary so the renderers can work.

// This is the type used by our users, sort of a Builder that return a new instance each time
// and append the set value to an internal list 
public struct Button
{
     public Button Text(string value) => (...);
     
     internal ReadOnlyDictionary<string, obj> Build() { ... }
}

// This will be an implementation of IButton, hidden from our users
internal class FabulousButton : IButton
{
    private ReadOnlyDictionary<string, obj> _properties;
    FabulousButton(ReadOnlyDictionary<string, obj> properties)
    {
        _properties = properties;
    }

    void Update(ReadOnlyDictionary<string, obj> properties)
    {
        var previousProperties = _properties;
        _properties = properties;

        // Diffing of the 2 dictionaries to determine what changed
        // and which mapped functions inside the renderer should be called
        (...)
    }

    public string Text => _properties["Text"];
}

@TimLariviere Everything you said is how it works :-)

The drawing there is confusing as far as the renderers.

The only part of this you'll need to be concerned about is the Fabulous Button and then everything else from there we'll take care of

For the most part the interfaces are readonly

This is the interface used by button
https://github.com/dotnet/maui/blob/slim-renderer-samples/Maui.Core/Views/IText.cs

All that's really on you (as far as the renderers) is to signal to the renderer that it should re-consume the IButton

For example, on the BindableObject version of all of this we're just calling the Renderer's updateproperty method here

https://github.com/dotnet/maui/blob/slim-renderer-samples/System.Maui.Core/VisualElement.cs#L1132

Some point (soon?) @Clancey will have a public version of Comet you can look at to see how he's doing it.

I would check out
https://github.com/dotnet/maui/blob/slim-renderer-samples

You can probably add your own Fabulous.Core head to that and then start adding implementations to the interfaces

@PureWeen Oh cool. Thanks, I'll try to play with the samples you linked to see how it goes.

@PureWeen @Clancey I’m sure the Maui team will be all over this, but please can the new Slim renderers favor composition over inheritance. Inheritance is useful, but unfortunately in XF it has made some of the renderer hierarchies incredibly complex and difficult to maintain.

@Rand-Random

https://github.com/dotnet/maui/tree/slim-renderer-samples

@velocitysystems

I’m sure the Maui team will be all over this, but please can the new Slim renderers favor composition over inheritance. Inheritance is useful, but unfortunately in XF it has made some of the renderer hierarchies incredibly complex and difficult to maintain.

That's how they are built. There's a very thin base class that just inherits directly from good ol' System.Object

https://github.com/dotnet/maui/blob/slim-renderer-samples/Maui.Core/Renderers/View/AbstractViewRenderer.Android.cs

And has no native ties.

From there the whole thing is defined through what's basically a Dictionary<string, Func>

https://github.com/dotnet/maui/blob/slim-renderer-samples/Maui.Core/Renderers/View/AbstractViewRenderer.cs#L31

Which basically operates like a decorator.

You can decorate mappers with additional mappers and you can inject your own func's etc..

We're aiming for 95 percent of users scenarios to be covered just by adding your own Func to the mapper or just accessing the native elements directly since it'll all be multi targeted

@PureWeen What would be the most appropriate channel to discuss the implementation of those slim renderers in your sample?

I have some questions like:

  • Will the default values be defined in a centralized place? In XF, they are currently defined when creating the BindableProperty fields but these will not be present depending on the app model.
  • Will the Application class also become (partially) an interface? It defines a lot of UI behaviors (resources, menu, main page) and would be great to implement differently.
  • Will Measure/Arrange/etc be extracted from the control interfaces? I don't think it really makes sense for app models to implement them differently.

Will the default values be defined in a centralized place? In XF, they are currently defined when creating the BindableProperty fields but these will not be present depending on the app model.

This is a good question. @Clancey ? Not sure if we've defined this yet. There's an initial setup phase where all the mappers get called with the current value of the properties (default value) but I'm not sure if we have a plan yet for default values and how those will be generalized

Will the Application class also become (partially) an interface? It defines a lot of UI behaviors (resources, menu, main page) and would be great to implement differently.

Yes! We're hoping to collapse all the application classes (native and xplat) down into a single application class. Why are you asking about this? I'm just curious your use case here so we can make sure to address

Will Measure/Arrange/etc be extracted from the control interfaces? I don't think it really makes sense for app models to implement them differently.

At this point that is the plan. The idea will be to extract all of our layout code out so that none of it depends on BindableObject/Property.. This way Blazor/Comet/other can just use a StackLayout and the result will be the same.

Why are you asking about this? I'm just curious your use case here so we can make sure to address

I'm not entirely sure of what I'd want yet. But in Fabulous, we don't currently have a good story for defining global styles and main menu (like for macOS). Since we let our users subclass the Application class themselves, we basically tell them to define resources/menu like they would in classic Xamarin.Forms.

So ideally, all the UI-related properties of Application would also be part of the view, that way we would be able to apply our view-diffing logic on it too.

Something like that

public interface IAppRoot
{
    IEnumerable<object> Resources { get; }
    IMenu MainMenu { get; }
    IPage MainPage { get; }
}

public class Application
{
    /// Bootstrapping and other logic of MAUI

   public IAppRoot Root { get; set; } // Replaces MainPage, which is typed for pages only
}

@PureWeen Another question: Who will be responsible for triggering events like TextChanged, Toggled, etc.? The controls or the renderers?

One thing I think would greatly simplify the implementation of other app models is the possibility to not trigger state-changing events when changes are programmatical.

For example, today, TextChanged on Entry is triggered both when the user writes something or when we do MyEntry.Text = "New value";.
I think reacting to a programmatic change is not really useful, and implicit which is bad for reasoning about the code.

Also this lead to an infinite loop on Android because the platform triggers its events with a slight delay and it forced Fabulous to go out of sync with no possibility to come back.
The only workaround we found was to first unsubscribe the event before setting the value and then resubscribing...

A curious question. When MAUI is architecture agnostic why are the controls named by architecture names? For example In the diagram above we have Maui.Mvvm.ButtonRenderer.Android? @PureWeen @Clancey

XF has something called Compressed Layouts (Which is buggy)
Do we've such as thing (without bugs for sure!) in MAUI?

I see how people react in this thread about having Flutter/Skia approach to render UI and I mostly agree with them.
I'm really glad that MAUI potentially will have support for custom/not native controls and renders.
However, I have to say that the ability to work with native UI secures the framework on the political side of things.
And yes, I'm pointing out on Apple. Due to the latest news, I wouldn't be surprised if at some point in time for some reason using Flutter would be considered as 'exploiting non-documented/restricted features' or 'not following Apple UI guidelines' and so on.

I see how people react in this thread about having Flutter/Skia approach to render UI and I mostly agree with them.
I'm really glad that in MAUI potentially will have support for custom/not native controls and renders.
However, I have to say that the ability to work with native UI secures the framework on the political side of things.
And yes, I'm pointing out on Apple. Due to the latest news, I wouldn't be surprised if at some point in time for some reason using Flutter would be considered as 'exploiting non-documented/restricted features' or 'not following Apple UI guidelines' and so on.

If MAUI supports the Web (like Flitter), then we can always render into WebView.
Apple is unlikely to ever dare to block WebView-based applications, because some large companies are represented in AppStore only through WebView

I see how people react in this thread about having Flutter/Skia approach to render UI and I mostly agree with them.
I'm really glad that in MAUI potentially will have support for custom/not native controls and renders.
However, I have to say that the ability to work with native UI secures the framework on the political side of things.
And yes, I'm pointing out on Apple. Due to the latest news, I wouldn't be surprised if at some point in time for some reason using Flutter would be considered as 'exploiting non-documented/restricted features' or 'not following Apple UI guidelines' and so on.

If MAUI supports the Web (like Flitter), then we can always render into WebView.
Apple is unlikely to ever dare to block WebView-based applications, because some large companies are represented in AppStore only through WebView

that's already against there guidelines - https://developer.apple.com/app-store/review/guidelines/#minimum-functionality

After having read a bit back and fourth what this whole new world of MAUI seems to be, please for the love of all that is holy actually make a write once use everywhere rendering engine like SKIA or an other multiplatform rendering engine, having to implement custom UI on each platform like in Xamarin Forms feels old and like it was a solution created in hell's seventh circle.

if backward compatibility is a must "just" make the new and modern render support a way to render older components, I've seen other platforms have neat solution for this, the most recently one I've used is in the unity's UI engine where the new modern UXML have a IMGUI Render.

@jackie0100
I fully agree

having to implement custom UI on each platform like in Xamarin Forms feels old and like it was a solution created in hell's seventh circle.

As for renderer implementation, what about the idea of an IView IS A native view (instead of an IView HAS A native view). ie inheritance instead of composition? This would lead to the fastest, leanest architecture with absolutely zero "Forms overhead". You're basically working with pure native views, and just a common interface.

Then you could do things like, over in iOS land, just cast your view to be a UIView, and add a native child to it (whatever type you want) because an IView is a UIView. Similarly, if you want to do 'native embedding', it's easy because an IView is a UIView, you could just add one of your IViews to your native view because they're the same thing. This would massively enable native <-> maui interopability, and with the highest level of performance and lowest memory consumption.

I kind of feel like prototyping this myself. Perhaps a weekend/evening project...

image

If MAUI supports the Web (like Flitter), then we can always render into WebView.

Don't need WebView on iOS: can render directly in OpenGL or Metal.

Or use Skia with either OpenGL or Metal underneath.

ability to work with native UI secures the framework on the political side of things. [Apple]

At some point, Apple removed from their written policy the requirement to use native UI widgets. I don't see any practical way they would reverse policy back to being restrictive.

Regardless, being able to work with native controls is a good option.

@legistek

Why are so many people obsessed with Skia? A good rendering spec would be agnostic to the rendering engine ...

While I totally agree about being "agnostic", there are a lot of details that must be implemented to render any interactive UI - if you go directly to OpenGL/Metal/Vulkan/whatever low-level rendering engine. People are obsessed with Skia because it is an effective middle layer between the app's UI concerns and the actual rendering engine: Skia handles a lot of what would have to be designed and implemented, if all you have is bare metal. No reason to reinvent this work. While it should not be the only target, it is an extremely valuable and mature target, that will make it much easier to, say, move from OpenGL to Vulkan.

I also suspect that targetting Skia would be much less cumbersome than Xamarin Forms maintenance of two parallel widget heirarchies - the cross-platform widgets and the native widgets.

Skia might even hasten the day that .Net Maui is highly performant in the browser. Again, because instead of building up from a low-level, of rendering you are starting at an appropriate mid-level abstraction. That would be a huge win.

Hi every one , don't forget it:
#103

rocuh commented

Having watched the recent maui videos, unless I'm mistaken it does seem there has been a drift to have more styled controls with the native control being overlayed with drawing done on the platform intedependant side. Whether its skia or some sort of batched interop to native canvas drawing I hope this approach is pursued! The XF platform renderer model has always ironically hurt the Microsoft UI platforms the most, being the least used.

I would also leave open the ability for a control to explicitly not to have a native component and for the layout compositor to detect this, it might allow an automated reduction in native views created (i.e. if all controls in a container are maui labels drawn with skia, it could make the container an SkView and just call the draw operation on the label child controls), on Android that would give speed boost in things like list elements that have lots of images + text controls for example.

I don't understand what a renderer is.
If the program for absorbing the visual differences of the target is called a renderer, it should be absorbed by Xamarin and MAUI altogether. If not, I think it's an unfinished Xamarin and MAUI. And it will never be completed.
I think application programming should be more independent of the differences in the target environment.

レンダラーというものが理解できません。
ターゲットのビジュアルに関する差異を吸収するためのプログラムをレンダラーというのであれば、それはXamarinやMAUIが全て吸収すべきです。そうではないのだとすると、それはXamarinもMAUIも未完成なのだと思います。そしてそれは、永遠に完成することはないでしょう。
アプリケーションプログラミングは、もっとターゲットの環境の差異から独立できるようにすべきだと考えます。

Will this enable the possibility to run in WebGL? C# already runs in Webassembly, so.... Native web interfaces (without plugins)?

@guidevnet - My guess is that https://skia.org/user/modules/canvaskit would be used as (a quick time-to-market) target in browsers:

Skia now offers a WebAssembly build for easy deployment of our graphics APIs on the web.

CanvasKit provides a playground for testing new Canvas and SVG platform APIs, enabling fast-paced development on the web platform. It can also be used as a deployment mechanism for custom web apps requiring cutting-edge features, ...

... WebGL context encapsulated as an SkSurface, allowing for direct drawing to an HTML canvas

Why are so many people obsessed with Skia? A good rendering spec would be agnostic to the rendering engine used at the low level. If a particular platform renderer wants to use Skia (or Direct2D or OpenGL or whatever) that shouldn't be something the application layer should have to worry about.

You are right!

XF is a good design,but It's very difficult to。

MAUI fixed XF The problem

There is going to be a <string,string> dictionary somehow at the heart of this project? PropertyMapper.cs . It's good to move away from .Net pre-generic horrors like INotifyPropertyChanged, but the solution isn't to jettison the .Net type system like this and replace it with strings.

There is no need for strings, and no need for any sort of dictionary lookup when changing a property. It's abandoning performance, type safety, and linker-friendliness.

Please tell me that the dictionary is for compile-time code-generation only, and that you are not really going to store on user systems dictionaries of all MAUI properties, and that when setting a property on a MAUI View it won't convert it to a string, look up a corresponding string, and only then set a property on a native view!

Skia handles a lot of what would have to be designed and implemented, if all you have is bare metal. No reason to reinvent this work.

Skia is rather slow, doesn't use GPU efficiently. It's also huge, practically unmaintainable, and hard to even compile.

As for the complexity, I don't disagree but I was able to do most of that alone in my spare time https://github.com/Const-me/Vrmac Sure Microsoft has more resources.

Skia is rather slow, doesn't use GPU efficiently. It's also huge, practically unmaintainable, and hard to even compile.

I've build my own UI framework that is rendered 100%using SkiaSharp. It displays complex screens with list views, scrolling, lots of events and rich effects. Everything is rendered at 120 FPS on a OPPO phone. I'm not sure based on what you state that Skia is slow.

Try doing the same with XF. I've spent years working on XF projects. It will lag or freeze, it will be ugly and inconstent depending on the target plateform.

OPPO phone

A brand is irrelevant. If you phone is a modern one you bought for $1000, you gonna get 120 FPS almost regardless on the rendering method.

On a $200 smartphone, especially if the display is 1080p or higher, especially if the phone is couple years old, things will be different.

And another thing. Performance of the phones is on the higher end of the spectrum, due to very high production volumes. Modern phone SoCs use 7nm or 5nm process and are very performant in general.

In addition to phones, .NET supports much slower devices. Raspberry Pi 4 has an SoC made with 28nm process, that’s comparable to Snapdragon 427 from 2016.

I'm not sure based on what you state that Skia is slow.

It’s much faster than Xamarin and many others. However, much slower, and much less power efficient, than Direct2D or nVidia’s nv_path_rendering.

This was not always the case, when Direct2D was introduced only Windows had good enough GPU API (Direct3D 11), but by now, other platforms are more or less on par. It’s now possible to implement a functional equivalent of Direct2D on top of GLES3, Vulkan or Metal, I’ve made a proof of concept that runs on Raspberry Pi 4.

Update: it’s technically possible to implement the support inside Skia. After all, they already consume nv_path_rendering GL extension when available, and even use Direct2D for a few things (text, mostly). However, this makes it very hard for .NET to implement some important features.

  1. 3D rendering integration, see <D3DImage> in WPF or <SwapChainPanel> in UWP.
  2. Accelerated video playback, see <MediaElement>
  3. Custom effects, see WPF bitmap effects or IBasicVideoEffect interface in UWP.

OPPO phones manufactures phones that costs under 200$, that's way I precised the brand as an argument for good performances.

It’s much faster than Xamarin and many others. However, much slower, and much less power efficient, than Direct2D or nVidia’s nv_path_rendering.

Thanks for the clarification.

Raspberry Pi 4 has an SoC made with 28nm process, that’s comparable to Snapdragon 427 from 2016.

Not sure raspberry Pi was made to display rich user interfaces. But even if you'd want it, i'm pretty sure the framework I've worked on shows good perfs and those devices, As I rely on caching to avoid unecessary redrawing. With my spare time I managed to have such results.. As you said : Sure Microsoft has more resources.

Personnaly I see no disqualifers at using a renderer that runs smooths on all kinds of devices , that addresses the vast majority of the use cases, as a cross renderer. Especially when compared to what's actually proposed...
Getting inconsistency in the app design and app behavior between device targets is hell for app editors. Not even talking about perfs. I recommanded my clients to use flutter instead of XF because of that. I want to beleive in MAUI but looks like i'm going to still recommand flutter after all. Which i'm truly disapointed at. Will see the final product of course.

OPPO phones manufactures phones that costs under 200$

Right, but they also manufacture phones which cost well above $1000.

Not sure raspberry Pi was made to display rich user interfaces

Not the case now, but it could be, even when rendering on a 4k display. Technically, the GPU is not too bad.

I see no disqualifers at using a renderer that runs smooths on all kinds of devices

My proof-of-concept library is not pixel perfect but it’s close. I’ve compared between Raspberry Pi 4 backed by GLES 3.1, and Windows 10 backed by Direct3D 12. It doesn’t use native controls. On the API surface it’s somewhat close to Skia (more specifically, I’ve tried to re-implement Direct2D), but unlike Skia and similar to D2D, it’s designed to leverage modern 3D GPUs. Under the hood it uses a third-party library called diligent engine.

Especially when compared to what's actually proposed

Indeed, what’s proposed is just horrible. If I would choose between 2 solutions, what’s proposed and Skia, I would pick Skia no questions asked. However, even ignoring the performance, with Skia these 3 use cases (integrating 3D-rendered content, video playback, custom effects) are all very hard. Personally I don’t care about custom effects, but the software I work on often does need 3D content and/or video.

Why we are not considering Silverlight like approach to drawing the controls in Framework level than, having wrappers around custom renderers (Is it because of apple's restrictions).
I support consistency over native look. It's really a pain in the a** to check and modify each and every platform. I believe WPF also uses a similar approach, though it looks like a native button, they just have an embedded Windows XP, 7 and 8 styles / theme hidden beneath.

@vibeeshan025

Is it because of apple's restrictions

I believe Flutter is a counter-example.

I support consistency over native look.

Strongly agree.

Besides the consistency, .NET runtime currently runs on platforms which don’t have any native look at all, like embedded Linux. I would love to have officially supported GPU-targeted GUI framework which runs on top of OS kernel, bypassing X11/Wayland/XFCE desktop managers. I did it couple times myself (besides the one I linked above, for another projects I consumed nanovg instead) but an MS-supported option would be awesome. Even if I have to plug my own windowing and input support, that’s still relatively small amount of complexity compared to GPU integration, 2D rendering, and all the higher-level stuff on top of that.

I believe WPF also uses a similar approach

You’re correct, WPF re-implemented everything on top of DirectX 9.0c. At the time, DX9 was the most compatible way to access a 3D GPU on Windows. It has a few issues probably due to limitations of D3D9 and quirks of old GPUs https://jeremiahmorrill.wordpress.com/2011/02/14/a-critical-deep-dive-into-the-wpf-rendering-system/ but still pretty darn good in practice.

Only a few isolated WPF components integrate native controls, most notably the embeddable web browser.

If you want "consistency" then you can use Flutter, Web, QT or your custom renderer or anything. What is lacking is exactly native renderers. You have to write your app at least 3 times for Windows, MacOS and Linux if you want it to be native. I know most of Windows users doesn't care that their apps looks... bad, doesn't integrate with the OS and you have to learn every app but on other platforms, especially MacOS people do care. You choose Mac because it's nice and has nice apps. Yet another cross platform renderer is useless for most... Why use this then if I can just do that in web with millions of available resources and devs...

@davidskuza

Flutter

Desktop support is still in beta: https://flutter.dev/desktop It has a non-trivial learning curve because it includes a purposedly-built programming language, i.e. harder to find developers.

Web

Requires a desktop environment, doesn’t work on bare metal. Electron apps tend to consume lots of memory. JavaScript is not always the best tool for the job: it’s slow, and very hard to integrate with native code, people usually do it with an embedded JSON RPC web server in the same process.

QT

While mature, widely used, and generally good quality, the usability is not great because C++. Also, for many use cases it requires a commercial version, which is very expensive.

your custom renderer

Extremely hard to do well. I know because I have made one: https://github.com/Const-me/Vrmac/

most of Windows users doesn't care that their apps looks

That was not always the case. As demonstrated by WPF, it is possible to re-create look and feel of native controls on top of a GPU-based renderer.

Desktop support is still in beta: https://flutter.dev/desktop It has a non-trivial learning curve because it includes a purposedly-built programming language, i.e. harder to find developers.

Good this is stable.

Requires a desktop environment, doesn’t work on bare metal. Electron apps tend to consume lots of memory. JavaScript is not always the best tool for the job: it’s slow, and very hard to integrate with native code, people usually do it with an embedded JSON RPC web server in the same process.

You know that non of the arguments are "valid" (can't find better word). Look around, Slack, VS Code, Teams, Discord, WhatsApp etc. Most of them built with web/electron because it's fast time to market and good enough performance. If any of your argument would be true those apps would be written in C, C++ or Rust.

Requires a desktop environment,

? does MAUI target embedded?

doesn’t work on bare metal

? MAUI also needs runtime?

JavaScript is not always the best tool for the job: it’s slow

I wouldn't say it's slow. Language it's not perfect either but what to do. Nothing is even close to perfect if you are working on it long enough. For now JavaScript happened to be the most universal "best tool for the job" ranging from UI, server side to embedded.

and very hard to integrate with native code, people usually do it with an embedded JSON RPC web server in the same process

Wow, never saw anybody doing like that. Literally if you don't know C/C++ env the easiest way is to build node addon... Node is the only platform when I have integrated native code and did not want to abandon the job. You don't even need to configure anything besides your source files...

Extremely hard to do well. I know because I have made one

That was not always the case. As demonstrated by WPF, it is possible to re-create look and feel of native controls on top of a GPU-based renderer.

Then you should probably know how many attempts at this were made and how many are successful. Also Microsoft recreating GUI they created in WPF doesn't even count. They built it, they control every aspect of it, they can even integrate it in the OS. They built in once for Win32 with software renderer then why they could not with DirectX.

I just wanted to say that there are people who would be happy for native UI library because I saw everybody who posted here wants MonoGame with UI on top.
Also with current state of the world even if such platform would exists (custom drawn controls) why as a business should I choose that if there is a web. The community, ecosystem. There are even people who don't even know C# exists but can code crossplatform apps.

Right now if you would want to build native app for every platform with native controls, UX and integrations you would probably have to use C/C++/Rust/JS for Linux, C# for Windows but if you build for Linux then it's better to stay with C++ anyway to share logic and on MacOS integrate using Swift. If MAUI would allow to use native UI/UX but code everything/most in C# then there is an argument and a huge one. wxWidgets would be probably the only competition with that possibility and I doubt if this would be done correctly anybody would even consider it... When I found this project I got so hyped that there will be such thing supported. (Okay, if React Native Windows would have been released then there is also that but with MVU and maybe if needed some tweaks to the language we would have first contender vs JavaScript).

After 2-3 years of stable Flutter I don't see people jumping to it because such platforms will always be inferior. People are more hyped for Jetpack Compose. And yet, Flutter is solving problem which is not solved as for web on mobile with low end phones isn't so performant in regions like India which is a massive market for mobile apps.

Also if you think that custom rendered controls would solve all your cross platform "consistency" problems then I think that will not be the case. You will be consistently below average besides single platform of choice (at most equal with web). If you search for custom UI's (there are software e.g. in music industry which were built that way) or also with web there are problems which cannot be solved universally anyway.
"Why does my font doesn't look native and sharp? Oh, you used custom renderer not the native one system provided. Use native one. You used native renderers everywhere? Why now this layout is different, there are bigger/smaller margins, spacings and paddings, looks ugly, whole app looks weird, you have to change that!".

does MAUI target embedded?

MAUI does not exist yet, we’re discussing proposed architecture here. The .NET runtime does indeed target embedded, Microsoft even ships ARM Linux binaries. They depends on Linux kernel of course, but not much else (a Unicode-related OS package).

Language it's not perfect either but what to do.

I would like to be able to implement equivalent UX in cross-platform .NET.

many attempts at this were made and how many are successful

Some of them were. Flutter has successfully re-implemented native controls of iOS and Android. It’s not a rocket science, just GUI design and attention to details.

Microsoft recreating GUI they created in WPF doesn't even count

Why not? They were different people with decades of time between these projects. Win32 GUI (gdi32.dll, comctl32.dll, etc.) is in large parts a legacy from 16-bit Windows 3.x.

why as a business should I choose that if there is a web

That’s a great question. Here’s a few reasons.

I don’t believe HTML5 is an optimal substrate for rich GUI apps. It was designed for documents as opposed to GUI. For instance, data binding and data templates are important parts of MS XAML platforms. With modern web, technically we have react/angular/etc., but they are implemented by third parties on top of HTML DOM. These features are fundamentally complicated, and are way more usable when provided by the platform. In business terms, this means for many projects with complicated rich GUI, HTML/Electron will take more money to develop compared to XAML.

Web browsers don’t work on top of bare OS kernel, they need a desktop environment.

Web browsers are huge, not all people are happy downloading 100MB installer for a chat app.

3D graphics is limited to WebGL, which is not good enough compared to appropriate GPU APIs (Direct3D on Windows, Metal on OSX and iOS, Vulkan on most modern Linuxes including Android).

Hardware accelerated video is limited to HTML’s <video> element, which is OK for media consumption but some desktop software does authoring.

Many other use cases need to integrate with native APIs for various reasons. HTML/JavaScript doesn’t have low latency audio, has very limited support for custom input devices, doesn’t support custom peripherals, doesn’t support protected storage (Windows) or keychain services (Apple), and so on. These features are not too hard in modern .NET and don’t require writing a single line of C++, native interop is good.

if you would want to build native app for every platform with native controls

The success of Electron shows that’s not what many people want. They want consistent GUI across all platforms, while keeping software development costs reasonable (e.g. avoiding C++).

Another thing, among modern platforms, only OSX, iOS and Android have decent native controls.

On Windows everything is in XAML nowadays, the look and feel is completely defined with these styles and templates. Note the recent 0.5 milestone of WinUI 3.

On Linux there’re multiple competing desktop environments, with different native control libraries and UX conventions.

I don't see people jumping to it because such platforms will always be inferior

I think their main mistake was inventing Dart, instead of embedding something like .NET, Go, or JVM.

which cannot be solved universally anyway

They are all solvable, look at modern web browsers or game engines. However, they are very expensive to solve well across multiple platforms, too many edge cases: DPI scaling, display rotation, right to left languages, accessibility, and many others.

The .NET runtime does indeed target embedded, Microsoft even ships ARM Linux binaries. They depends on Linux kernel of course, but not much else (a Unicode-related OS package).

ARM is an architecture. What does it have to do with embedded? More modern than x86. Even in 2nd sentence you mention Linux...

I would like to be able to implement equivalent UX in cross-platform .NET.

Avalonia.

Some of them were. Flutter has successfully re-implemented native controls of iOS and Android. It’s not a rocket science, just GUI design and attention to details.

Yeah... go and try use new OS things. Oh, you can't. Best you get is "work in progress".

Why not? They were different people with decades of time between these projects. Win32 GUI (gdi32.dll, comctl32.dll, etc.) is in large parts a legacy from 16-bit Windows 3.x.

Oh, I forgot. Win32 GUI is legacy, doesn't change. You can work 10 years on your UI and still you won't be obsolete. Even more irrelevant.

I don’t believe HTML5 is an optimal substrate for rich GUI apps. It was designed for documents as opposed to GUI. For instance, data binding and data templates are important parts of MS XAML platforms.

Who cares what you believe? It has been done, it works, customers are happy enough and they decide what to we do. Not to mention more and more (all my current work) customers want web and doesn't care about desktop anymore (in general business trade). Now with COVID and remote work even more. I know companies which were "offline" first, "security" concerned but after of year of remote work they decided to go "online".

It was designed for documents as opposed to GUI.

So what? I don't get this argument. XAML is designed like HTML (but worse) and now you are happy because marketing told you another.

Web browsers don’t work on top of bare OS kernel, they need a desktop environment.

The availability of CI, test runners and crawlers? You run everything on Windows Server? Haha.

Web browsers are huge, not all people are happy downloading 100MB installer for a chat app.

But for .NET core they are. Not to mention PWA's or things like Neutrino which uses bundled browser with OS.

3D graphics is limited to WebGL, which is not good enough compared to appropriate GPU APIs (Direct3D on Windows, Metal on OSX and iOS, Vulkan on most modern Linuxes including Android).

There is WebGPU incoming. It's so good people extracted it from browser and they are using it from C++/Rust for common abstraction over all platforms. If you need more performance than that probably GCed language is not enough either.

Many other use cases need to integrate with native APIs for various reasons. HTML/JavaScript doesn’t have low latency audio, has very limited support for custom input devices, doesn’t support custom peripherals, doesn’t support protected storage (Windows) or keychain services (Apple), and so on. These features are not too hard in modern .NET and don’t require writing a single line of C++, native interop is good.

At most yet, faster than MAUI it seems. Web Audio? Web Serial? Web Usb? It for sure supports more, easily. But that are Web standards and you are talking about running on OS in things like Electron... you can have more than .NET in there. For sure this way is not limited.

The success of Electron shows that’s not what many people want. They want consistent GUI across all platforms, while keeping software development costs reasonable (e.g. avoiding C++).

What? It's not what "people" want. It's what developers want. You missed last 10 years of evolution or what? You are still on Windows XP, right? Oh no, that would be Windows 7.

I know more people avoiding .NET that anything else.

On Windows everything is in XAML nowadays, the look and feel is completely defined with these styles and templates. Note the recent 0.5 milestone of WinUI 3.

Yes, aka big mistake but we have to support it. Adoption of XAML around the world perfectly shows how much people like it. "MVU" is good confirmation about this statement. And no, your world and people using C# are not examples it's good if it's the only sensible option. Also "MVU" as it people here are calling happened to be so good dev experience that everyone want's to do it.

On Linux there’re multiple competing desktop environments, with different native control libraries and UX conventions.

AFAIK Gnome and KDE. Other things are just your "consistent" custom cross platform GUI.

I think their main mistake was inventing Dart, instead of embedding something like .NET, Go, or JVM.

They did but it was too slow for 120 fps.

They are all solvable, look at modern web browsers or game engines. However, they are very expensive to solve well across multiple platforms, too many edge cases: DPI scaling, display rotation, right to left languages, accessibility, and many others.

You just given the same examples as I did. Go render some text that looks everywhere the same. Impossible because browser renders font with system font renderer and there is always some differences. Starting with layouting for fonts which different engines do differently or bugs. Game engines are even more incosistent because they do not have features like an UI framework have. You see a few bitmaps on screens and you think they are consistent but run that game on e.g. 21:9 and half of UI doesn't render because it thinks screen ended, other half tries for some reason to stretch etc. They do everything often manually so if you did not tested that it crumbles. Refund. Funny enough the best scalable, crossplatform, complex game UIs were made with web and webkit, or Coherent...

Sorry, this discussion seems OT. Can a moderator chime in and delete some of the comments above (and this one)?

Very welcoming community.

Desktop support is still in beta: https://flutter.dev/desktop It has a non-trivial learning curve because it includes a purposedly-built programming language, i.e. harder to find developers.

Good this is stable.

Requires a desktop environment, doesn’t work on bare metal. Electron apps tend to consume lots of memory. JavaScript is not always the best tool for the job: it’s slow, and very hard to integrate with native code, people usually do it with an embedded JSON RPC web server in the same process.

You know that non of the arguments are "valid" (can't find better word). Look around, Slack, VS Code, Teams, Discord, WhatsApp etc. Most of them built with web/electron because it's fast time to market and good enough performance. If any of your argument would be true those apps would be written in C, C++ or Rust.

Requires a desktop environment,

? does MAUI target embedded?

doesn’t work on bare metal

? MAUI also needs runtime?

JavaScript is not always the best tool for the job: it’s slow

I wouldn't say it's slow. Language it's not perfect either but what to do. Nothing is even close to perfect if you are working on it long enough. For now JavaScript happened to be the most universal "best tool for the job" ranging from UI, server side to embedded.

and very hard to integrate with native code, people usually do it with an embedded JSON RPC web server in the same process

Wow, never saw anybody doing like that. Literally if you don't know C/C++ env the easiest way is to build node addon... Node is the only platform when I have integrated native code and did not want to abandon the job. You don't even need to configure anything besides your source files...

Extremely hard to do well. I know because I have made one

That was not always the case. As demonstrated by WPF, it is possible to re-create look and feel of native controls on top of a GPU-based renderer.

Then you should probably know how many attempts at this were made and how many are successful. Also Microsoft recreating GUI they created in WPF doesn't even count. They built it, they control every aspect of it, they can even integrate it in the OS. They built in once for Win32 with software renderer then why they could not with DirectX.

I just wanted to say that there are people who would be happy for native UI library because I saw everybody who posted here wants MonoGame with UI on top.
Also with current state of the world even if such platform would exists (custom drawn controls) why as a business should I choose that if there is a web. The community, ecosystem. There are even people who don't even know C# exists but can code crossplatform apps.

Right now if you would want to build native app for every platform with native controls, UX and integrations you would probably have to use C/C++/Rust/JS for Linux, C# for Windows but if you build for Linux then it's better to stay with C++ anyway to share logic and on MacOS integrate using Swift. If MAUI would allow to use native UI/UX but code everything/most in C# then there is an argument and a huge one. wxWidgets would be probably the only competition with that possibility and I doubt if this would be done correctly anybody would even consider it... When I found this project I got so hyped that there will be such thing supported. (Okay, if React Native Windows would have been released then there is also that but with MVU and maybe if needed some tweaks to the language we would have first contender vs JavaScript).

After 2-3 years of stable Flutter I don't see people jumping to it because such platforms will always be inferior. People are more hyped for Jetpack Compose. And yet, Flutter is solving problem which is not solved as for web on mobile with low end phones isn't so performant in regions like India which is a massive market for mobile apps.

Also if you think that custom rendered controls would solve all your cross platform "consistency" problems then I think that will not be the case. You will be consistently below average besides single platform of choice (at most equal with web). If you search for custom UI's (there are software e.g. in music industry which were built that way) or also with web there are problems which cannot be solved universally anyway.
"Why does my font doesn't look native and sharp? Oh, you used custom renderer not the native one system provided. Use native one. You used native renderers everywhere? Why now this layout is different, there are bigger/smaller margins, spacings and paddings, looks ugly, whole app looks weird, you have to change that!".

C# and .NET are cross platform

I have built several apps in xamarin forms, recently I switched to the flutter, what I instantly noticed is, ease of writing UI. I built a simple dashboard UI (refer below) within 1.5 days, if it is xamarin forms it would take me at least 3-4 days(as per my experience). Hot reload works like a charm in flutter(but most of the time it sucks in xamarin forms especially if your writing a custom renderer for a button, you cant see preview).

Screenshot 2021-05-17 at 1 52 53 PM

I don't want to write a custom renderer for even simple things(Shadows, Elevations, etc), which is a tedious task, please find a way to avoid custom renderers as much as possible. Writing animations also very simple which is not the case in xamarin forms.

From a backend perspective C# is pretty solid in terms of (MVVM, DI, Design patterns) hands down!

I've been developing with Xamarin.Forms since its inception. Every client I've worked for has wanted as close to an identical UI as possible on all target platforms. Clients do not want or need native controls/widgets/views to be rendered typically. It is a rare edge case. All clients I've worked for have adopted Xamarin because existing .NET developers could use C#/.NET to build mobile apps, while being able to consume existing libraries without reinventing the wheel. Clients and developers I've spoken to want Microsoft to ditch the native UI approach, and to emulate the Flutter and UNO approach of rendering controls independently of the constraints of the platform. The majority of development time is spent trying to tweak the UI to make it look identical on both platforms for current Xamarin developers. With the release of Flutter 2.2, it is becoming increasingly difficult to rationalize further investment in MAUI until this becomes THE primary architecture for the platform. Mimicking the Flutter/UNO approach highly simplifies the development process on your end, and working prototypes are already alive and well that should be used to accelerate development. This is where developers want MS and the MAUI/Xamarin team to invest in. The holy grail for developers is for MS to emulate Flutter's architecture while giving we developers the massive advantage of being able to continue to use .NET and C# so we don't have to reinvent the wheel by rewriting libraries in an immature language like Dart. Finally, Microsoft is investing in working with Google to allow Flutter to target Windows.. MS should instead be investing in competing directly with Google by building MAUI the way its veteran developers want. If MAUI goes native UI first at launch, it will be obsolete the day it is released. If this happens, after seven years of using Xamarin/.NET to develop mobile apps, I will move on and invest in Flutter instead, because at least Google has its head on straight enough to build the tools we want and need.

@brencode there's room in the market for different solutions and different approaches. I agree that for the most part Flutter is dominating this space as Google seems to be investing heavily in marketing (they see this as a loss leader for their cloud platform). I see that Maui and Uno are attempting to solve same issue but coming from different directions. If you want 100% consistency of layout etc, then Uno is the answer. If you want a framework for rapidly scaffolding an application, the Maui with pieces like Shell will give you that jump start - it also is the way to go if your company/customer is fixated on not using third party frameworks (I don't understand this but it does exist with some orgs)

@brencode but MAUI will be implement also with draw controls by https://github.com/dotnet/Microsoft.Maui.Graphics.Controls

Xamarin is very good from a backend perspective, I can quickly build enterprise architecture patterns with ease, but when it comes to UI, I need to spend a lot of time to match UI pixel perfectly with a mockup. Please focus on the UI part that's all we want. why don't you guys use Skia Sharp to draw controls on canvas which can eliminate all UI renderers. let me show a simple example, I want to create a simple round corner Entry like below. see how much code I need to write for xamarin vs flutter.

6wSSE

Flutter way

TextField(
 decoration: new InputDecoration(
     border: new OutlineInputBorder(
       borderRadius: const BorderRadius.all(
         const Radius.circular(10.0),
       ),
     ),
     filled: true,
     hintStyle: new TextStyle(color: Colors.grey[800]),
     hintText: "Type in your text",
     fillColor: Colors.white70),
)

Xamarin Way

//UI
< controls: CustomEntry IsPassword = "True"
x: Name = "txtEmail"
Style = "{StaticResource EntryStyle}" > </controls:CustomEntry>

/ / Custom Entry
public class CustomEntry: Entry {}

//Android Shape

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" > 
    <stroke android:width="1dp" android:color="#e7e7e7" /> 
    <solid android:color="#fafafa" /> 
    <padding android:left="1dp" android:right="1dp" android:top="1dp" /> 
    <corners android:radius="5dp" />
</shape>

//Android Renderer
public class CustomEntryRenderer: EntryRenderer {
	public CustomEntryRenderer(Context context) : base(context) {
		AutoPackage = false;
	}
	protected override void OnElementChanged(ElementChangedEventArgs<Entry> e) 
        { 
            base.OnElementChanged(e);
            if (Control != null) 
            { 
                Control.Background = Android.App.Application.Context.GetDrawable(Resource.Drawable.rounded_corners); 
                Control.Gravity = GravityFlags.CenterVertical; 
                Control.SetPadding(10, 0, 0, 0); } 
            }
        }
}

//iOS Renderer
public class CustomEntryRenderer: EntryRenderer {
	protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) {
		base.OnElementPropertyChanged(sender, e);
		Control.Layer.BorderWidth = 0;
		Control.BorderStyle = UITextBorderStyle.None;
	}
}

see how much code it took to show a simple round corner text field in xamarin forms vs flutter? , this is where lot of people going away from xamarin.

Xamarin is very good from a backend perspective, I can quickly build enterprise architecture patterns with ease, but when it comes to UI, I need to spend a lot of time to match UI pixel perfectly with a mockup. Please focus on the UI part that's all we want. why don't you guys use Skia Sharp to draw controls on canvas which can eliminate all UI renderers. let me show a simple example, I want to create a simple round corner Entry like below. see how much code I need to write for xamarin vs flutter.

6wSSE

Flutter way

TextField(
 decoration: new InputDecoration(
     border: new OutlineInputBorder(
       borderRadius: const BorderRadius.all(
         const Radius.circular(10.0),
       ),
     ),
     filled: true,
     hintStyle: new TextStyle(color: Colors.grey[800]),
     hintText: "Type in your text",
     fillColor: Colors.white70),
)

Xamarin Way

//UI
< controls: CustomEntry IsPassword = "True"
x: Name = "txtEmail"
Style = "{StaticResource EntryStyle}" > </controls:CustomEntry>

/ / Custom Entry
public class CustomEntry: Entry {}

//Android Shape

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" > 
    <stroke android:width="1dp" android:color="#e7e7e7" /> 
    <solid android:color="#fafafa" /> 
    <padding android:left="1dp" android:right="1dp" android:top="1dp" /> 
    <corners android:radius="5dp" />
</shape>

//Android Renderer
public class CustomEntryRenderer: EntryRenderer {
	public CustomEntryRenderer(Context context) : base(context) {
		AutoPackage = false;
	}
	protected override void OnElementChanged(ElementChangedEventArgs<Entry> e) 
        { 
            base.OnElementChanged(e);
            if (Control != null) 
            { 
                Control.Background = Android.App.Application.Context.GetDrawable(Resource.Drawable.rounded_corners); 
                Control.Gravity = GravityFlags.CenterVertical; 
                Control.SetPadding(10, 0, 0, 0); } 
            }
        }
}

//iOS Renderer
public class CustomEntryRenderer: EntryRenderer {
	protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) {
		base.OnElementPropertyChanged(sender, e);
		Control.Layer.BorderWidth = 0;
		Control.BorderStyle = UITextBorderStyle.None;
	}
}

see how much code it took to show a simple round corner text field in xamarin forms vs flutter? , this is where lot of people going away from xamarin.

Try the .NET Maui C# MVU - Comet

https://github.com/dotnet/Comet

I've been developing with Xamarin.Forms since its inception. Every client I've worked for has wanted as close to an identical UI as possible on all target platforms. Clients do not want or need native controls/widgets/views to be rendered typically. It is a rare edge case. All clients I've worked for have adopted Xamarin because existing .NET developers could use C#/.NET to build mobile apps, while being able to consume existing libraries without reinventing the wheel. Clients and developers I've spoken to want Microsoft to ditch the native UI approach, and to emulate the Flutter and UNO approach of rendering controls independently of the constraints of the platform. The majority of development time is spent trying to tweak the UI to make it look identical on both platforms for current Xamarin developers. With the release of Flutter 2.2, it is becoming increasingly difficult to rationalize further investment in MAUI until this becomes THE primary architecture for the platform. Mimicking the Flutter/UNO approach highly simplifies the development process on your end, and working prototypes are already alive and well that should be used to accelerate development. This is where developers want MS and the MAUI/Xamarin team to invest in. The holy grail for developers is for MS to emulate Flutter's architecture while giving we developers the massive advantage of being able to continue to use .NET and C# so we don't have to reinvent the wheel by rewriting libraries in an immature language like Dart. Finally, Microsoft is investing in working with Google to allow Flutter to target Windows.. MS should instead be investing in competing directly with Google by building MAUI the way its veteran developers want. If MAUI goes native UI first at launch, it will be obsolete the day it is released. If this happens, after seven years of using Xamarin/.NET to develop mobile apps, I will move on and invest in Flutter instead, because at least Google has its head on straight enough to build the tools we want and need.

MAUI C# MVU - Comet. Also, .NET Maui will have support for drawn UI using GraphicsControl

https://github.com/dotnet/Comet

https://github.com/dotnet/Microsoft.Maui.Graphics.Controls

https://github.com/dotnet/Microsoft.Maui.Graphics

I've seen this conversation happening in a few places, and I thought I'd share my own experience (despite the fact the plural of "anecdote" is not "data").

This does not match my experience with Xamarin. The clients I've worked with have mostly fallen into two categories:

Those that don't care about the UI details. Pixel perfect UI is not interesting to them compared to delivering functionality. For them, sharing business logic between platforms (and sometimes with a C# server) that can be delivered quickly is number one priority.

Those that want a native looking app. Most of these have avoided Forms (for example because they want to use native navigation patterns (Android supports a lot more patterns that are a challenge on iOS)). This has started to change now with some Forms embedding and the fact that I can use effects to apply some existing native styling code to Forms controls has made that much easier.

A final note that is finally getting more attention is accessibility. I've just started to scratch the surface of advanced accessibility stuff iOS and Android support natively, and being able to get access to that (even in Forms) is important. Re-implementing controls would involve a lot of work on that front.

(Bit of a cheap shot, but do your designers who care about the pixels being perfect for sighted users care about the screenreader announcements being perfect for blind users?)

A final note that is finally getting more attention is accessibility. I've just started to scratch the surface of advanced accessibility stuff iOS and Android support natively, and being able to get access to that (even in Forms) is important. Re-implementing controls would involve a lot of work on that front.

(Bit of a cheap shot, but do your designers who care about the pixels being perfect for sighted users care about the screenreader announcements being perfect for blind users?)

Yes, accessibility is important. Issue with current platform specific controls is that they are highly coupled by design. Single control can contain behavior logic, drawing logic, user input handling and accessibility all tied to a single platform APIs. Customizing just a single aspect of a control in a multiplatform application means re-implementing same thing multiple times with vastly different APIs.

Providing unified abstractions over lower-level platform APIs and building controls on top, gives multiplatform developers ability to customize controls at much lower cost. Unified APIs enable developers to implement, for example, customized drawing or customized reactions to scroll input only once, instead of writing separate implementation for each platform.

Even though the cost of developing framework like this is higher in the beginning, the cost in the long run is probably smaller, as creating and maintaining loosely coupled multiplatform controls is much more cost effective for framework developers too. Look how basic Xamarin.Forms controls still are after so many years and how quickly Flutter controls are evolving. Most of Xamarin.Forms controls implement only functionality that is common on all platforms and are often missing functionality that is provided just by a single vendor. For controls build on top of unified abstractions of low-level APIs, this becomes a non-issue. Every functionality implemented in a control is instantly avaliable on all platforms. Framework controls also don't need to lag behind platform specific controls anymore, as framework can provide even controls or functionality that is not avaliable in any platform's UI framework.

If there is any issue with providing accessibility features for custom-drawn controls, it is up to platform vendors to provide better APIs for this kind of multiplatform frameworks.