Bonjour, Habr! Je vous présente la traduction de l'article
"Les applications Flutter rêvent-elles de widgets sensibles à la plateforme?"
Lors du développement d'applications sur Flutter avec une conception native pour iOS et Android, je suis tombé sur le fait que je devais écrire un tas de conditions pour vérifier la plate-forme sur laquelle le code est exécuté, tout en faisant deux implémentations d'interface utilisateur similaires. Je n'aimais pas cela et je suis heureux d'avoir trouvé un article qui m'a aidé à résoudre mon problème.
À propos de l'auteur: Swav Kulinski - Développeur Android principal chez The App Business, Flutter GDE.
Ensuite, nous parlerons au nom de l'auteur.
Flutter est une solution de développement d'applications mobiles multiplateforme qui promet une liberté absolue dans la création d'une interface utilisateur quelle que soit la plate-forme. Ceci est réalisé par le fait que le framework utilise son propre moteur de rendu pour dessiner des widgets.
Le problème avec de nombreuses solutions multiplateformes est qu'elles se ressemblent sur iPhone et Android. Mais qu'en est-il des entreprises qui doivent conserver l'apparence de la plateforme? Qui doit utiliser Material Design pour Android et Human Interface pour iOS? Pour ces entreprises, Flutter convient, équipé de packages contenant un ensemble de widgets personnalisés pour iOS et Android, appelés Cupertino et Material.

Flutter est de nature multiplateforme, mais en ce qui concerne l'interface utilisateur de mise en page, qui devrait ressembler à chaque plate-forme, ce n'est pas entièrement vrai. Nous devons faire deux implémentations de disposition similaires. Cela est dû au fait que, par exemple, pour iOS, le CupertinoNavigationBar doit être dans CupertinoPageScaffold, et dans Android, l'AppBar à l'intérieur de Scaffold. Cette fonctionnalité réduit les avantages des plates-formes croisées dans Flutter, car pour chaque plate-forme, vous devez écrire votre propre code pour la mise en page.
Je voudrais proposer une approche qui vous permet de créer des interfaces abstraites et d'ajuster l'apparence et le comportement de l'application en fonction de la plateforme sur laquelle elle s'exécute.
Considérez les constructeurs suivants pour deux widgets qui fournissent une barre d'application supérieure:
CupertinoNavigationBar ({ this.leading, this.middle, })
et
AppBar ({ this.leading, this.title })
Les deux widgets ci-dessus jouent le même rôle, étant le panneau supérieur de l'application dans le style de Cupertino et Material. Mais ils nécessitent tout de même une contribution différente. Une solution est nécessaire qui s'éloignera de la façon dont nous créons des widgets spécifiques, tout en fournissant une implémentation en fonction de la plate-forme. Nous utiliserons la bonne vieille méthode d'usine.
import 'package:flutter/material.dart'; import 'dart:io' show Platform; abstract class PlatformWidget<I extends Widget, A extends Widget> extends StatelessWidget { @override Widget build(BuildContext context) { if (Platform.isAndroid) { return createAndroidWidget(context); } else if (Platform.isIOS) { return createIosWidget(context); } // platform not supported returns an empty widget return Container(); } I createIosWidget(BuildContext context); A createAndroidWidget(BuildContext context); }
En fait, la classe ci-dessus est une fabrique de widgets dépendante de la plate-forme qui, lorsqu'elle est implémentée, peut fournir un constructeur personnalisé (ou plusieurs constructeurs nommés) qui prend en charge les besoins des deux classes spécifiques.
J'ai choisi des génériques pour renvoyer des classes spécifiques, car parfois le widget parent a besoin d'un certain type, qui doit être renvoyé par le widget enfant.
Nous pouvons maintenant implémenter notre premier widget.
class PlatformAppBar extends PlatformWidget<CupertinoNavigationBar, AppBar> { final Widget leading; final Widget title; PlatformAppBar({ this.leading, this.title, }); @override AppBar createAndroidWidget(BuildContext context) { return AppBar( leading: leading, title: title, ); } @override CupertinoNavigationBar createIosWidget(BuildContext context) { return CupertinoNavigationBar( leading: leading, middle: title, ); } }
Assez simple, non? Veuillez noter que nous avons un contrôle total sur le contenu des widgets dans le panneau d'application.
Supposons que nous ayons implémenté Scaffold et Button.
class PlatformScaffoldWidget extends PlatformWidget<CupertinoPageScaffold,Scaffold> { ... } class PlatformButton extends PlatformWidget<CupertinoButton,FlatButton> { ... }
Nous sommes maintenant prêts à utiliser et à réutiliser nos widgets orientés plateforme.
Widget build(BuildContext context) { return PlatformScaffoldWidget( appBar: PlatformAppBarWidget( leading: PlatformButton( child: Icon(Icons.ic_arrow_back), onClick: () => _handleBack() ), title: Text("I love my Platform"), ), content: ... ); }
C'est fait! Le code ci-dessus affichera une barre d'application orientée plateforme sur les deux plateformes, et notre PlatformScaffoldWidget est prêt à être réutilisé dans le reste de l'application sans aucun problème.
Le code peut être consulté sur le
github.