Implémentation de menus contextuels Flutter sur HarmonyOS avec context_menus

Présentation du package

Le package experimental/context_menus est un outil expérimental pour Flutter, conçu pour créer et personnaliser des menus contextuels multiplateformes. Il prend en charge des scénarios tels que la barre d'outils de sélection de texte sur mobile et le menu clic droit sur desktop. Ce package offre une flexibilité élevée avec des fonctionnalités telles que des sous-menus en cascade, la personnalisation des boutons, et une adaptation optimale pour HarmonyOS, garantissant une expérience utilisateur cohérente.

Fonctionnalités principales :

  • Création de menus contextuels n'imoprte où dans l'application
  • Support des sous-menus imbriqués
  • Personnalisation complète des boutons et actions
  • Modification de l'ordre et du comportmeent des boutons par défaut
  • Compatibilité avec les sélections de texte et les scénarios non textuels
  • Adaptation native pour HarmonyOS

Intégration dans un projet HarmonyOS

1. Ajout des dépendances

Étant donné la nature expérimentale du package, il doit être importé via Git. Modifiez le fichier pubspec.yaml de votre projet Flutter pour HarmonyOS comme suit :

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^1.0.2
  url_launcher: ^6.1.6
  context_menus:
    git:
      url: "https://github.com/flutter/samples.git"
      path: "experimental/context_menus"

2. Composants et API essentiels

ContextMenuRegion

Un widget enveloppant qui détecte les gestes de clic droit ou d'appui long pour déclencher un menu contextuel :

ContextMenuRegion({
  Key? key,
  required Widget child,
  required ContextMenuBuilder builder,
});
ContextMenuBuilder

Un calllback pour construire le contenu du menu :

typedef ContextMenuBuilder = Widget Function(BuildContext context, Offset position);
ContextMenuController

Un contrôleur pour gérer l'affichage et la fermeture du menu :

final controller = ContextMenuController();

// Afficher le menu
controller.show(
  context: context,
  contextMenuBuilder: (ctx) => /* Widget du menu */,
);

// Fermer le menu
controller.remove();

3. Exemples d'utilisation

Menu contextuel sur un élément quelconque
import 'package:flutter/material.dart';
import 'package:context_menus/context_menu_region.dart';

class GenericMenuDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ContextMenuRegion(
      child: Container(
        color: Colors.blueGrey[50],
        padding: EdgeInsets.all(20),
        child: Center(
          child: Text('Effectuez un clic droit ou un appui long pour ouvrir le menu'),
        ),
      ),
      builder: (context, position) {
        return Card(
          elevation: 8,
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              ListTile(
                leading: Icon(Icons.copy),
                title: Text('Copier'),
                onTap: () {
                  // Logique de copie
                  Navigator.pop(context);
                },
              ),
              ListTile(
                leading: Icon(Icons.cut),
                title: Text('Couper'),
                onTap: () {
                  // Logique de coupe
                  Navigator.pop(context);
                },
              ),
              ListTile(
                leading: Icon(Icons.paste),
                title: Text('Coller'),
                onTap: () {
                  // Logique de collage
                  Navigator.pop(context);
                },
              ),
            ],
          ),
        );
      },
    );
  }
}
Menu avec sous-menus imbriqués
import 'package:flutter/material.dart';
import 'package:context_menus/context_menu_region.dart';

class NestedMenuDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ContextMenuRegion(
      child: Container(
        color: Colors.green[50],
        padding: EdgeInsets.all(20),
        child: Center(
          child: Text('Clic droit pour un menu avec sous-menus'),
        ),
      ),
      builder: (context, position) {
        return MenuBar(children: [
          SubmenuButton(
            menuChildren: [
              MenuItemButton(
                child: Text('Choix A'),
                onPressed: () {
                  // Action pour Choix A
                  Navigator.pop(context);
                },
              ),
              MenuItemButton(
                child: Text('Choix B'),
                onPressed: () {
                  // Action pour Choix B
                  Navigator.pop(context);
                },
              ),
            ],
            child: Text('Menu principal'),
          ),
        ]);
      },
    );
  }
}
Personnalisation du menu de sélection de texte
import 'package:flutter/material.dart';

class TextSelectionMenuCustom extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return TextField(
      maxLines: null,
      decoration: InputDecoration(
        hintText: 'Tapez du texte, puis sélectionnez-le pour voir le menu',
        border: OutlineInputBorder(),
        contentPadding: EdgeInsets.all(16),
      ),
      contextMenuBuilder: (context, state) {
        return AdaptiveTextSelectionToolbar.buttonItems(
          anchors: state.contextMenuAnchors,
          buttonItems: <contextmenubuttonitem>[],
        );
      },
    );
  }
}</contextmenubuttonitem>
Menu contextuel sur une image
import 'package:flutter/material.dart';
import 'package:context_menus/context_menu_region.dart';
import 'package:url_launcher/url_launcher.dart';

class ImageMenuDemo extends StatelessWidget {
  final String imageSource = 'https://example.com/sample-image.jpg';

  @override
  Widget build(BuildContext context) {
    return ContextMenuRegion(
      child: Card(
        elevation: 4,
        child: Image.network(imageSource, width: 300, height: 200, fit: BoxFit.cover),
      ),
      builder: (context, position) {
        return Card(
          elevation: 8,
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              ListTile(
                leading: Icon(Icons.open_in_new),
                title: Text('Ouvrir dans le navigateur'),
                onTap: () {
                  launchUrl(Uri.parse(imageSource));
                  Navigator.pop(context);
                },
              ),
              ListTile(
                leading: Icon(Icons.copy),
                title: Text('Copier le lien'),
                onTap: () {
                  // Logique de copie de lien
                  Navigator.pop(context);
                },
              ),
              ListTile(
                leading: Icon(Icons.download),
                title: Text('Télécharger'),
                onTap: () {
                  // Logique de téléchargement
                  Navigator.pop(context);
                },
              ),
            ],
          ),
        );
      },
    );
  }
}

Étiquettes: Flutter HarmonyOS context_menus Dart UI

Publié le 3 juin à 18h55