フューチャー技術ブログ

Adobe XDからFlutterに変換する

モバイル開発をする場合、デザインはAdobe XDかFigmaか何かしらのワイヤフレームツールを使うと思います。本エントリーではそれらをもとにアプリケーションを作成したときのTipsを紹介します。

なお、デザインする人はステークホルダーの人に共有したりすると思うので有料版のXDの方が良いと思いますが、Flutter開発する人はXDファイルを持っている or 共有してもらえたら、スターター版で大丈夫です。XDの有料版とスターター版の違いは共有の機能の自由度だったり、PDFエクスポートの回数制限だったりします。

スターターパックをインストールしたら、Creative Cloudアプリ(タスクバーに常駐していると思います)のマーケットプレースから、XD to Flutterというプラグインを入れます。AdobeとGoogleが協力して開発しているプラグインで、これがあるのとないのでは開発効率が大きく変わります。なお、この常駐アプリ、結構CPUを持っていくっぽいので、プラグインを入れた後は終了させたほうが良いかも?プラグインのインストール以外はXDのバージョンアップでは使いましたが、使うのはそれぐらいかと。

XD to Flutterプラグイン

基本はCopy Selected

さて、XD to Flutterにはまるごとエクスポートする機能もありますが、どうもレスポンシブのせいか、ちょっと見た目のデザインがちょっとXDと違うとか違いがあります。XD to Flutterでエクスポートすると、adobe_xdパッケージのPinを使ったコードが生成されます。XDのレスポンシブ機能をFlutter上で再現する機能のようですが、XD上でそこまできちんとデザインを作り込まれていないとおそらく逆効果です。でも、実装する立場からすると、そこをXD上で頑張るよりは、早くXDファイルをもらえた方が嬉しいかなと思います。

あくまでもXDはお絵描きツールなので、内部のコンテンツの量や数が可変になったときのレイアウトの挙動とか、そのままフリーハンドで再現できるわけではありません。高機能なUI部品をそのまま再現できません。もしかしたら.NetのExpression Blendが世界を制覇する世界線であればそういう開発もできたかもしれませんが、基本は1要素を選択して、左下のCopy Selectedボタンを使って、コードをクリップボードに入れて、Android Studioに貼り付けていくのが良いでしょう。

Copy Selectedボタン

テキストとかもフォーマットつきで取り出せますので、それをぺたぺた貼り付けていけば良い感じに再現できます。こういう影付き角丸長方形とかも・・・

う影付き角丸長方形

こんな感じのコードになります。

Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.0),
color: const Color(0xff9ffdfb),
boxShadow: [
BoxShadow(
color: const Color(0x29000000),
offset: Offset(0, 3),
blurRadius: 6,
),
],
),
)

要素を貼り付ける土台としては次のコンポーネントを駆使して組み合わせていく感じです。CSSで要素のレイアウトをしたことがあれば難しくはないと思います。もっといろいろあると思いますが↓姿形のないレイアウト用コンポーネントは、以下のやつぐらいを使えばだいたいやりたいレイアウトは問題なくできました。以下のリストはよく使う順です。

  • Scaffold: 基本の土台です
  • Column: 基本の縦整列
  • Row: 横整列。Columnの中に入れる
  • SizedBox: 固定サイズのスペーサーとして使う
  • Container: こちらも固定サイズのスペーサーとして使えるが背景画像を設定したりするし、子要素も持てるし、HTMLのdiv的に使える。相対サイズを設定したい場合は
    MediaQuery.of(context).size.widthに0.8を掛け算して設定とかもある。
  • Padding: 中の要素の前後左右にスペースを設定。CSSのpaddingと一緒。SizedBoxを前後左右に並べるよりもリーズナブル。隙間調整に。
  • Expanded: 中の要素を空きスペースを埋めるように広げる。CSSのflexboxみたいなもの。たまに、自動で空きスペース全部埋めるようにレイアウトされる要素を閉じ込めるのに使う(横いっぱいに勝手に広がるRadioListTileを横にいくつか並べたい場合とか)
  • Stack: レイヤーにして要素を前後に重ねるときに利用。背景画像を一枚置くだけならContainerで済むが、そうでない場合に
  • SingleChildScrollView: どうしても縦横比の小さい端末で下が欠けてしまう、ソフトキーボードが出た瞬間におかしくなる、みたいなときに。全体をこれでくるむと(Scaffoldのbodyをこれにして、他の要素はこれの子供にする)、なんとかなる。

基本的なレイアウトについてはこのブログのFlutterレイアウト入門にもあります。

画像の要素の書き出し

Flutterはプラグインを入れればSVGが使えます。adobe_xdパッケージもベクター画像はSVGのパッケージを前提としたコードを生成したりもします。しかし、最新のSVGパッケージと、Containerの背景にSVGを使うパッケージで依存のバージョンが合わず、背景にSVGが使えなかったりしたので問題なく本体機能だけで使えるPNGを作成しました。レンダラーの都合でSVGのままでは再現性が怪しい場合も画像にしておくと良いかもしれません。

書き出すときは、ファイルメニューの書き出しを選択し、フォーマットでSVGを選ぶと出力できます。PNGをここから書き出すのもできますが、どうもXDに配置されたサイズでの書き出しになるっぽくて、かなり荒い画像になってしまったのでSVGでエクスポートしています。

ファイルメニューの書き出し SVGエクスポート

その後はOSSのInkscapeで、DPIを180とか大きめにしてPNGに書き出しています。ちょっと不安定だったり、ウェルカムウインドウが開いているとウインドウ操作ができなかったり、DPIを変更してフォーカスを変換してからエクスポート先、の方を押さないとサイズが反映されなかったり、ちょっと癖はありますが、根気よくがんばりましょう。

PNGに書き出し

生成されたらassetフォルダにいれて、pubspec.yamlのassetsの項目に格納先のフォルダに入れてあげて再ビルドします。画像の追加はホットリロードでは対応してくれないので、一度アプリを停止させて再ビルドが必要です。

pubspec.yaml
flutter:
assets:
- assets/images/

なお、XDから書き出したSVGがうまくInkskape上でレンダリングできずに崩れてしまう場合は、XD上で拡大してスクリーンショットをとって回避する手もあります。ありました。

まとめ

ゲームのように固定レイアウトでも良い(空いたスペースはレターボックスを表示したり)ケースであれば、デザインツールから一括インポートというのもできるかもしれません。僕も以前、Adobe Flashで作ったゲームの画面レイアウトをJSFLでJSONファイルにエクスポートして、ゲームエンジン(ngCore)上にそっくり再現(カットインアニメーションも)するランタイムライブラリを実装したことがありました。ただし、Flashのフルの機能を使われると変換できないので、ルールに従ったデザインを作ってもらう必要があります。Excelを入力ツールとして使うときも同様ですね。

実際のGUIフレームワーク(Qt)に密接につながっているQt Designerでデザインしてデスクトップアプリケーションを実装したこともありました。これは再現性という点ではポイントは高いのですが、デザイナーが使い慣れたツールというわけではなく、どうしても操作するのは開発者になってしまうでしょう。

Flutterアプリで作るようなノンゲームのアプリではレスポンシブに作ることになります。自動変換まではいけませんが、デザイナーが慣れたAdobe製のツール上でデザインを作ってくれたら、それをクリップボードに入れてばしばし貼り付けるというワークフローになります。ちょっと面倒に見えるかもしれませんが、今までやってきたデザインの実装の各種手法の中ではフリクションが少なく、かなり快適です。できあがるコードもFlutterの機能をばっちり使えたコードになります。