一般社団法人 全国個人事業主支援協会

COLUMN コラム

Flutterでアプリ開発を行っていると、
WebViewを使って広告や動的コンテンツを表示する場面が多くあります。
しかし、特にiOSでは注意しなければならない落とし穴があります。

それは、
「画面に表示されないとWebView内のJavaScriptが動作しない」
という問題です。


なぜそのようなことが起きるのか?

理由はシンプルでありながら、少し深い背景があります。

iOSの省電力最適化

AppleのWKWebViewでは、画面外にある場合、リソース消費を抑えるため、描画やJavaScriptの実行を停止する仕様となっております。
「見えていないものにCPUを使わない」という合理的な設計思想に基づく動作です。

FlutterのPlatformView制約

また、FlutterにおけるWebViewWidgetは通常のWidgetとは異なり、ネイティブ側のPlatformViewとして扱われます。
そのため、Flutterのスクロールやレイアウトサイクルとはタイミングがずれてしまい、WebViewの描画が遅れたり、JavaScriptの実行タイミングが遅延しやすくなるのです。

この二重の要因が重なることで、
「画面内に入りきるまではWebView内のJavaScriptが動かない」
という現象が発生します。


具体的にどのような症状が現れるのか?

  • WebViewに設定したJavaScriptが最初は動かない

  • スクロールして画面内に入った瞬間に、ようやく動き始める

  • 最悪の場合、画面外にある間は何も動作しない

  • リストやバナーに組み込んだ際、読み込み失敗のように見えてしまう

このような現象が発生することがあります。


どのように解決すればよいのか?【実践的な対策】

1. VisibilityDetectorを使用する

Flutterにはvisibility_detectorという便利なパッケージが存在します。
これを利用することで、Widgetが画面に表示されたタイミングを検出することが可能です。

つまり、
「見えるようになった瞬間に初めてロードを開始する」
という設計に切り替えることで、問題を回避できます。

この方法は、現場でも最も多く採用されています。


2. 高さを固定して初期状態から画面内に配置する

可能であれば、WebViewの高さを固定(例えば高さ200pxなど)して、
初期表示時から画面内に収まる位置に配置する方法も有効です。

これにより、ページロード直後からJavaScriptが問題なく動作します。
ただし、ページ内容によって高さが変わるバナー広告など、動的な高さが必要なケースでは適用が難しい場合があります。


3. SingleChildScrollViewに切り替える

特にシンプルな画面構成であれば、
CustomScrollViewのような複雑なSliver構造をやめて、
SingleChildScrollViewColumn構成に切り替えることも非常に有効です。

この方法であれば、スクロールの管理がFlutter側のみとなるため、
WebViewの表示判定やスクロール干渉に起因する問題を大きく軽減できます。

もちろん、リストアイテムが非常に多い場合には注意が必要ですが、
適度な量のコンテンツであれば、非常に効果的な解決策となります。


注意点:Androidでは問題が発生しにくいことも

ちなみに、Androidでは

  • WebViewが画面外でも比較的自由に動作する

  • スクロール中でもJavaScriptの実行に大きな制約がない

という特性があるため、
この問題は基本的にiOS特有のものと考えたほうがよいでしょう。

クロスプラットフォーム開発を行う際には、
iOS実機での検証を怠らないことが非常に重要です。


【まとめ】

問題 対策
画面外だとWebView内のJavaScriptが動かない(特にiOS) VisibilityDetectorで表示を検知してからloadする
そもそも画面内に入る前に動作させたい 高さを固定して初期表示時から画面内に配置する
CustomScrollViewとの相性が悪い SingleChildScrollViewに切り替える

この記事をシェアする

  • Twitterでシェア
  • Facebookでシェア
  • LINEでシェア