Maui: [Spéc] Architecture de rendu mince

Créé le 19 mai 2020  ·  56Commentaires  ·  Source: dotnet/maui

ATTENTION : cette spécification est toujours un WIP, nous expérimentons toujours ce concept

La description

L'architecture des moteurs de rendu minces bénéficie de fonctionnalités de multi-ciblage et de projet unique.

Exemple

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);
          }
     }
}

Standardisation des moteurs de rendu

Tous les moteurs de rendu par défaut seront portés sur cette architecture, pour toutes les plateformes

Enregistrement des moteurs de rendu

Le rendererRegistrar existera sur le service de dépendance et sera accessible par serviceCollection.Get<IRendererRegistrar>() , permettant de contrôler quel moteur de rendu est associé à quel contrôle

Interfaces sur les moteurs de rendu

Concept de mappeur

Le mappeur de propriétés est chargé de déclencher des actions dans les modifications de propriétés de réponse. Un moteur de rendu mince lui-même ne souscrit pas aux modifications de propriété, mais certaines actions déclarées sont exécutées en réponse aux modifications.

La propriété du mappeur de propriétés d'un contrôle est public static et peut être étendue par le code utilisateur.

Le mappeur de propriétés ne joue aucun rôle dans la boucle de rétroaction (bouton cliqué, texte saisi)

À FAIRE : discuter de ce qu'il faut utiliser pour la clé de mappeur. string ou object ? Ce serait bien d'éviter la comparaison de chaînes au cas où nous pourrions comparer des références (en cas de BindableProperties)

Comment utiliser les rendus personnalisés hérités

Comment utiliser des contrôles tiers en fonction des anciens moteurs de rendu

Comment compléter les moteurs de rendu existants

Le nouveau modèle d'extensibilité de cette architecture est basé sur le mappeur de propriétés. Lorsque vous souhaitez ajouter la prise en charge d'une nouvelle propriété, il suffit de mapper la nouvelle propriété. Pour que la propriété existe, le sous-classement du contrôle est nécessaire, mais le sous-classement du moteur de rendu ne l'est pas.

Rétrocompatibilité

Que nous souhaitions conserver la compatibilité descendante avec les moteurs de rendu personnalisés existants ou que les sous-classes d'anciens moteurs de rendu influenceront l'architecture de ce

Difficulté : très élevée

proposal-open slim renderer

Commentaire le plus utile

N'essayez pas de rester rétrocompatible à tout prix. C'est quelque chose de nouveau. Il n'a pas besoin d'être compatible avec XF. Vous pouvez faire quelque chose de mieux.

Tous les 56 commentaires

Xamarin forme les moteurs de rendu wpf et certains moteurs de rendu Android tels que ButtonRenderer sont rapides, et nous savons ce que signifie « rapide » ici.
Ces moteurs de rendu seront-ils rapides ou non ?
Merci d'avance.

