【Flutter】WidgetからImageを生成する方法(Widgetのキャプチャ)

もくじ

こんにちは。

スマホアプリをメインに開発しているロッキーカナイです。

Flutter関連の記事を載せさせてもらっている関係で、何か面白いことができないかとネットを漁っていたら、こんな記事を見つけました。

Flutter Widget to Image

なんと「Widgetを画像に出力できるよ」という内容なのです。

スクリーンキャプチャならぬウィジェットのキャプチャができまっせという感じ。実用方法はぱっと思いつきませんが、面白そうだったので、記事にしてみました。

やること紹介

画像が表示される画面を作って、それをキャプチャして下部に表示されるものを作ってみる。

できあがったコードの紹介

こんな感じ。

import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/rendering.dart';


void main() {
  runApp(MaterialApp(home: MyHomePage()));
}


class MyHomePage extends StatefulWidget {

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}


class _MyHomePageState extends State<MyHomePage> {

  // グローバルキー
  GlobalKey _globalKey = GlobalKey();
  // イメージ
  Image _image;

  @override
  Widget build(BuildContext context) {

    return RepaintBoundary(
      key: _globalKey,
      child: Scaffold(
        appBar: AppBar(
          title: Text(
            'キャプチャテスト',
          ),
        ),
        body: Container(
          child: Column(
            children: <Widget>[

              /*
               * 画像表示エリア
               */
              Expanded(
                child: Center(
                  child: Image.network(
                    "https://www.egao-inc.co.jp/wp-content/uploads/2018/12/aruru02-1.jpg",
                  ),
                ),
              ),

              /*
               * キャプチャ表示エリア
               */
              Container(
                color: Colors.yellow,
                height: 200.0,
                child: Center(
                  child: _image != null
                      ? _image
                      : Container(),
                ),
              ),
            ],
          ),
        ),
        floatingActionButton: FloatingActionButton(
          child: Icon(Icons.add),
          onPressed: () {

            // キャプチャ開始
            _doCapture();
          },
        ),
      ),
    );
  }

  /*
   * キャプチャ開始
   */
  Future<Null> _doCapture() async {

    var image  = await _convertWidgetToImage();

    setState(() {
      _image = image;
    });
  }

  /*
   * _globalKeyが設定されたWidgetから画像を生成し返す
   */
  Future<Image> _convertWidgetToImage() async {
    try {
      RenderRepaintBoundary boundary = _globalKey.currentContext.findRenderObject();
      ui.Image image = await boundary.toImage(pixelRatio: 3.0);
      ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);
      var pngBytes = byteData.buffer.asUint8List();
      return Image.memory(pngBytes);

    } catch (e) {
      print(e);
    }

    return null;
  }
}

RepaintBoundaryの子供になっているウィジェットが画像に変換される対象にしていますので、今回だとScaffold全体が画像になります。

それ以外にボタンだけとか対象のウィジェットだけ画像にするというのも可能です。

こんな感じにできました。

↓初期画面

↓フローティングボタンを押下で、

キャプチャした画像が表示されました。

ちなみに猫の画像は、新宿のカフェアルルさんの入り口にあるオブジェです。

最後に

今後もFlutterのまじめな記事や今回のような面白そうな記事があったらまた紹介したいと思います。

関連する記事

もっと見る