概要
Flutterで作成したアプリにシェア機能を実装した際の備忘録です。
3つのパッケージを利用することで、簡単に任意のWidgetのスクリーンショットを添付してSNSなどへシェアすることができるようになります。
下記はiOSシミュレータでサンプルコードを実行した際の挙動になります。
シミュレータのためシェア先の候補が少ないですが、TwitterやInstagramなどがインストールされている場合は、シェア先の候補として自動的に表示されるようになります。
サンプルコード
動作環境
$ flutter --version
Flutter 2.8.1 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 77d935af4d (8 weeks ago) • 2021-12-16 08:37:33 -0800
Engine • revision 890a5fca2e
Tools • Dart 2.15.1
使用するパッケージ
()内は本記事で使用しているパッケージのバージョン
・ share_plus(3.0.4)
・ screenshot(1.2.3)
・ path_provider(2.0.9)
要点
main.dart全文
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'package:screenshot/screenshot.dart';
import 'package:share_plus/share_plus.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final _screenShotController = ScreenshotController();
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Screenshot(
controller: _screenShotController,
child: Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
ElevatedButton(
onPressed: () async {
const _shareText = 'シェアするテキスト';
final _screenshot = await _screenShotController.capture(delay: const Duration(milliseconds: 10));
if (_screenshot != null) {
// スクリーンショットをドキュメントディレクトリに保存
final _documentDirectoryPath = await getApplicationDocumentsDirectory();
final imagePath = await File('${_documentDirectoryPath.path}/screenshot.png').create();
await imagePath.writeAsBytes(_screenshot);
// スクリーンショットとテキストをシェア
await Share.shareFiles([imagePath.path], text: _shareText);
}
},
child: const Text('スクリーンショットをシェア'),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
),
);
}
}
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'package:screenshot/screenshot.dart';
import 'package:share_plus/share_plus.dart';
2. ScreenshotControllerクラスのインスタンスを作成します。
// FYI: https://github.com/sakatech-jp/flutter_screenshot_share/blob/master/lib/main.dart#L36
final _screenShotController = ScreenshotController();
3. スクリーンショットに含めたいWidgetをScreenshot
でWrapして、controllerに2.で宣言した_screenShotController
を指定します。
// FYI: https://github.com/sakatech-jp/flutter_screenshot_share/blob/master/lib/main.dart#L47-L48
@override
Widget build(BuildContext context) {
return Screenshot(
controller: _screenShotController,
child: Scaffold(....)
);
}
4. シェア用のボタンがタップされた際の挙動をonPressed
に定義します。
// FYI: https://github.com/sakatech-jp/flutter_screenshot_share/blob/master/lib/main.dart#L64-L79
onPressed: () async {
const _shareText = 'シェアするテキスト';
final _screenshot = await _screenShotController.capture(delay: const Duration(milliseconds: 10));
if (_screenshot != null) {
// スクリーンショットをドキュメントディレクトリに保存
final _documentDirectoryPath = await getApplicationDocumentsDirectory();
final imagePath = await File('${_documentDirectoryPath.path}/screenshot.png').create();
await imagePath.writeAsBytes(_screenshot);
// スクリーンショットとテキストをシェア
await Share.shareFiles([imagePath.path], text: _shareText);
}
},