Maui: [Spec] Slim Renderer Architecture

Created on 19 May 2020  ·  56Comments  ·  Source: dotnet/maui

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

proposal-open slim renderer

Most helpful comment

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.

All 56 comments

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
https://github.com/dotnet/maui/pull/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.

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.

@PureWeen
This URL
https://github.com/dotnet/maui/blob/slim-renderer-samples

gives 404, is it private?

@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

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:
https://github.com/dotnet/maui/discussions/103

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も未完成なのだと思います。そしてそれは、永遠に完成することはないでしょう。
アプリケーションプログラミングは、もっとターゲットの環境の差異から独立できるようにすべきだと考えます。

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jsuarezruiz picture jsuarezruiz  ·  6Comments

qcjxberin picture qcjxberin  ·  5Comments

Joshua-Ashton picture Joshua-Ashton  ·  9Comments

sim756 picture sim756  ·  16Comments

probonopd picture probonopd  ·  50Comments