🙆‍♀️

【Flutter】複数タブで各ページの状態を保持しながらWebViewを使う

2022/07/31に公開

ソースコード

https://github.com/popy1017/flutter_multi_webview

※ WebView には flutter_inappwebview パッケージを使用。

https://pub.dev/packages/flutter_inappwebview/example

課題

PageViewやTabBarViewでWebViewを表示している際、WebViewのページ(またはタブ)を表示するたびにロードが走ってしまう。
→ Webページの状態(スクロール位置や表示内容)が保持できない。

解決策

こちらのQAを参考にした。

https://stackoverflow.com/questions/56985081/how-to-make-webview-not-reload-when-i-switch-appbar-in-my-flutter-app

WebViewをAutomaticKeepAliveClientMixinをmixinしたWidgetとすることで、ページやタブ切り替え時にも状態が保持できるようになる。

AutomaticKeepAliveClientMixinをmixinしたWebView
class KeepAliveWebPage extends StatefulWidget {
  const KeepAliveWebPage(this.url, {Key? key}) : super(key: key);

  final String url;

  
  State<KeepAliveWebPage> createState() => _KeepAliveWebPageState();
}_

class _KeepAliveWebPageState extends State<KeepAliveWebPage>
    with AutomaticKeepAliveClientMixin {
  
  Widget build(BuildContext context) {
    super.build(context);
    return InAppWebView(
      initialUrlRequest: URLRequest(url: Uri.parse(widget.url)),
    );
  }

  
  bool get wantKeepAlive => true;
}
PageViewの書き方は通常の使い方通り
class PageWebView extends StatefulWidget {
  const PageWebView({Key? key}) : super(key: key);

  
  State<PageWebView> createState() => _PageWebViewState();
}

class _PageWebViewState extends State<PageWebView> {
  final _controller = PageController();

  int _currentPageIndex = 0;

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Page: $_currentPageIndex'),
      ),
      body: PageView(
        controller: _controller,
        children: const [
          KeepAliveWebPage("https://flutter.dev/"),
          KeepAliveWebPage("https://www.nintendo.co.jp/"),
          KeepAliveWebPage("https://www.playstation.com/ja-jp/"),
        ],
        onPageChanged: (int pageIndex) {
          setState(() {
            _currentPageIndex = pageIndex;
          });
        },
      ),
    );
  }
}

Discussion