Supernova Studio で Flutter コードを吐き出したときのエラー解決メモ その1

16 min read読了の目安(約14700字

たまたま今回はすんなり直ったので誰かの参考になればいいなとメモ。

TL;DR

  • Align の入れ子を消してやるとだいたいオッケー
  • assets を pubspec.yaml に追加するのを忘れずに(凡ミス)
  • 冗長な指定やレイアウト崩れは地道に直しました。。。。

Supernova Studio の可能性がすごい

Supernova Studio、使ってみて可能性を感じた人は多いんじゃないでしょうか。
Sketch ファイルを読み込ませることで
Flutter, iOS(Swift), Android(Java/Korlin)のコードを吐き出してくれるっていうスーパーなやつです。
詳しくは以下。

やってみよう! で動かすとエラーで全然動かない

これはまぁどこででも言われてます。えぇ……(困惑)
私の手元で出たエラーは例えばこういうのですね

flutter: ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
flutter: The following assertion was thrown during performLayout():
flutter: BoxConstraints forces an infinite width.
flutter: These invalid constraints were provided to RenderPositionedBox's layout() function by the following
flutter: function, which probably computed the invalid constraints in question:
flutter:   RenderFlex.performLayout (package:flutter/src/rendering/flex.dart:768:15)
flutter: The offending constraints were:
flutter:   BoxConstraints(w=Infinity, 0.0<=h<=Infinity)
flutter:
flutter: The relevant error-causing widget was:
flutter:   Column file:*********lib/views/screens/login.dart:38:22
flutter:
flutter: When the exception was thrown, this was the stack:
flutter: #0      BoxConstraints.debugAssertIsValid.<anonymous closure>.throwError (package:flutter/src/rendering/box.dart:517:9)
flutter: #1      BoxConstraints.debugAssertIsValid.<anonymous closure> (package:flutter/src/rendering/box.dart:559:21)
flutter: #2      BoxConstraints.debugAssertIsValid (package:flutter/src/rendering/box.dart:565:6)
flutter: #3      RenderObject.layout (package:flutter/src/rendering/object.dart:1677:24)
flutter: #4      RenderFlex.performLayout (package:flutter/src/rendering/flex.dart:768:15)
flutter: #5      RenderObject.layout (package:flutter/src/rendering/object.dart:1777:7)
flutter: #6      RenderStack.layoutPositionedChild (package:flutter/src/rendering/stack.dart:491:11)
flutter: #7      RenderStack.performLayout (package:flutter/src/rendering/stack.dart:587:30)
flutter: #8      RenderObject.layout (package:flutter/src/rendering/object.dart:1777:7)
flutter: #9      RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:113:14)
flutter: #10     RenderObject.layout (package:flutter/src/rendering/object.dart:1777:7)
flutter: #11     RenderConstrainedBox.performLayout (package:flutter/src/rendering/proxy_box.dart:268:14)
flutter: #12     RenderObject.layout (package:flutter/src/rendering/object.dart:1777:7)
flutter: #13     MultiChildLayoutDelegate.layoutChild (package:flutter/src/rendering/custom_layout.dart:171:12)
flutter: #14     _ScaffoldLayout.performLayout (package:flutter/src/material/scaffold.dart:498:7)
flutter: #15     MultiChildLayoutDelegate._callPerformLayout (package:flutter/src/rendering/custom_layout.dart:243:7)
flutter: #16     RenderCustomMultiChildLayoutBox.performLayout (package:flutter/src/rendering/custom_layout.dart:402:14)
flutter: #17     RenderObject.layout (package:flutter/src/rendering/object.dart:1777:7)
flutter: #18     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:113:14)
flutter: #19     RenderObject.layout (package:flutter/src/rendering/object.dart:1777:7)
flutter: #20     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:113:14)
flutter: #21     _RenderCustomClip.performLayout (package:flutter/src/rendering/proxy_box.dart:1308:11)
flutter: #22     RenderObject.layout (package:flutter/src/rendering/object.dart:1777:7)
flutter: #23     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:113:14)
flutter: #24     RenderObject.layout (package:flutter/src/rendering/object.dart:1777:7)
flutter: #25     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:113:14)
flutter: #26     RenderObject.layout (package:flutter/src/rendering/object.dart:1777:7)
flutter: #27     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:113:14)
flutter: #28     RenderObject.layout (package:flutter/src/rendering/object.dart:1777:7)
flutter: #29     RenderStack.performLayout (package:flutter/src/rendering/stack.dart:560:15)
flutter: #30     RenderObject.layout (package:flutter/src/rendering/object.dart:1777:7)
flutter: #31     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:113:14)
flutter: #32     RenderObject.layout (package:flutter/src/rendering/object.dart:1777:7)
flutter: #33     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:113:14)
flutter: #34     RenderObject.layout (package:flutter/src/rendering/object.dart:1777:7)
flutter: #35     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:113:14)
flutter: #36     RenderObject.layout (package:flutter/src/rendering/object.dart:1777:7)
flutter: #37     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:113:14)
flutter: #38     RenderObject.layout (package:flutter/src/rendering/object.dart:1777:7)
flutter: #39     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:113:14)
flutter: #40     RenderObject.layout (package:flutter/src/rendering/object.dart:1777:7)
flutter: #41     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:113:14)
flutter: #42     RenderOffstage.performLayout (package:flutter/src/rendering/proxy_box.dart:3222:13)
flutter: #43     RenderObject.layout (package:flutter/src/rendering/object.dart:1777:7)
flutter: #44     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:113:14)
flutter: #45     RenderObject.layout (package:flutter/src/rendering/object.dart:1777:7)
flutter: #46     _RenderTheatre.performLayout (package:flutter/src/widgets/overlay.dart:685:15)
flutter: #47     RenderObject.layout (package:flutter/src/rendering/object.dart:1777:7)
flutter: #48     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:113:14)
flutter: #49     RenderObject.layout (package:flutter/src/rendering/object.dart:1777:7)
flutter: #50     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:113:14)
flutter: #51     RenderObject.layout (package:flutter/src/rendering/object.dart:1777:7)
flutter: #52     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:113:14)
flutter: #53     RenderObject.layout (package:flutter/src/rendering/object.dart:1777:7)
flutter: #54     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:113:14)
flutter: #55     RenderObject.layout (package:flutter/src/rendering/object.dart:1777:7)
flutter: #56     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:113:14)
flutter: #57     RenderObject.layout (package:flutter/src/rendering/object.dart:1777:7)
flutter: #58     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:113:14)
flutter: #59     RenderObject.layout (package:flutter/src/rendering/object.dart:1777:7)
flutter: #60     RenderView.performLayout (package:flutter/src/rendering/view.dart:167:14)
flutter: #61     RenderObject._layoutWithoutResize (package:flutter/src/rendering/object.dart:1634:7)
flutter: #62     PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:884:18)
flutter: #63     RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:436:19)
flutter: #64     WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:914:13)
flutter: #65     RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:302:5)
flutter: #66     SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1117:15)
flutter: #67     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1055:9)
flutter: #68     SchedulerBinding.scheduleWarmUpFrame.<anonymous closure> (package:flutter/src/scheduler/binding.dart:864:7)
flutter: (elided 11 frames from class _RawReceivePortImpl, class _Timer, dart:async, and dart:async-patch)
flutter:
flutter: The following RenderObject was being processed when the exception was fired: RenderFlex#0176d relayoutBoundary=up1 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE:
flutter:   creator: Column ← Positioned ← Stack ← DecoratedBox ← ConstrainedBox ← Container ← _BodyBuilder ←
flutter:     MediaQuery ← LayoutId-[<_ScaffoldSlot.body>] ← CustomMultiChildLayout ← AnimatedBuilder ←
flutter:     DefaultTextStyle ← ⋯
flutter:   parentData: top=129.0; bottom=65.0; offset=Offset(0.0, 0.0) (can use size)
flutter:   constraints: BoxConstraints(0.0<=w<=Infinity, h=732.0)
flutter:   size: MISSING
flutter:   direction: vertical
flutter:   mainAxisAlignment: start
flutter:   mainAxisSize: max
flutter:   crossAxisAlignment: stretch
flutter:   verticalDirection: down
flutter: This RenderObject had the following descendants (showing up to depth 5):
flutter:     child 1: RenderPositionedBox#a56ba NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
flutter:       child: RenderDecoratedBox#09521 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
flutter:         child: RenderParagraph#bbf72 NEEDS-LAYOUT NEEDS-PAINT
flutter:           text: TextSpan
flutter:     child 2: RenderPositionedBox#dcd74 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
flutter:       child: RenderPadding#570b9 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
flutter:         child: RenderConstrainedBox#80a78 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
flutter:           child: RenderDecoratedBox#2b7e6 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
flutter:             child: RenderPadding#0a7f3 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
flutter:     child 3: RenderPositionedBox#525bc NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
flutter:       child: RenderConstrainedBox#50151 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
flutter:         child: RenderDecoratedBox#236ce NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
flutter:           child: RenderPadding#abebf NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
flutter:             child: RenderMouseRegion#8ef5f NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
flutter:     child 4: RenderPositionedBox#61265 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
flutter:       child: RenderPadding#a3945 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
flutter:         child: RenderConstrainedBox#8d4f4 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
flutter:           child: RenderSemanticsAnnotations#ed757 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
flutter:             child: _RenderInputPadding#37fcc NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
flutter:     child 5: RenderPositionedBox#d1c6c NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
flutter:       child: RenderPadding#8adcd NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
flutter:         child: RenderConstrainedBox#77a51 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
flutter:           child: RenderParagraph#a82e6 NEEDS-LAYOUT NEEDS-PAINT
flutter:             text: TextSpan
flutter:     child 6: RenderPositionedBox#708cc NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
flutter:       child: RenderPadding#e2bac NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
flutter:         child: RenderConstrainedBox#4f3c7 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
flutter:           child: RenderSemanticsAnnotations#57cc0 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
flutter:             child: _RenderInputPadding#6610f NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
flutter: ════════════════════════════════════════════════════════════════════════════════════════════════════
flutter: Another exception was thrown: RenderBox was not laid out: RenderFlex#0176d relayoutBoundary=up1 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
flutter: Another exception was thrown: Null check operator used on a null value
flutter: Another exception was thrown: Updated layout information required for RenderPositionedBox#a56ba NEEDS-LAYOUT NEEDS-PAINT to calculate semantics.
flutter: Another exception was thrown: Bad state: Future already completed
flutter: Another exception was thrown: Unable to load asset: assets/images/login-bg.png

Application finished.

臆せずエラーメッセージを読んでいきましょう。

Unable to load asset の解決

これは凡ミスですね。画像の読み込みするのに pubspec.yaml に設定を追加していません。
なので以下のように指定してやって解決。

flutter:
  uses-material-design: true

  assets:
    - assets/images/

BoxConstraints forces an infinite width の解決

"BoxConstraints forces an infinite width."
は「BoxConstraints が無限の横幅を強制されています。
と言われていますね。

Supernova Studio から出力すると大体

return Scaffold(
  body: Container(
  constraints: BoxConstraints.expand(),
  child: Stack(
    alignment: Alignment.center,
    children: [
    Positioned(
      top: 129,
      bottom: 65,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          Align(
            alignment: Alignment.topCenter,
            child: Container(
              width: 315,
              child: Text(
	        "Forgot your password?",
		textAlign: TextAlign.right,
		style: TextStyle(
		  fontWeight: FontWeight.w400,
		  fontSize: 15,
		),
	      ),
            ),
          ),
...

などと鬼のように入れ子にされて出力されます。
Positioned での絶対位置指定や Container での要素サイズ指定で乗り切ってくるみたいですね。

余談ですが、このあたりはなんとなく、CSSで position: absolute; 使ってデザインをコードに落とし込んだものにイメージは似てる気がします。

.hofe {
    position: absolute;
    left: 50px;
    top: 50px;
}

閑話休題。
で、コードを見ながら、手探りでコードをまるっと消したりしながらどこで引っかかってるか探していきました。
すると、

      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: []

のように、私の生成コードの場合は Column.children が空要素のときはエラーが全て消えました。
ので、犯人はこの中のものですね。

Text.style: TextStyle は問題ないし
Container.child: Text もそこまで問題なさそうです。
で、 Container の親になっている Align は必要なのかパッと見不明だったので消してみたら……ビンゴ!全てのエラーがなくなりました。

っていうだけです。今回はこれでいけました。
また何か別のエラーにブチ当たったら記事にします。

p.s. 配置崩れ

プレビューまで出してからの出力なのに、
(これは Supernova Stuio 上で表示されるDartで気づいてたけど)ボタンに色がついてなかったり、
色の指定が全て Color.fromARGB だったり、
子Widgetの min-widthheight の指定だけでいいのに
Container で包んで widthheight が指定されていたり
と所々強引な指定や冗長な指定が見当るので、手作業で直しました。
なかなかに辛いというかこれなら全部イチから組んだ方が早いのでは……。あっ(察し)