[Flutter] Widgetを画像として抽出し保存する実装手順

![IMG_9108.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672609/f0ef320a-b89d-12b0-d223-d87049f201f6.jpeg)


こんにちわ。いせりゅーです。最近は寒暖差がすごくてとても辛いですね。でも僕はリモートワークだから楽だ！！と思いながら毎日頑張っています。

今回は、一部のWidgetをスクリーンショットして保存する方法をご紹介いたします。




## 使用したPackage
### Image Gallery Saver
- 画像をアルバムに保存する

https://pub.dev/packages/image_gallery_saver

### screenshot
- ウィジェットを画像としてキャプチャできる

https://pub.dev/packages/screenshot


# 開発方法

### 設定

```yaml:pubspec.yaml
dependencies:
  flutter:
    sdk: flutter
  # 適宜、適切なVersionを入れてください。
  image_gallery_saver: ^1.7.1
  screenshot: ^1.2.3
```

### iOSの設定

```plist:info.plist
<key>NSPhotoLibraryUsageDescription</key>
<string>画像を保存します。</string>
```


### Androidの設定

`android/app/src/main/AndroidManifest.xml`に記載を行います。


```xml:AndroidManifest.xml
<application
  android:name="${applicationName}"
  android:label="image_gallery_saver_example"
  # ここを追加
  android:requestLegacyExternalStorage="true"
...省略

```

# 実装スタート

まずは、保存する処理を記載していきましょう。
やることとしては、
 - ScreenshotControllerを追加する。
 - 保存のカメラロールに写真を保存する。

```dart
ScreenshotController screenshotController = ScreenshotController();

Future<void> storeImage() async {
    screenshotController.capture().then((capturedImage) async {
      if (capturedImage != null) {
        await ImageGallerySaver.saveImage(capturedImage);
     }
  });
}

```

これだけでは、どのWidgetをカメラロールに保存するかが設定できていません。その設定をしていきます。
やり方としてはとても簡単です。
- 保存したいWidgetの上に`Screenshot`を追加するだけです。

```dart
Screenshot(
 controller: screenshotController,
 child: Container(
   width: 200,
   height: 200,
   color: Colors.greenAccent,
     child: const Center(
       child: Text(
         'ここのWidgetを保存するよ',
       ),
     ),
   ),
 ),

```

# 解説

```dart
//ScreenshotControllerを定義する。
ScreenshotController screenshotController = ScreenshotController();

void storeImage() {
  //アプリケーションの現在の画面のスクリーンショットをキャプチャする。
  //capture()メソッドは非同期の操作で、Futureを返すため、.then()を使ってその結果を待つことができる。
  screenshotController.capture().then((capturedImage) async {
    if (capturedImage != null) {
      //画像をデバイスのギャラリーに保存します
      await ImageGallerySaver.saveImage(capturedImage);
    }
  });
}

```

# ソースコード

```dart:main.dart
import 'package:flutter/material.dart';
import 'package:image_gallery_saver/image_gallery_saver.dart';
import 'package:screenshot/screenshot.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> {
  ScreenshotController screenshotController = ScreenshotController();

  Future<void> storeImage() async {
    screenshotController.capture().then((capturedImage) async {
      if (capturedImage != null) {
        await ImageGallerySaver.saveImage(capturedImage);
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Screenshot(
              controller: screenshotController,
              child: Container(
                width: 200,
                height: 200,
                color: Colors.greenAccent,
                child: const Center(
                  child: Text(
                    'ここのWidgetを保存するよ',
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: storeImage,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

```

# 検証動画


![Simulator Screen Recording - iPhone 14 Pro Max - 2023-05-23 at 16.28.56.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672609/c73949f4-58b9-5bb3-f335-ac5acf535a83.gif)


最後に、この技術を使用した開発したアプリをご紹介致します。


# アプリ紹介

#### アプリ名

### 「寝過ごし防止」

#### アプリの概要
- クレヨンしんちゃんのタイトルを自由に作成できる。

#### iOSのダウンロード

https://apps.apple.com/jp/app/%E3%82%AF%E3%83%AC%E3%83%A8%E3%83%B3%E3%81%97%E3%82%93%E3%81%A1%E3%82%83%E3%82%93%E3%83%A1%E3%83%BC%E3%82%AB%E3%83%BC/id6449378278

#### Androidのダウンロード

https://play.google.com/store/apps/details?id=com.crayon_app