Introduzione

La condivisione di contenuti è una funzionalità che gli utenti danno ormai per scontata: dal link di un articolo a una foto, passando per file PDF generati dall'app. In Flutter, il pacchetto ufficiale share_plus (parte della suite Plus mantenuta dalla community Flutter) permette di invocare il foglio di condivisione nativo del sistema operativo con poche righe di codice.

In questa guida vedremo come installare il pacchetto, condividere testo e link, allegare file e immagini, gestire il risultato della condivisione e affrontare le differenze tra le piattaforme.

Installazione

Aggiungi la dipendenza al tuo pubspec.yaml:

dependencies:
  share_plus: ^10.1.2

Oppure da terminale:

flutter pub add share_plus

Non serve alcuna configurazione nativa aggiuntiva per i casi d'uso base: share_plus sfrutta le API di condivisione integrate di ogni piattaforma.

Condividere testo e link

Il caso più semplice è la condivisione di una stringa di testo o di un URL. Dalla versione 10 si utilizza SharePlus.instance.share con un oggetto ShareParams:

import 'package:share_plus/share_plus.dart';

Future<void> condividiTesto() async {
  await SharePlus.instance.share(
    ShareParams(
      text: 'Dai un\'occhiata a questo articolo: https://flutter.dev',
      subject: 'Articolo interessante',
    ),
  );
}

Il parametro subject viene usato, ad esempio, come oggetto quando l'utente sceglie di condividere via email. Su altre app potrebbe essere ignorato.

Gestire il risultato della condivisione

Spesso è utile sapere se l'utente ha effettivamente completato l'azione. Il metodo share restituisce un oggetto ShareResult con lo stato dell'operazione:

Future<void> condividiConFeedback() async {
  final result = await SharePlus.instance.share(
    ShareParams(text: 'Contenuto da condividere'),
  );

  switch (result.status) {
    case ShareResultStatus.success:
      debugPrint('Condivisione completata');
    case ShareResultStatus.dismissed:
      debugPrint('Condivisione annullata');
    case ShareResultStatus.unavailable:
      debugPrint('Stato non disponibile su questa piattaforma');
  }
}

Nota: su iOS lo stato viene generalmente riportato correttamente, mentre su Android alcune app di destinazione potrebbero non restituire un feedback affidabile, restituendo unavailable.

Condividere file e immagini

Per allegare file (immagini, PDF, documenti) si usa la proprietà files con oggetti XFile:

import 'dart:typed_data';
import 'package:share_plus/share_plus.dart';

Future<void> condividiImmagine(Uint8List bytes) async {
  final file = XFile.fromData(
    bytes,
    mimeType: 'image/png',
    name: 'grafico.png',
  );

  await SharePlus.instance.share(
    ShareParams(
      files: [file],
      text: 'Ecco il grafico generato dall\'app',
    ),
  );
}

Se hai già un file su disco, puoi passarne direttamente il percorso:

Future<void> condividiPdf(String percorso) async {
  await SharePlus.instance.share(
    ShareParams(
      files: [XFile(percorso)],
      subject: 'Report mensile',
    ),
  );
}

Puoi condividere più file contemporaneamente semplicemente aggiungendo altri XFile alla lista.

Posizionamento del popover su iPad

Su iPadOS il foglio di condivisione viene presentato come un popover e richiede un'origine, altrimenti l'app potrebbe crashare. Puoi indicare l'area del widget che ha innescato l'azione tramite sharePositionOrigin:

Future<void> condividiDaPulsante(BuildContext context) async {
  final box = context.findRenderObject() as RenderBox?;

  await SharePlus.instance.share(
    ShareParams(
      text: 'Contenuto condiviso',
      sharePositionOrigin: box != null
          ? box.localToGlobal(Offset.zero) & box.size
          : null,
    ),
  );
}

È buona pratica passare sempre questo parametro quando l'azione parte da un widget preciso, per garantire un comportamento coerente su iPad.

Esempio completo con un pulsante

Ecco un widget minimale che integra la condivisione:

import 'package:flutter/material.dart';
import 'package:share_plus/share_plus.dart';

class PulsanteCondivisione extends StatelessWidget {
  const PulsanteCondivisione({super.key});

  Future<void> _condividi(BuildContext context) async {
    final box = context.findRenderObject() as RenderBox?;
    await SharePlus.instance.share(
      ShareParams(
        text: 'Sto usando questa fantastica app Flutter!',
        subject: 'App consigliata',
        sharePositionOrigin:
            box != null ? box.localToGlobal(Offset.zero) & box.size : null,
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return ElevatedButton.icon(
      onPressed: () => _condividi(context),
      icon: const Icon(Icons.share),
      label: const Text('Condividi'),
    );
  }
}

Differenze tra piattaforme

  • Android e iOS: supporto completo per testo, link e file.
  • Web: usa la Web Share API quando disponibile (richiede un contesto sicuro HTTPS e un browser compatibile); in caso contrario alcune funzioni potrebbero non funzionare.
  • Desktop (Windows, macOS, Linux): il supporto è disponibile ma può variare; su alcune configurazioni la condivisione di file richiede l'app di sistema appropriata.

È sempre consigliabile testare su ogni piattaforma target e prevedere un fallback (ad esempio la copia negli appunti) dove la funzionalità non fosse disponibile.

Best practice

  • Fornisci sempre un text significativo: molte app di destinazione mostrano solo il testo, ignorando il subject.
  • Passa sharePositionOrigin per un'esperienza corretta su iPad.
  • Non affidarti in modo rigido allo ShareResultStatus su Android per logiche critiche.
  • Per file temporanei, generali in una directory di cache e ripuliscili dopo la condivisione.

Conclusioni

Con share_plus integrare la condivisione nativa in Flutter è questione di pochi minuti. Grazie all'API basata su ShareParams puoi condividere testo, link e file in modo uniforme su più piattaforme, gestendo anche i dettagli specifici come il posizionamento su iPad. È uno di quei pacchetti che aggiungono valore percepito all'app con uno sforzo minimo.