Supernova Studio を使ってFlutterのコード吐き出してみた

先日 Flutter Interact というイベントがあり、Flutter1.12 のリリースやWeb、Desktop版の開発状況などの発表がありました。
Flutter Interact に関しては下記記事が色々まとまっていたので気になる方は見てみてください。
[Flutter Interact キーノート 発表内容のまとめ](https://medium.com/@ntaoo/flutter-interact-%E3%82%AD%E3%83%BC%E3%83%8E%E3%83%BC%E3%83%88-%E7%99%BA%E8%A1%A8%E5%86%85%E5%AE%B9%E3%81%AE%E3%81%BE%E3%81%A8%E3%82%81-318efa1a291c)

そこで発表されたのが [Supernova Studio](https://supernova.io/) でFlutterのソースコードをエクスポートするのが無料になるといった内容でした。
Flutter Interact　の前日~~（前日というか当日というか微妙なところだけど）~~ の flutter_meetup_tokyo で Supernova Studio についてLTしている方がいて、そこで初めて知りとても興味が湧いていたツールだったので、とてもタイムリーな内容で個人的にはすごく盛り上がりました。

正直なところワイヤーフレームも XD とか Sketch を使わないで Flutter で作れば良いのでは？？ と思っていますし、今個人で作ってるアプリも頭で考えて Flutter で書いて手で触って修正してといって感じで進めています。
とはいえ、あれもこれもやらないとイケない状況になるとデザイナーさんが作ったのデータ見ながらここが何pxでフォントサイズが何で...みたいなことはやってられないので、デザインからUI部分のコードを書き起こせたらとても便利になるのではと思い、実際に使ってみました。


## Supernova Studio
Supernova Studio は XD と Sketch のプロジェクトから　`Android` `iOS` `React Native` `Flutter`のコードをエクスポート出来るサードパーティーツールになっています。
このツールを使うことで、画面遷移やアニメーションなどもGUIで組み込めて、ネイティブアプリでもデザイナーさんと分業が出来る夢のツールになっています。

とはいえ、自動生成されたコードは保守運用出来るものじゃなかったり、そもそも手を加えないと動かなかったりとなかなか夢を叶えてくれませんでした。
今回はどこまで夢を見させてくれるのかを実際に Flutter のコードにエクスポートしてどのようなコードが出来上がるのかを見てみたいと思います。
[今回使用したサンプル](https://www.sketchappsources.com/free-source/2810-candy-simple-task-management-app-sketch-freebie-resource.html)

実際にFlutterのコードとしてエクスポートするページ
![Login@3x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91583/b4c558d6-bc16-1bf2-6bc2-300413296763.png)

##SketchのプロジェクトからFlutterのコードをエクスポート
実際にエクスポートしてみました。
畳んでいるということはそういうことです...
FlutterはUIが構造的な作りをしているのでそこそこのコードをエクスポートしてくれるのでは？？と思っていましたが、まだ難しいみたいですね。

<details><summary>実際にエクスポートされたコード</summary><div>

```dart

import 'package:candy_todo/values/values.dart';
import 'package:flutter/material.dart';


class LoginWidget extends StatelessWidget {
  
  @override
  Widget build(BuildContext context) {
  
    return Scaffold(
      body: Container(
        constraints: BoxConstraints.expand(),
        decoration: BoxDecoration(
          color: Color.fromARGB(255, 255, 238, 238),
        ),
        child: Stack(
          alignment: Alignment.center,
          children: [
            Positioned(
              top: 33,
              child: Text(
                "LOGIN",
                textAlign: TextAlign.center,
                style: TextStyle(
                  color: AppColors.primaryText,
                  fontFamily: "Avenir",
                  fontWeight: FontWeight.w900,
                  fontSize: 14,
                  letterSpacing: 4,
                ),
              ),
            ),
            Positioned(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: [
                  Align(
                    alignment: Alignment.topLeft,
                    child: Container(
                      margin: EdgeInsets.only(left: 1),
                      child: Text(
                        "Email",
                        textAlign: TextAlign.left,
                        style: TextStyle(
                          color: AppColors.primaryText,
                          fontFamily: "Avenir",
                          fontWeight: FontWeight.w400,
                          fontSize: 12,
                        ),
                      ),
                    ),
                  ),
                  Container(
                    height: 51,
                    margin: EdgeInsets.only(left: 1, top: 8),
                    decoration: BoxDecoration(
                      color: AppColors.primaryElement,
                      border: Border.fromBorderSide(Borders.primaryBorder),
                      borderRadius: Radii.k8pxRadius,
                    ),
                    child: Container(),
                  ),
                  Container(
                    height: 16,
                    margin: EdgeInsets.only(left: 1, top: 16, right: 1),
                    child: Row(
                      crossAxisAlignment: CrossAxisAlignment.stretch,
                      children: [
                        Align(
                          alignment: Alignment.topLeft,
                          child: Text(
                            "Password",
                            textAlign: TextAlign.left,
                            style: TextStyle(
                              color: AppColors.primaryText,
                              fontFamily: "Avenir",
                              fontWeight: FontWeight.w400,
                              fontSize: 12,
                            ),
                          ),
                        ),
                        Spacer(),
                        Align(
                          alignment: Alignment.topLeft,
                          child: Opacity(
                            opacity: 0.5,
                            child: Text(
                              "Forgot?",
                              textAlign: TextAlign.left,
                              style: TextStyle(
                                color: AppColors.primaryText,
                                fontFamily: "Avenir",
                                fontWeight: FontWeight.w400,
                                fontSize: 12,
                              ),
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                  Container(
                    height: 51,
                    margin: EdgeInsets.only(left: 1, top: 8),
                    child: Stack(
                      alignment: Alignment.center,
                      children: [
                        Positioned(
                          left: 0,
                          top: 0,
                          right: 0,
                          child: Container(
                            height: 51,
                            decoration: BoxDecoration(
                              color: AppColors.primaryElement,
                              border: Border.fromBorderSide(Borders.primaryBorder),
                              borderRadius: Radii.k8pxRadius,
                            ),
                            child: Container(),
                          ),
                        ),
                        Positioned(
                          top: 16,
                          right: 5,
                          child: Opacity(
                            opacity: 0.5,
                            child: Text(
                              "",
                              textAlign: TextAlign.left,
                              style: TextStyle(
                                color: AppColors.primaryText,
                                fontFamily: "",
                                fontWeight: FontWeight.w400,
                                fontSize: 20,
                              ),
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                  Container(
                    height: 51,
                    margin: EdgeInsets.only(top: 40, right: 1),
                    decoration: BoxDecoration(
                      color: AppColors.secondaryElement,
                      borderRadius: Radii.k8pxRadius,
                    ),
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        Text(
                          "Login",
                          textAlign: TextAlign.center,
                          style: TextStyle(
                            color: AppColors.secondaryText,
                            fontFamily: "Avenir",
                            fontWeight: FontWeight.w800,
                            fontSize: 14,
                          ),
                        ),
                      ],
                    ),
                  ),
                  Spacer(),
                  Align(
                    alignment: Alignment.topCenter,
                    child: Text(
                      "New User? Register Here",
                      textAlign: TextAlign.center,
                      style: TextStyle(
                        color: AppColors.primaryText,
                        fontFamily: "Avenir",
                        fontWeight: FontWeight.w800,
                        fontSize: 14,
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}
```

</div></details>

## まとめ
この記事を書こうと決めたときは、エクスポートしたコードを手直ししてdiffを出そうと思っていましたが、コードを見たところ修正内容が多すぎると思いここで打ち切ります...
内容的に下げているような内容になっているかもしれませんが、個人的には supernova Studio の今後にとても期待しています。
Supernova では現在Flutterエンジニアの方を募集しているみたいなので、Flutterエンジニアの方が参画されたらまたエクスポートされるコードの内容も変わってくるかもしれません。
また個人的にもアップデートを追っていこうと思います。

そういえば、adobeからXDのプロジェクトをFlutterのコードにエクスポートできるプラグインがでるみたいなのでこちらも期待です。

弊社ではFlutter エンジニアを募集しています。
弊社のアプリは３つ中２つがFlutter製です。
もう一つも絶賛Flutterでリプレイス中です。
ご興味がある方は下記のリンクからコーポレートサイトと募集要項など見てみてください。
[募集要項 Flutterエンジニア(コーポレートサイト)](https://www.torico-corp.com/recruit/job/25/)