shinonome-inc / qiita_client_yo

【模擬開発案件】Qiitaクライアントアプリ(PlayGroundモバイルコース最終課題)
3 stars 0 forks source link

【メモ】WebViewで色々やったときのコード #37

Closed KobayashiYoh closed 2 years ago

KobayashiYoh commented 2 years ago

WebViewにもネットワークエラーを表示するのかと勘違いしていて途中まで実装しました。 git reset --hardで無かったことにするのももったいないため、自分用のメモとして残します。

mobile_yo\mobile_qiita_app\lib\components\web_view_component.dart

import 'dart:io';

import 'package:flutter/material.dart';
import 'package:mobile_qiita_app/pages/top_page.dart';
import 'package:mobile_qiita_app/views/network_error_view.dart';
import 'package:webview_flutter/webview_flutter.dart';

class WebViewComponent extends StatefulWidget {
  const WebViewComponent({required this.initialUrl, Key? key})
      : super(key: key);

  final String initialUrl;

  @override
  _WebViewComponentState createState() => _WebViewComponentState();
}

class _WebViewComponentState extends State<WebViewComponent> {
  late WebViewController _webViewController;
  double _webViewHeight = 0;
  bool _isLoading = false;
  bool _isError = false;

  Future<void> _calculateWebViewHeight() async {
    double newHeight = double.parse(
      await _webViewController
          .evaluateJavascript("document.documentElement.scrollHeight;"),
    );
    setState(() {
      _webViewHeight = newHeight;
    });
    print(newHeight);
  }

  Future<void> _reload() async {
    await _webViewController.reload();
  }

  void _backToTopPageWithRedirectUrl(String url) {
    bool hasCode = url.contains('https://qiita.com/settings/applications?code');
    if (hasCode) {
      Navigator.of(context).push(
        MaterialPageRoute(
          builder: (_) => TopPage(redirectUrl: url),
        ),
      );
    }
  }

  @override
  void initState() {
    super.initState();
    if (Platform.isAndroid) {
      WebView.platform = SurfaceAndroidWebView();
    }
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Column(
        children: [
          Stack(
            children: [
              Container(
                height: _webViewHeight,
                child: WebView(
                  initialUrl: widget.initialUrl,
                  javascriptMode: JavascriptMode.unrestricted,
                  onPageStarted: (String url) async {
                    setState(() {
                      _isLoading = true;
                    });
                  },
                  onPageFinished: (String url) async {
                    setState(() {
                      _isLoading = false;
                    });
                    _calculateWebViewHeight();
                    _backToTopPageWithRedirectUrl(url);
                  },
                  onWebResourceError: (error) {
                    setState(() {
                      _isError = true;
                    });
                  },
                  onWebViewCreated: (controller) async {
                    _webViewController = controller;
                  },
                ),
              ),
              if (_isError || _isLoading || !_isError)
                Container(
                  height: _webViewHeight,
                  color: Colors.white,
                ),
              if (_isError || !_isError)
                Container(
                  // デバイスに表示されているModalBottomSheetの高さ
                  height: MediaQuery.of(context).size.height * 0.94 - 59.0,
                  child: NetworkErrorView(onTapReload: _reload),
                ),
              if (_isLoading)
                Container(
                  // デバイスに表示されているModalBottomSheetの高さ
                  height: MediaQuery.of(context).size.height * 0.94 - 59.0,
                  child: Center(child: CircularProgressIndicator()),
                ),
            ],
          ),
        ],
      ),
    );
  }
}