Flutterのテキストに謎の下線。本当の原因はAIの推測の外にあった

AI活用術

課題

Flutterで作ったアプリの特定のテキストにだけ、指定した覚えのない下線が出ることがある。AIに直してもらっても直らないことがあり、しかも一度は「直った」と報告されているだけに、次にどこを疑えばいいのか分かりにくい。

解決できるようにすること

Flutterのテキストに原因不明の下線が出たときの実際の直し方(Material祖先の欠如という仕様)を知り、あわせてAIが「もっともらしいが的外れな原因」に飛びつく典型パターンを知って、同じような誤診断を早めに疑えるようにする。

先に結論

個人開発しているパズルアプリ「月灯り調合所」(色を仕分けるWater Sort系ゲーム)で、スプラッシュ画面のテキストに謎の下線が出るという不具合に遭遇した。

AIが最初に飛びついた原因は「もっともらしいが外れ」だった。該当2箇所にだけfontFamily指定が入っていて、下線もその2箇所にだけ出ている、という一致だけを根拠にした推測で、テストも全部PASSしたが直っていなかった。

本当の原因は、Flutterのかなり細かい仕様だった。TextMaterialの祖先を持たないと、指定していない装飾(下線)がデフォルトで表示されてしまう、というもの。しかもこの不具合は、ローカルのテスト環境では構造的に再現できないタイプのものだった。

最初の「もっともらしい原因」

実機でスプラッシュ画面を確認していたところ、アプリ名と価値メッセージの下に下線がついていることに気づいた。意図したものではないので、AIへ「下線なしに直してほしい」と伝えた。ただ、このやり取りの中では画像そのものをAIへ直接確認させることができなかったため、AIにはコードを読んで原因を推測してもらうことにした。

AIがスプラッシュ画面のコードを確認したところ、アプリ名と価値メッセージのTextStyleだけにfontFamily: 'Roboto'という指定が入っていた。これは以前、別の画面で日本語が文字化けする問題への対策として追加したものだった。

ここでAIが原因として選んだ根拠は、「この2箇所だけに固有の指定が入っていて、下線もこの2箇所だけに出ている」という一致だった。もっともらしく聞こえるが、これは「同じ場所で起きている」という表面的な相関でしかなく、「なぜfontFamily指定が下線を生むのか」という仕組みの説明にはなっていない。それでもAIはこれが原因だろうと判断し、指定を削除した。

flutter analyzeは成功、flutter testも全62件PASS。AIから「テストは全部PASSしました」と報告を受け、「よし、直った」と思うところだったが、この時点ではAIはまだ画像そのものを確認できておらず、コードレビューだけで完了扱いにしていた。

そこで自分から、修正前のビルドで撮っておいた実機スクリーンショットを共有した。見比べると、下線の位置は修正した2箇所と完全に一致していた。診断の裏付けは取れた形になったが、これは修正前のビルドの画像であって、修正後にちゃんと直っているかどうかはまだ確認できていなかった。

また出た。「まだ直っていない」

次のビルドを配信してもらった後、実機で確認してみると、まだ下線(しかも2重下線)が出ていた。念のためアプリを再インストールしてみても同じだったので、そのままAIへ伝えた。

再インストールしても直っていないということは、端末側のキャッシュが原因ではない。実機ではまだ直っていないとAIへ伝えたところ、そこで最初の診断が誤りだったと分かり、あらためて原因を調べ直してもらった。「表面的な一致」に飛びついた推測は、やはり本当の原因ではなかった。

本当の原因:Materialを持たないTextの仕様

AIは今度、実機のスクリーンショットを直接確認するところから始めた。画像は307×657pxとかなり小さかったので、Pythonで文字部分を切り出して4倍に拡大したところ、はっきりとした2本の平行線が見えた。

コードの中をTextDecorationで検索しても、下線を指定している箇所はどこにもない。指定していないのに下線が出るとはどういうことなのか。AIが外部を調べてみると、Flutterで実際に報告されている既知の現象に行き当たった。

