Content sharing in Flutter apps

In this article, we are going to learn about Content sharing in flutter apps, we can find the awesome package called share_plus in pud.dev to achieving this. Share plus plugin is wrapped with ACTION_SEND Intent on Android and UIActivityViewController on iOS.

This plugin consists of two methods, one is share(..) and another one is shareFiles(..) method.

share(..) method is used for sharing the textual content only

Share.share('Hi, check out my blog https://flutterant.com');

and this method also can take an optional parameter called subject which is used to populate an email subject when the user chooses to send an email

Share.share('check out my blog https://flutterant.com', subject: 'Regarding flutter tutorials');

shareFiles(..) method is used for sharing one or multiple files, here also we can share text and subject by the optional parameters 

Share.shareFiles(['${directory.path}/image.jpg'], text: 'Great picture');
Share.shareFiles(['${directory.path}/file.pdf', '${directory.path}/image2.jpg']);

Implementation of Content sharing

Project Setup:

  1. Create a new Flutter project in your favorite IDE, and remove the boilerplate code. Ref link
  2. Add the share_plus and file_picker dependencies in pubspec.yaml file, and install them by running pub get.
dependencies:
  flutter:
    sdk: flutter
  share_plus: <"latest version">
  file_picker:<"latest version">

Building Home page

Creating a StatefulWidget called HomePage in main.dart file, which is for taking the users input and shared them across the apps

//main.dart
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter_share_content/image_preview.dart';
import 'package:share_plus/share_plus.dart';

void main() {
  runApp(MyApp());
}
//Content sharing
class MyApp extends StatelessWidget {
  // This widget is the root of your application.
//content sharing
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Flutter Share content app',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}
//Content sharing
class _HomePageState extends State {
  String text = '';
  String subject = '';
  List filePaths = [];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Share plugin"),
      ),
      body: SingleChildScrollView(
        child: Padding(
          padding: const EdgeInsets.all(24.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              TextField(
                decoration: const InputDecoration(
                  labelText: 'Share text:',
                  hintText: 'Enter some text and/or link to share',
                ),
                maxLines: 2,
                onChanged: (String value) => setState(() {
                  text = value;
                }),
              ),
              TextField(
                decoration: const InputDecoration(
                  labelText: 'Share subject:',
                  hintText: 'Enter subject to share (optional)',
                ),
                maxLines: 2,
                onChanged: (String value) => setState(() {
                  subject = value;
                }),
              ),
              const Padding(padding: EdgeInsets.only(top: 12.0)),
              FilePreview(filePaths, onDelete: _onDeleteFile),
              ListTile(
                leading: Icon(Icons.add),
                title: Text('Add Attachment'),
                onTap: () async {
                  _addAttachments();
                },
              ),
              const Padding(padding: EdgeInsets.only(top: 12.0)),
              Builder(
                builder: (BuildContext context) {
                  return ElevatedButton(
                    onPressed: text.isEmpty && filePaths.isEmpty
                        ? null
                        : () => _onShare(context),
                    child: const Text('Share'),
                  );
                },
              ),
            ],
          ),
        ),
      ),
    );
  }

  Future _addAttachments() async {
    FilePickerResult result = await FilePicker.platform.pickFiles(
      type: FileType.custom,
    );
    if (result != null) {
      PlatformFile fileList = result.files.first;
      setState(() {
        filePaths.add(fileList.path);
      });
    } else {
      print("No file selceted");
    }
  }

  void _onShare(BuildContext context) async {
    if (filePaths.isNotEmpty) {
      await Share.shareFiles(
        filePaths,
        text: text,
        subject: subject,
      );
    } else {
      await Share.share(
        text,
        subject: subject,
      );
    }
  }
  void _onDeleteFile(int position) {
    setState(() {
      filePaths.removeAt(position);
    });
  }
}
//Content sharing

If we look at the above code snippet,

  • String text holds the text content
  • String subject holds the subject which is used to populate as an email subject
  • List filePaths holds the list of file paths that are selected by the user.
  • _addAttachments() method will be invoked whenever the user taps on the Add Attachment text. It will be responsible for pick the files from the device by FilePicker and add them to the list.
  • _onShare() method will be triggered when the user presses the share button, it will responsible for sharing content
  • _onDeleteFile() method is for deleting a selective file based on the list position
  • FilePreview widget is for previewing the selected files and along with the delete icon for deleting the file in vertical order
//file_preview.dart
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';

class FilePreview extends StatelessWidget {
  
  final List filePaths;

  final Function(int) onDelete;

  const FilePreview(this.filePaths, {Key key, this.onDelete}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    if (filePaths.isEmpty) {
      return Container();
    }
    final fileWidgets = [];
    for (var i = 0; i < filePaths.length; i++) {
      fileWidgets.add(_FilePreview(
        filePaths[i],
        onDelete: onDelete != null ? () => onDelete(i) : null,
      ));
    }
    return SingleChildScrollView(
      scrollDirection: Axis.vertical,
      child: Column(
          crossAxisAlignment: CrossAxisAlignment.start, children: fileWidgets),
    );
  }
}
//Content sharing
class _FilePreview extends StatelessWidget {
  final String filePath;
  final VoidCallback onDelete;

  const _FilePreview(this.filePath, {Key key, this.onDelete})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: Stack(
        children: [
          ConstrainedBox(
            constraints: BoxConstraints(),
            child: Container(
              height: 100,
              // width: 120,
              color: Colors.grey.shade400,
              child: Padding(
                padding: const EdgeInsets.all(8.0),
                child: Text(filePath),
              ),
            ),
        
          ),
          Positioned(
            right: 0,
            child: Padding(
              padding: const EdgeInsets.all(8.0),
              child: Container(
                height: 30,
                width: 30,
                child: FloatingActionButton(
                    backgroundColor: Colors.red,
                    onPressed: onDelete,
                    child: Icon(Icons.delete)),
              ),
            ),
          ),
        ],
      ),
    );
  }
}
//Content sharing

Implementation part has done, let’s run the application and see the output

Output:

Content sharing

For more Information about share_plus click here

Thanks for reading !!! 🙂

Leave a Comment