@ysmoradi Ouais ! Ces nouveaux moteurs de rendu suivront le modèle de rendu rapide (c'est-à-dire, pas de vue wrapper autour de la vue principale). Nous prévoyons de le faire pour toutes les plateformes, pas seulement Android et WPF.

N'essayez pas de rester rétrocompatible à tout prix. C'est quelque chose de nouveau. Il n'a pas besoin d'être compatible avec XF. Vous pouvez faire quelque chose de mieux.

Pourquoi ne pas créer un framework d'interface utilisateur avec son propre ensemble de contrôles sans aucun type de mappage et de logique comportementale entièrement écrit sur c# qui serait rendu avec la bibliothèque graphique Skia ? Comme les gens utilisent une conception fortement personnalisée, il n'est pas nécessaire d'essayer de respecter les directives de conception de la plate-forme. Le seul besoin est la possibilité de personnalisations flexibles. Veuillez me corriger si quelque chose me manque, mais je ne comprends pas pourquoi l'architecture de Renderer est avantageuse.

Avec cette approche, est-il possible d'écrire un moteur de rendu multiplateforme au lieu du moteur de rendu spécifique à la plateforme ? Comme la cartographie Contrôle des boutons avec contrôle skia-sharp.

Le moteur de rendu de la plate-forme est une mauvaise conception. Comme vous le voyez, de nombreuses bibliothèques de contrôle xamarin ne prennent pas en charge UWP en raison de la limite de la plate-forme.
Prenons un exemple, l'ombre dans UWP. Vous ne pouvez pas obtenir une ombre d'angle à partir d'un bouton d'angle (bien sûr, vous pouvez modifier le modèle de bouton pour le faire, mais c'est une autre chose).

Je sais qu'il est très difficile de créer un rendu multiplateforme. Mais Flutter nous a dit que c'était faisable. À long terme, un moteur de rendu multiplateforme est la meilleure solution.

Je pense que le rendu de l'application entière en tant que toile 2D personnalisée pourrait fonctionner de manière transparente pour l'application mobile.

Mais cela peut ne pas fonctionner pour les applications de bureau ou les applications complexes, car de nombreuses actions utilisateur doivent être réimplémentées, telles que glisser-déposer, sélection de texte, raccourci clavier pour manipuler du texte, etc.

Pourquoi ne pas créer un framework d'interface utilisateur avec son propre ensemble de contrôles sans aucun type de mappage et de logique comportementale entièrement écrit sur c# qui serait rendu avec la bibliothèque graphique Skia ? Comme les gens utilisent une conception fortement personnalisée, il n'est pas nécessaire d'essayer de respecter les directives de conception de la plate-forme. Le seul besoin est la possibilité de personnalisations flexibles. Veuillez me corriger si quelque chose me manque, mais je ne comprends pas pourquoi l'architecture de Renderer est avantageuse.

Je pense que le rendu de l'application entière en tant que toile 2D personnalisée pourrait fonctionner de manière transparente pour l'application mobile.

Mais cela peut ne pas fonctionner pour les applications de bureau ou les applications complexes, car de nombreuses actions utilisateur doivent être réimplémentées, telles que glisser-déposer, sélection de texte, raccourci clavier pour manipuler du texte, etc.

Pourquoi ne pas créer un framework d'interface utilisateur avec son propre ensemble de contrôles sans aucun type de mappage et de logique comportementale entièrement écrit sur c# qui serait rendu avec la bibliothèque graphique Skia ? Comme les gens utilisent une conception fortement personnalisée, il n'est pas nécessaire d'essayer de respecter les directives de conception de la plate-forme. Le seul besoin est la possibilité de personnalisations flexibles. Veuillez me corriger si quelque chose me manque, mais je ne comprends pas pourquoi l'architecture de Renderer est avantageuse.

Vous avez tout à fait raison sur tout cela, mais l'équipe n'est pas obligée de choisir la seule approche. Je pense que tout cela est dû au manque de temps. Je veux dire qu'ils ont juste besoin de publier un « tout nouveau » framework d'interface utilisateur entièrement multiplateforme dans un an avec .net 6. Et il est beaucoup moins risqué de prendre comme base un bon vieux framework éprouvé. C'est bon et ça devrait l'être. Mais je pense que le rendu de toile 2D personnalisé à long terme a beaucoup plus d'avantages et mérite vraiment d'être appelé "cross platform". Les formulaires Xamarin sont vraiment une bonne chose et ils ont un énorme progrès pour aujourd'hui. Mais il est temps de passer à autre chose. Les équipes Microsoft et xamarin ont des ingénieurs très intelligents et ils envisagent probablement une telle approche ou ont peut-être même des liens avec http://avaloniaui.net/ comme atout

Pourquoi ne pas créer un framework d'interface utilisateur avec son propre ensemble de contrôles sans aucun type de mappage et de logique comportementale entièrement écrit sur c# qui serait rendu avec la bibliothèque graphique Skia ? Comme les gens utilisent une conception fortement personnalisée, il n'est pas nécessaire d'essayer de respecter les directives de conception de la plate-forme. Le seul besoin est la possibilité de personnalisations flexibles. Veuillez me corriger si quelque chose me manque, mais je ne comprends pas pourquoi l'architecture de Renderer est avantageuse.

Il pourrait être cool d'avoir le 4ème rendu gris par défaut pour que les développeurs de Skia le changeront à 100% à coup sûr pour offrir un design riche,
Pour le dos, le peignage laisserait ces 3 tels qu'ils sont, mais ajouterait " dessinez-le vous-même cher développeur"_skia_render et assumerez 90% de la responsabilité du développeur.

Si le concept de moteurs de rendu doit être maintenu, peut-on envisager d'éliminer le pont entre le code d'interface utilisateur partagé et les moteurs de rendu via INotifyPropertyChanged et les gestionnaires d'événements ? c'est à dire

  • Au lieu de définir une _propriété_ sur le contrôle partagé et un événement PropertyChanged en cours de propagation, la propriété peut-elle être mappée et définie directement sur le moteur de rendu de la plate-forme ?
  • Au lieu d'appeler une _method_ sur le contrôle partagé et un événement déclenché et géré par le moteur de rendu, la méthode peut-elle être mappée et impliquée directement sur le moteur de rendu de la plate-forme ?

INotifyPropertyChanged est idéal pour la conception MVVM et les modèles de vue à couple lâche, mais s'est toujours senti maladroit en tant que mécanisme de pont entre le code d'interface utilisateur partagé et les moteurs de rendu de la plate-forme. Cela conduirait à son tour à de meilleures performances, à moins de « bavardage » entre l'interface utilisateur partagée et la couche de rendu et une meilleure expérience de développement.

C'est long mais ça vaut le coup d'être regardé pour un peu de "base-ball à l'intérieur" à Maui.
https://www.youtube.com/watch?v=_MGh3xipWm4

Il semble que l'architecture de Maui prendra en charge à la fois les contrôles rendus par la plate-forme et les contrôles dessinés sur le canevas, et en outre, le noble @Clancey continuera à travailler sur un ensemble de rendu basé sur skia pour Maui qui ne fonctionnera pas seulement dans la saveur MVU de Maui mais aussi pour le modèle MVVM.

À première vue, Maui ressemblait à un changement de marque de Forms, mais à y regarder de plus près, il s'agit d'une restructuration de l'architecture Forms pour rendre ses couches plus lâchement couplées et ainsi prendre en charge bon nombre des questions que nous posons dans ce fil. Des moments amusants à venir.

C'est un peu hors sujet, mais c'est quelque chose que je voulais demander juste à cause de sa pertinence par rapport à cette chose exacte :

Comment fonctionne la mémoire avec SKCanvasView (ou Skia en général) ? Chacun occupe-t-il toujours de la mémoire proportionnellement à sa taille ? Cela change-t-il s'il en chevauche d'autres ?

Si, par exemple, j'avais un contrôle de dégradé (renderer écrit en Skia) et en plus j'avais un bouton semi-transparent (renderer écrit en Skia), cela prendrait-il deux fois plus de mémoire, ou le contexte graphique est-il en quelque sorte partagé ? Et si les contrôles Skia chevauchaient des contrôles non-Skia ?

J'ai déjà envisagé d'implémenter des contrôles graphiques sophistiqués dans Forms à l'aide de Skia, mais le fait de ne pas comprendre le fonctionnement de la mémoire a toujours causé suffisamment d'inquiétudes pour moi.

@GalaxiaGuy Je pense que l'utilisation d'un contrôle skia se chevauche sur un contrôle non skia, tout comme un contrôle winform hébergé sur un contrôle wpf. Vous pouvez le faire, mais pas le meilleur.
Si vous avez deux contrôles rendus par SKCanvasView , le contexte graphique ne sera pas partagé. Le meilleur moyen est de composer les deux rendus et de les dessiner sur une seule toile.
Dans mon test, les performances de SkiaSharp ne sont pas si mauvaises si vous ne faites que des choses statiques. Et j'essaye de faire quelques animations, l'utilisation du CPU est un peu élevée sur mon portable.

Pourquoi tant de gens sont-ils obsédés par Skia ? Une bonne spécification de rendu serait indépendante du moteur de rendu utilisé au bas niveau. Si un moteur de rendu de plate-forme particulier souhaite utiliser Skia (ou Direct2D ou OpenGL ou autre), cela ne devrait pas être quelque chose dont la couche d'application devrait s'inquiéter.

Il y a longtemps, la plus grande promesse de XAML avec WPF était l'idée de Lookless Controls où les graphiques réels des contrôles étaient reportés sur des modèles. Xamarin Forms utilisait XAML sans cette capacité, et c'était son point le plus faible, quelques années plus tard, partiellement corrigé par la spécification de dessin.
Je ne pense pas que nous ayons besoin d'un autre ensemble d'interfaces et d'abstractions sur les composants existants dans divers systèmes d'exploitation et frameworks, mais des contrôles vraiment sans apparence basés sur XAML - indépendantes de la plate-forme et des backends de rendu graphique spécifiques à la plate-forme. Et bien sûr, le modèle par défaut peut tout aussi bien être le contrôle natif réel, mais le Saint Graal est les modèles graphiques définis une fois pour toutes.

Il y a longtemps, la plus grande promesse de XAML avec WPF était l'idée de Lookless Controls où les graphiques réels des contrôles étaient reportés sur des modèles. Xamarin Forms utilisait XAML sans cette capacité, et c'était son point le plus faible, quelques années plus tard, partiellement corrigé par la spécification de dessin.

D'accord! Et vous avez vraiment besoin d'un très petit nombre de primitives de rendu pour accomplir probablement 99 % de tout ce dont une application a besoin :

  • Bordures (y compris les options pour l'ombre portée et les bords arrondis)
  • Lignes/Ellipses/Rectangles
  • Rendu de texte brut
  • Saisie de texte brut
  • Rendu de texte riche
  • Saisie de texte riche
  • Rendu HTML
  • Présentateur d'images
  • Présentateur audio/vidéo
  • Brosses Solides et Linéaires / Dégradés Radiaux

Les plates-formes de rendu XF sont devenues tellement pléthoriques car chaque fois qu'un nouveau type de contrôle est ajouté au framework, il est fait avec un nouveau moteur de rendu plutôt que de s'appuyer sur des primitives existantes dans le framework.

Oui, il faudrait déplacer beaucoup plus de logique dans la couche de framework, le plus difficile étant en ce qui concerne les contrôles d'éléments ( VirtualizingStackPanel est essentiel pour avoir une visionneuse d'éléments évolutive mais n'a, à ma connaissance, jamais été efficacement porté à l'extérieur de WPF parce que c'est si complexe). Mais avec WPF étant open source, une grande partie de cela peut être transférée dans MAUI maintenant et je pense que c'est enfin le moment où cela devrait commencer à se produire.

vous avez vraiment besoin d'un très petit nombre de primitives de rendu pour accomplir probablement 99% de tout ce dont une application a besoin.

La plate-forme Uno utilise cette approche.

@velocitysystems

Au lieu de définir une propriété sur le contrôle partagé et un événement PropertyChanged propagé, la propriété peut-elle être mappée et définie directement sur le moteur de rendu de la plate-forme ?

C'est aussi un grand objectif de ce changement. Une fois que nous serons de l'autre côté de ces changements, les moteurs de rendu n'auront aucune idée de ce que signifie un BindableObject ou INPC

C'est aussi un grand objectif de ce changement. Une fois que nous serons de l'autre côté de ces changements, les moteurs de rendu n'auront aucune idée de ce que signifie un BindableObject ou INPC

Ainsi, une méthode sur le moteur de rendu sera invoquée par le framework chaque fois qu'une BindableProperty change au lieu que le moteur de rendu doive s'abonner à PropertyChanged ?

@legistek à droite

Cela inverse essentiellement les dépendances

Ainsi, les moteurs de rendu fonctionneront simplement contre IButton.

Et puis System.Maui ajoutera une référence au projet de rendu par opposition à la façon dont les moteurs de rendu ont une référence à Xamarin.Forms.Core

J'ai vérifié dans un pic que nous avons ici
https://github.com/dotnet/maui/pull/66

Donc vous pouvez voir à quoi cela pourrait ressembler

Je ferai un stream aujourd'hui à 15h30 PDT avec @davidortinau et nous parlerons des moteurs de rendu minces

https://www.twitch.tv/microsoftdeveloper

Rejoignez-nous! Vérifiez-le! Et posez des questions !

@PureWeen Malheureusement, je l'ai raté. Y aura-t-il un enregistrement disponible sur YouTube ?

C'est aussi un grand objectif de ce changement. Une fois que nous serons de l'autre côté de ces changements, les moteurs de rendu n'auront aucune idée de ce que signifie un BindableObject ou INPC.

C'est énorme, une réelle amélioration substantielle. Il ne fait aucun doute qu'avec le passage à Maui, le modèle d'héritage complexe utilisé dans de nombreux moteurs de rendu sera supprimé au profit d'une approche plus compositionnelle ?

Je vais passer en revue le #66 aujourd'hui.

En regardant #66, il est agréable de voir que les moteurs de rendu minces sont construits et invoqués avec 'bait-and-switch' plutôt que d'utiliser la réflexion. Juste quelques réflexions :

  • Les moteurs de rendu Slim résoudront-ils les problèmes de GC, en particulier sur Android où il existe un décalage entre le cycle de vie des contrôles gérés et natifs ? Ceci est particulièrement visible dans les vues enfants dans les mises en page virtualisées menant au redoutable ObjectDisposedException .
  • Les moteurs de rendu Slim entraîneront-ils la dépréciation de Effect ? Les effets peuvent être utiles, mais en fin de compte, ils ajoutent de la complexité et un autre potentiel de latence au cycle de vie de la mise en page.
  • Comment une propriété « bidirectionnelle » fonctionnerait-elle avec la nouvelle conception du moteur de rendu ? Par exemple, disons que j'ai un MediaElement avec une propriété Position ( TimeSpan ). Le setter met à jour la position actuelle et le getter récupère la position actuelle du lecteur multimédia natif, c'est-à-dire AVPlayer , MediaPlayer . Existe-t-il une conception pour mapper un _getter_ avec des moteurs de rendu minces ?

Les moteurs de rendu Slim résoudront-ils les problèmes de GC, en particulier sur Android où il existe un décalage entre le cycle de vie des contrôles gérés et natifs ? Ceci est particulièrement visible dans les vues enfants dans les mises en page virtualisées menant à la redoutable ObjectDisposedException.

Nous avons des idées ici !! Nous souhaitons retravailler un peu les stratégies de suppression pour, espérons-le, résoudre la plupart, sinon la totalité, des exceptions ODE. À l'heure actuelle, nous éliminons tout de manière très agressive dans Android/iOS, mais je suis à peu près certain que nous pouvons simplement compter sur le GC pour faire ce que fait le GC. Si nous nous assurons simplement de tout déréférencer et de laisser le GC faire le travail, cela devrait aider dans beaucoup de ces cas

Les moteurs de rendu Slim entraîneront-ils la dépréciation d'Effet ? Les effets peuvent être utiles, mais en fin de compte, ils ajoutent de la complexité et un autre potentiel de latence au cycle de vie de la mise en page.

C'est certainement une bonne chose à examiner au fur et à mesure que nous évoluons cette idée. Une fois que nous aurons atteint un design final pour tout cela, nous examinerons les effets. Mais, oui, je pouvais voir les effets devenir obsolètes car ils sont conçus comme un moyen d'exploiter des éléments natifs sans avoir à utiliser le rendu complet. Mappers fondamentalement des effets obsolètes

Comment une propriété « bidirectionnelle » fonctionnerait-elle avec la nouvelle conception du moteur de rendu ? Par exemple, disons que j'ai un MediaElement avec une propriété Position (TimeSpan). Le setter met à jour la position actuelle et le getter récupère la position actuelle du lecteur multimédia natif, c'est-à-dire AVPlayer, MediaPlayer. Existe-t-il une conception pour mapper un getter avec des moteurs de rendu minces ?

Nous travaillons encore un peu sur celui-ci. Corrigez-moi si je me trompe @Clancey mais l'ActionMapper était notre approche actuelle pour cela oui? https://github.com/dotnet/maui/blob/slim-renderers/Maui.Core/PropertyMapper.cs#L91

Comment une propriété « bidirectionnelle » fonctionnerait-elle avec la nouvelle conception du moteur de rendu ? Par exemple, disons que j'ai un MediaElement avec une propriété Position (TimeSpan). Le setter met à jour la position actuelle et le getter récupère la position actuelle du lecteur multimédia natif, c'est-à-dire AVPlayer, MediaPlayer. Existe-t-il une conception pour mapper un getter avec des moteurs de rendu minces ?

Nous travaillons encore un peu sur celui-ci. Corrigez-moi si je me trompe @Clancey mais l'ActionMapper était notre approche actuelle pour cela oui? https://github.com/dotnet/maui/blob/slim-renderers/Maui.Core/PropertyMapper.cs#L91

Pas exactement. Donc, l'ActionMapper est la même chose qu'un PropertyMapper à l'exception qu'ils ne sont pas appelés pendant la phase SetElement. Donc, pour des choses comme WebView, GoBack. Vous ne voulez pas appeler cela pendant l'initialisation, mais c'est toujours quelque chose dont vous avez besoin pour communiquer avec le moteur de rendu.

Nous prenons déjà en charge la cartographie bidirectionnelle. c'est-à-dire l'entrée. Lorsque la valeur du texte risque sur l'entrée. le IEntry a un string Text {get;set;} et nous définissons simplement la valeur. Donc, pour les éléments multimédias, vous avez 2 options. On est simplement en arrière la position/heure quand elle change. Si vous voulez en faire quelque chose, vous interrogez plutôt. Vous pouvez le faire. Les vues xplat ont accès au moteur de rendu. view.Renderer.NativeView as NativeMediaView Vous pouvez maintenant retirer toutes les propriétés que vous voulez !

Voici quelques vidéos de nos flux pendant la construction

@Clancey 's here sera plus approfondi
https://www.youtube.com/watch?v=_MGh3xipWm4

Je les touche un peu ici avec David
https://www.youtube.com/watch?v=lAmwjfZY1IM

Comment une propriété « bidirectionnelle » fonctionnerait-elle avec la nouvelle conception du moteur de rendu ? Par exemple, disons que j'ai un MediaElement avec une propriété Position (TimeSpan). Le setter met à jour la position actuelle et le getter récupère la position actuelle du lecteur multimédia natif, c'est-à-dire AVPlayer, MediaPlayer. Existe-t-il une conception pour mapper un getter avec des moteurs de rendu minces ?

Nous travaillons encore un peu sur celui-ci. Corrigez-moi si je me trompe @Clancey mais l'ActionMapper était notre approche actuelle pour cela oui? https://github.com/dotnet/maui/blob/slim-renderers/Maui.Core/PropertyMapper.cs#L91

Pas exactement. Donc, l'ActionMapper est la même chose qu'un PropertyMapper à l'exception qu'ils ne sont pas appelés pendant la phase SetElement. Donc, pour des choses comme WebView, GoBack. Vous ne voulez pas appeler cela pendant l'initialisation, mais c'est toujours quelque chose dont vous avez besoin pour communiquer avec le moteur de rendu.

Nous prenons déjà en charge la cartographie bidirectionnelle. c'est-à-dire l'entrée. Lorsque la valeur du texte risque sur l'entrée. le IEntry a un string Text {get;set;} et nous définissons simplement la valeur. Donc, pour les éléments multimédias, vous avez 2 options. On est simplement en arrière la position/heure quand elle change. Si vous voulez en faire quelque chose, vous interrogez plutôt. Vous pouvez le faire. Les vues xplat ont accès au moteur de rendu. view.Renderer.NativeView as NativeMediaView Vous pouvez maintenant retirer toutes les propriétés que vous voulez !

Une autre chose à considérer ici sont les enregistrements qui arrivent en C#9. La spécialité étant qu'ils sont immuables et ont init accesseur de propriété with .

J'espère vraiment que les vues pourront être liées aux enregistrements, car cela facilite beaucoup les choses lorsqu'il s'agit de MVVM pur ou même de MVU pur.

Question : dans le diagramme que vous avez publié, les contrôles Windows sont rendus par Windows.UI.* , mais si j'ai bien compris, cela est maintenant en train d'être obsolète et ne verra aucune mise à jour : toutes les améliorations apportées aux rendus de conception fluides sont ayant lieu dans Microsoft.UI.* dans le cadre du projet WinUI. Pouvez-vous s'il vous plaît commenter cela?

Je pense que le mappage aux contrôles natifs est une grosse erreur, c'est la partie terrible de Xamarin.Forms, vous ne pouvez pas créer facilement des mises en page uniques et magnifiques, vous deviez suivre le concept et l'approche des contrôles WPF et Flutter sans apparence avec un rendu moteur écrit en C++ en utilisant OpenGL / DirectX / Metal, car cela facilite la portabilité, les performances et la flexibilité en plus de ne pas dépendre des structures de plate-forme qui changent continuellement.

Le numéro est ici pour parler des nouveaux Architecture/Property Mappers. Pas ce contre quoi ils mappent. Juste pour réitérer. Slim Render Architecture pour natif ne signifie pas que nous ne ferons jamais et ne pourrons jamais faire une approche de contrôle dessiné. Mais cela nous permet de mélanger et de faire correspondre les contrôles natifs et non natifs où si vous optez pour un dessin purement dessiné, c'est plus difficile. Je prévois de continuer à travailler sur des commandes basées sur Skia qui suivent la même architecture Slim Renderer, y compris la couche de dessin. https://github.com/Clancey/Comet/tree/dev/src/Comet.Skia/Handlers.

Mon 2¢ sur ce truc de rendu (que j'avoue que je ne comprends pas tout à fait, TBH):

J'avais une idée sur la façon dont nous pourrions implémenter les deux contrôles rendus par la plate-forme (par exemple, encapsuler UIButton) _et_ les contrôles sans apparence (à la WPF) en utilisant la même classe de contrôle. C'est assez simple, honnêtement : faites en sorte que la classe Maui Button utilise un modèle de contrôle et supprimez-en tout le code de rendu spécifique à la plate-forme. Ensuite, fournissez un modèle intégré pour Button qui contient un ButtonRenderer. Le ButtonRenderer est ce qui communique avec Cocoa/UIKit/UWP/etc, avec du code spécifique à la plate-forme pour chaque boîte à outils d'interface utilisateur, et la classe Button utilisée par le développeur de l'application lui transmet simplement ses propriétés. Si l'utilisateur souhaite utiliser un bouton personnalisé, il peut simplement remplacer le modèle et utiliser des classes de dessin (quel que soit ce à quoi cela ressemble) au lieu du ButtonRenderer, comme nous le faisons dans WPF. Honnêtement, je ne sais pas si cela est déjà possible (ou même déjà utilisé) à Maui aujourd'hui, car je n'ai jamais pris le temps de comprendre Xamarin.Forms aussi profondément que je comprends WPF.

Dis-moi ce que tu penses!

J'essaie de comprendre ce que les moteurs de rendu Slim signifieraient pour différents modèles d'applications (MVVM, MVU, ...).

Le diagramme initial semble indiquer que chaque modèle d'application différent aura son propre ensemble de moteurs de rendu.
Mais à mon avis, il serait préférable d'avoir un ensemble de moteurs de rendu par type de rendu (par exemple, rendu vers des contrôles natifs comme XF, rendu sur toile, etc.).
Le moteur de rendu n'a pas besoin de connaître le modèle d'application, il a seulement besoin de savoir quelle valeur est mappée à quelle propriété afin qu'il puisse appliquer la mise à jour correcte au contrôle sous-jacent.
Seul le IButton sera implémenté différemment pour chaque modèle d'application et sera chargé d'appeler les fonctions mappées de son moteur de rendu.

Ceci est important car les bibliothèques tierces comme Fabulous n'auront pas la main-d'œuvre de Microsoft pour implémenter (avec tous les bogues qui vont avec) tous les moteurs de rendu appropriés pour chaque contrôle sur chaque plate-forme.

Un autre point est le suivant : les interfaces de contrôle ( IButton ) doivent être en lecture seule pour être consommées par les moteurs de rendu.
Les moteurs de rendu ne définissent pas de valeurs et chaque modèle d'application façonnera les contrôles différemment (BindableProperty, BindingObject, etc.).
Par exemple, Fabulous aura des vues immuables. Ce n'est qu'en interne qu'il sera autorisé à définir la mutation sur l'instance de IButton .

De cette façon, Fabulous pourrait utiliser directement l'interface IButton comme vue de lecture sur son dictionnaire interne afin que les moteurs de rendu puissent fonctionner.

// 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 Tout ce que vous avez dit, c'est comment ça marche :-)

Le dessin y est déroutant en ce qui concerne les moteurs de rendu.

La seule partie de cela dont vous devrez vous préoccuper est le bouton fabuleux et tout le reste à partir de là, nous nous occuperons de

Pour la plupart les interfaces sont en lecture seule

Ceci est l'interface utilisée par le bouton
https://github.com/dotnet/maui/blob/slim-renderer-samples/Maui.Core/Views/IText.cs

Tout ce qui est vraiment sur vous (en ce qui concerne les moteurs de rendu) est de signaler au moteur de rendu qu'il doit réutiliser le IButton

Par exemple, sur la version BindableObject de tout cela, nous appelons simplement la méthode updateproperty du Renderer ici

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

À un moment donné (bientôt ?) @Clancey aura une version publique de Comet que vous pourrez consulter pour voir comment il s'y prend.

je vérifierais
https://github.com/dotnet/maui/blob/slim-renderer-samples

Vous pouvez probablement ajouter votre propre tête Fabulous.Core à cela, puis commencer à ajouter des implémentations aux interfaces

@PureWeen Oh cool. Merci, je vais essayer de jouer avec les exemples que vous avez liés pour voir comment ça se passe.

@PureWeen @Clancey Je suis sûr que l'équipe de Maui sera là-dessus, mais s'il vous plaît, les nouveaux moteurs de rendu Slim peuvent-ils favoriser la composition par rapport à l'héritage. L'héritage est utile, mais malheureusement, dans XF, il a rendu certaines des hiérarchies de rendu incroyablement complexes et difficiles à maintenir.

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

donne 404, est-ce privé ?

@Rand-Aléatoire

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

@velocitysystems

Je suis sûr que l'équipe de Maui s'occupera de tout cela, mais s'il vous plaît, les nouveaux moteurs de rendu Slim peuvent-ils favoriser la composition par rapport à l'héritage. L'héritage est utile, mais malheureusement, dans XF, il a rendu certaines des hiérarchies de rendu incroyablement complexes et difficiles à maintenir.

C'est ainsi qu'ils sont construits. Il existe une classe de base très fine qui hérite directement du bon vieux System.Object

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

Et n'a pas de liens indigènes.

À partir de là, tout est défini à travers ce qui est essentiellement un dictionnaire

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

Qui fonctionne essentiellement comme un décorateur.

Vous pouvez décorer les mappeurs avec des mappeurs supplémentaires et vous pouvez injecter vos propres fonctions, etc.

Nous visons à couvrir 95% des scénarios d'utilisateurs en ajoutant simplement votre propre Func au mappeur ou en accédant directement aux éléments natifs, car tout sera multi-ciblé.

@PureWeen Quel serait le canal le plus approprié pour discuter de la mise en œuvre de ces moteurs de rendu minces dans votre échantillon ?

J'ai quelques questions comme :

  • Les valeurs par défaut seront-elles définies dans un endroit centralisé ? Dans XF, ils sont actuellement définis lors de la création des champs BindableProperty mais ceux-ci ne seront pas présents selon le modèle d'application.
  • La classe Application deviendra-t-elle aussi (partiellement) une interface ? Il définit de nombreux comportements d'interface utilisateur (ressources, menu, page principale) et serait formidable à implémenter différemment.
  • Est-ce que Mesurer/Arranger/etc sera extrait des interfaces de contrôle ? Je ne pense pas qu'il soit vraiment logique que les modèles d'applications les implémentent différemment.

Les valeurs par défaut seront-elles définies dans un endroit centralisé ? Dans XF, ils sont actuellement définis lors de la création des champs BindableProperty mais ceux-ci ne seront pas présents selon le modèle d'application.

C'est une bonne question. @Clancey ? Je ne sais pas si nous avons déjà défini cela. Il y a une phase de configuration initiale où tous les mappeurs sont appelés avec la valeur actuelle des propriétés (valeur par défaut) mais je ne sais pas si nous avons encore un plan pour les valeurs par défaut et comment celles-ci seront généralisées

La classe Application deviendra-t-elle aussi (partiellement) une interface ? Il définit de nombreux comportements d'interface utilisateur (ressources, menu, page principale) et serait formidable à implémenter différemment.

Oui! Nous espérons regrouper toutes les classes d'application (natives et xplat) en une seule classe d'application. Pourquoi posez-vous des questions à ce sujet ? Je suis juste curieux de connaître votre cas d'utilisation ici afin que nous puissions nous assurer d'aborder

Est-ce que Mesurer/Arranger/etc sera extrait des interfaces de contrôle ? Je ne pense pas qu'il soit vraiment logique que les modèles d'applications les implémentent différemment.

À ce stade, c'est le plan. L'idée sera d'extraire tout notre code de mise en page afin qu'aucun d'entre eux ne dépende de BindableObject/Property. De cette façon, Blazor/Comet/other peut simplement utiliser un StackLayout et le résultat sera le même.

Pourquoi posez-vous des questions à ce sujet ? Je suis juste curieux de connaître votre cas d'utilisation ici afin que nous puissions nous assurer d'aborder

Je ne suis pas encore tout à fait sûr de ce que je voudrais. Mais dans Fabulous, nous n'avons actuellement pas de bonne histoire pour définir les styles globaux et le menu principal (comme pour macOS). Puisque nous laissons nos utilisateurs sous-classer eux-mêmes la classe Application, nous leur disons essentiellement de définir des ressources/menu comme ils le feraient dans Xamarin.Forms classique.

Donc, idéalement, toutes les propriétés liées à l'interface utilisateur d'Application feraient également partie de la vue, de cette façon nous serions en mesure d'appliquer notre logique de différence de vue sur celle-ci également.

Quelque chose comme ca

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 Une autre question : qui sera responsable du déclenchement d'événements tels que TextChanged , Toggled , etc. ? Les contrôles ou les moteurs de rendu ?

Une chose qui, à mon avis, simplifierait grandement la mise en œuvre d'autres modèles d'applications est la possibilité de ne pas déclencher d'événements de changement d'état lorsque les changements sont programmés.

Par exemple, aujourd'hui, TextChanged sur Entry est déclenché à la fois lorsque l'utilisateur écrit quelque chose ou lorsque nous faisons MyEntry.Text = "New value"; .
Je pense que réagir à un changement de programme n'est pas vraiment utile, et implicite, ce qui est mauvais pour raisonner sur le code.

Cela a également conduit à une boucle infinie sur Android car la plate-forme déclenche ses événements avec un léger retard et a forcé Fabulous à se désynchroniser sans possibilité de revenir.
La seule solution de contournement que nous avons trouvée consistait à d'abord vous désabonner de l'événement avant de définir la valeur, puis de vous réabonner...

Une question curieuse. Lorsque MAUI est indépendant de l'architecture, pourquoi les contrôles sont-ils nommés par des noms d'architecture ? Par exemple Dans le schéma ci-dessus, nous avons Maui. Mvvm .ButtonRenderer.Android ? @PureWeen @Clancey

XF a quelque chose qui s'appelle Compressed Layouts (ce qui est bogué)
Avons-nous une telle chose (sans bugs à coup sûr !) dans MAUI ?

Je vois comment les gens réagissent dans ce fil à propos de l'approche Flutter/Skia pour rendre l'interface utilisateur et je suis plutôt d'accord avec eux.
Je suis vraiment heureux que MAUI prenne potentiellement en charge les contrôles et les rendus personnalisés/non natifs.
Cependant, je dois dire que la possibilité de travailler avec une interface utilisateur native sécurise le cadre du côté politique des choses.
Et oui, je fais remarquer sur Apple. En raison des dernières nouvelles, je ne serais pas surpris qu'à un moment donné, pour une raison quelconque, l'utilisation de Flutter soit considérée comme « exploiter des fonctionnalités non documentées/restreintes » ou « ne pas suivre les directives de l'interface utilisateur Apple », et ainsi de suite.

Je vois comment les gens réagissent dans ce fil à propos de l'approche Flutter/Skia pour rendre l'interface utilisateur et je suis plutôt d'accord avec eux.
Je suis vraiment heureux que MAUI prenne potentiellement en charge les contrôles et les rendus personnalisés/non natifs.
Cependant, je dois dire que la possibilité de travailler avec une interface utilisateur native sécurise le cadre du côté politique des choses.
Et oui, je fais remarquer sur Apple. En raison des dernières nouvelles, je ne serais pas surpris qu'à un moment donné, pour une raison quelconque, l'utilisation de Flutter soit considérée comme « exploiter des fonctionnalités non documentées/restreintes » ou « ne pas suivre les directives de l'interface utilisateur Apple », et ainsi de suite.

Si MAUI prend en charge le Web (comme Flitter), nous pouvons toujours effectuer un rendu dans WebView.
Il est peu probable qu'Apple ose jamais bloquer les applications basées sur WebView, car certaines grandes entreprises ne sont représentées dans l'AppStore que via WebView.

Je vois comment les gens réagissent dans ce fil à propos de l'approche Flutter/Skia pour rendre l'interface utilisateur et je suis plutôt d'accord avec eux.
Je suis vraiment heureux que MAUI prenne potentiellement en charge les contrôles et les rendus personnalisés/non natifs.
Cependant, je dois dire que la possibilité de travailler avec une interface utilisateur native sécurise le cadre du côté politique des choses.
Et oui, je fais remarquer sur Apple. En raison des dernières nouvelles, je ne serais pas surpris qu'à un moment donné, pour une raison quelconque, l'utilisation de Flutter soit considérée comme « exploiter des fonctionnalités non documentées/restreintes » ou « ne pas suivre les directives de l'interface utilisateur Apple », et ainsi de suite.

Si MAUI prend en charge le Web (comme Flitter), nous pouvons toujours effectuer un rendu dans WebView.
Il est peu probable qu'Apple ose jamais bloquer les applications basées sur WebView, car certaines grandes entreprises ne sont représentées dans l'AppStore que via WebView.

c'est déjà contre ces directives - https://developer.apple.com/app-store/review/guidelines/#minimum -functionality

Après avoir lu un peu en arrière ce que semble être ce tout nouveau monde de MAUI, s'il vous plaît pour l'amour de tout ce qui est saint, faites un moteur de rendu d'écriture une fois utilisé partout comme SKIA ou un autre moteur de rendu multiplateforme, devant implémenter des L'interface utilisateur sur chaque plate-forme, comme dans Xamarin Forms, semble vieille et comme si c'était une solution créée dans le septième cercle de l'enfer.

si la compatibilité descendante est un must "juste" faire de la prise en charge de rendu nouvelle et moderne un moyen de rendre des composants plus anciens, j'ai vu d'autres plates-formes avoir une solution intéressante pour cela, la plus récente que j'ai utilisée est dans le moteur d'interface utilisateur de l'unité où le nouveau UXML moderne a un rendu IMGUI.

@jackie0100
je suis complètement d'accord

devoir implémenter une interface utilisateur personnalisée sur chaque plate-forme comme dans Xamarin Forms semble vieux et comme si c'était une solution créée dans le septième cercle de l'enfer.

Quant à l'implémentation du moteur de rendu, qu'en est-il de l'idée d'une vue native IView IS A (au lieu d'une vue native IView HAS A ). c'est-à-dire l'héritage au lieu de la composition ? Cela conduirait à l'architecture la plus rapide et la plus légère avec un "overhead de formulaires" absolument nul. Vous travaillez essentiellement avec des vues natives pures et juste une interface commune.

Ensuite, vous pouvez faire des choses comme, dans le pays iOS, simplement convertir votre vue en UIView et y ajouter un enfant natif (quel que soit le type que vous voulez) car une IView est une UIView. De même, si vous souhaitez effectuer une « intégration native », c'est facile car une IView est une UIView, vous pouvez simplement ajouter l'une de vos IViews à votre vue native car il s'agit de la même chose. Cela permettrait massivement l'interopérabilité native <-> maui, et avec le plus haut niveau de performance et la plus faible consommation de mémoire.

J'ai un peu envie de prototyper ça moi-même. Peut-être un projet week-end/soirée...

image

Si MAUI prend en charge le Web (comme Flitter), nous pouvons toujours effectuer un rendu dans WebView.

Pas besoin de WebView sur iOS : peut être rendu directement dans OpenGL ou Metal .

Ou utilisez Skia avec OpenGL ou Metal en dessous.

la capacité de travailler avec l'interface utilisateur native sécurise le cadre du côté politique des choses. [Pomme]

À un moment donné, Apple a supprimé de sa politique écrite l'obligation d'utiliser des widgets d'interface utilisateur natifs. Je ne vois aucun moyen pratique pour eux de revenir à la politique restrictive.

Quoi qu'il en soit, être _capable_ de travailler avec des contrôles natifs est une bonne option.

@legistek

Pourquoi tant de gens sont-ils obsédés par Skia ? Une bonne spécification de rendu serait indépendante du moteur de rendu...

Bien que je sois totalement d'accord sur le fait d'être "agnostique", il y a beaucoup de détails qui doivent être implémentés pour rendre n'importe quelle interface utilisateur interactive - si vous allez directement à OpenGL/Metal/Vulkan/quel que soit le moteur de rendu de bas niveau. Les gens sont obsédés par Skia car il s'agit d'une _couche intermédiaire_ efficace entre les problèmes d'interface utilisateur de l'application et le moteur de rendu réel : Skia gère _beaucoup_ de ce qui devrait être conçu et mis en œuvre, si tout ce que vous avez est du métal nu. Aucune raison de réinventer ce travail. Bien que cela ne devrait pas être la cible _unique_, c'est une cible extrêmement précieuse et mature, qui facilitera beaucoup, disons, le passage d'OpenGL à Vulkan.

Je soupçonne également que cibler Skia serait beaucoup moins fastidieux que la maintenance par Xamarin Forms de deux hiérarchies de widgets parallèles - les widgets multiplateformes et les widgets natifs.

Skia pourrait même accélérer le jour où .Net Maui sera très performant dans le navigateur . Encore une fois, parce qu'au lieu de construire à partir d'un niveau bas, vous commencez par une abstraction appropriée de niveau intermédiaire. Ce serait une énorme victoire.

Salut à tous, ne l'oubliez pas :
https://github.com/dotnet/maui/discussions/103

Après avoir regardé les récentes vidéos de maui, sauf erreur, il semble qu'il y ait eu une dérive pour avoir des contrôles plus stylés avec le contrôle natif superposé au dessin effectué du côté indépendant de la plate-forme. Qu'il s'agisse de skia ou d'une sorte d'interopérabilité par lots avec un dessin sur toile natif, j'espère que cette approche sera poursuivie ! Ironiquement, le modèle de rendu de la plate-forme XF a toujours le plus nui aux plates-formes d'interface utilisateur Microsoft, étant la moins utilisée.

Je laisserais également ouverte la possibilité pour un contrôle de ne pas avoir explicitement de composant natif et pour que le compositeur de mise en page le détecte, cela pourrait permettre une réduction automatisée des vues natives créées (c'est-à-dire si tous les contrôles d'un conteneur sont des étiquettes maui dessinées avec skia, cela pourrait faire du conteneur un SkView et appeler simplement l'opération de dessin sur les contrôles enfants de l'étiquette), sur Android, cela donnerait un coup de pouce à des éléments tels que des éléments de liste contenant de nombreuses images + contrôles de texte, par exemple.

Je ne comprends pas ce qu'est un moteur de rendu.
Si le programme permettant d'absorber les différences visuelles de la cible s'appelle un moteur de rendu, il devrait être absorbé par Xamarin et MAUI. Sinon, je pense que c'est un Xamarin et MAUI inachevé. Et il ne sera jamais terminé.
Je pense que la programmation d'applications devrait être plus indépendante des différences dans l'environnement cible.

Je ne comprends pas ce qu'est un moteur de rendu.
Si le programme d'absorption des différences visuelles de la cible s'appelle un moteur de rendu, il doit être absorbé par Xamarin et MAUI. Sinon, je pense que c'est un Xamarin et MAUI inachevé. Et il ne sera jamais terminé.
Je pense que la programmation d'applications devrait être plus indépendante des différences dans l'environnement cible.

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

Amine-Smahi picture Amine-Smahi  ·  3Commentaires

jsuarezruiz picture jsuarezruiz  ·  3Commentaires

PureWeen picture PureWeen  ·  9Commentaires

sim756 picture sim756  ·  16Commentaires

PureWeen picture PureWeen  ·  21Commentaires