TextウィジェットがScaffoldMaterialの祖先を持たず、文字のスタイルを解決できない場合、色を指定していなければ赤、装飾(下線等)を指定していなければ黄色い下線として表示される、という仕様だった。

問題のスプラッシュ画面は、アプリの中で唯一、Materialに包まれていない特殊な場所に配置されたテキストだった。他の画面はすべて内部でMaterialを持つ構造になっていたので、同じ症状が出なかったのも辻褄が合う。

ここで分かったのは、最初にAIが根拠にした「2箇所だけの一致」自体は、本当は正しい手がかりだったということ。ただし読み方を間違えていた。この2箇所にfontFamily指定が入っていたのも、今回下線が出たのも、どちらも根っこは同じ「Materialの外側に配置されている」という事情にあった。fontFamily指定そのものが下線を引き起こしていたわけではなく、2つの症状が同じ原因から別々に生まれていただけだった。

直し方:Materialでラップし、decorationも明示する

AIは対象のテキストをMaterial(type: MaterialType.transparency)でラップし、スタイルを正しく解決できるようにした。念のため、decoration: TextDecoration.noneもあわせて明示的に指定し、二重の対策にした。

flutter analyzeは成功、flutter testも全62件PASS。ただし今回は、この結果だけで完了とは判断しないことにした。

なぜテストでは一度も見つからなかったのか

ローカルのflutter testは、Skia系のテスト用レンダラーを使う。一方、iOS実機の既定レンダラーはImpellerで、両者は装飾が未解決のときの描画の挙動が異なる。つまりこの不具合は、ローカルのテスト環境では構造的に再現できないタイプのものだった。実機での確認だけが、唯一の検証手段だった。

実機で確認できて、ようやく完了にした

次のビルドを、自分であらためて実機で確認した。スプラッシュの二重下線は出ていなかった。ここでようやく完了とした。

Flutterで謎の下線・色が出たときのCheckList

  • 指定していないのに下線・赤い文字色が出ていたら、そのTextの祖先にMaterial(またはScaffold)があるか確認する
  • MaterialApp.builder経由で配置するWidget等、Materialの外側に配置されがちな場所は特に疑う
  • 直すときはMaterial(type: MaterialType.transparency)でラップし、decoration: TextDecoration.noneもあわせて明示指定する
  • ローカルのflutter test(Skiaレンダラー)ではiOS実機(Impellerレンダラー)特有の描画差を再現できないことがあるため、見た目の不具合は実機で確認する
  • AIが原因を説明するとき、「同じ場所で起きている」という一致だけで終わっていないか、「なぜそれが原因になるのか」の仕組みまで説明できているかを確認する

まとめ

Flutterのテキストに謎の下線が出たら、まずMaterial祖先の有無を疑うといい。今回、AIが最初に選んだ「fontFamily指定」という原因は、実は正しい手がかり(Materialの外側に配置された特殊なテキスト)を掴んでいながら、読み方を間違えたパターンだった。「同じ2箇所で起きている」という一致は本物だったのに、その一致が生まれた本当の理由(仕組み)までは説明できていなかった。

AIの推測が「もっともらしく」聞こえるときほど、その根拠が仕組みの説明になっているのか、それとも一致を指摘しているだけなのかを見分けたい。今回のように見た目の不具合ほど、最後は実機で確認するところまでを完了の条件にしておきたい。


この記事は、筆者が実際に個人開発しているモバイルゲームの開発記録(2026年8月27日〜28日)を基に、独自調整したAIが下書きを作成し、筆者が事実確認・編集を行った上で公開しています。

追記(2026-09-07): このスプラッシュ画面を含む「月灯り調合所」は、その後App Storeで一般公開された。実際のアプリは月灯り調合所の紹介ページで紹介している。

PAGE TOP
タイトルとURLをコピーしました