[Flutter]グーグルフォームをオリジナルデザインにする。

以前作ったwebviewでグーグルフォームを表示するプログラムをちょっとだけ変えます。

import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:xxx/provider/contact_us_provider.dart';
import 'package:webview_flutter/webview_flutter.dart';

class ContactUsPage extends HookWidget {
 @override
 Widget build(BuildContext context) {
   final cusp = useProvider(contactUsStateProvider);
   final contactUsState = useProvider(contactUsStateProvider.state);
   final Completer<WebViewController> _controller =
       Completer<WebViewController>();
       
   useEffect(() {
     if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView();
     cusp.check();
     return () {};
   }, []);
   
   return Scaffold(
     appBar: AppBar(
       title: Text('お問い合わせ'),
     ),
     body: Builder(builder: (BuildContext context) {
       return contactUsState.connectionStatus == true
           ? IndexedStack(
               index: contactUsState.position,
               children: [
                 WebView(
                   initialUrl:'',
                   javascriptMode: JavascriptMode.unrestricted,
                   onWebViewCreated:
                       (WebViewController webViewController) async {
                     _controller.complete(webViewController);
                     // HTMLファイルのURL(ローカルファイルの情報)をControllerに追加する処理
                     await _loadHtmlFromAssets(_controller);
                   },
                   onPageFinished: cusp.doneLoading, // indexを0にしてWebViewを表示
                   onPageStarted:
                       cusp.startLoading, // indexを1にしてプログレスインジケーターを表示
                 ),
                 // プログレスインジケーターを表示
                 Container(
                   child: Center(
                     child: CircularProgressIndicator(
                         backgroundColor: Colors.blue),
                   ),
                 ),
               ],
             )
           // インターネットに接続されていない場合の処理
           : SafeArea(
               child: Center(
                 child: Column(
                   children: [
                     Padding(
                       padding: EdgeInsets.only(
                         top: 120,
                         bottom: 20,
                       ),
                       child: Container(),
                     ),
                     Padding(
                       padding: EdgeInsets.only(
                         bottom: 20,
                       ),
                       child: Text(
                         'インターネットに接続されていません',
                       ),
                     ),
                   ],
                 ),
               ),
             );
     }),
   );   
 }
 
 /// HTMLファイルを読み込む処理(非同期)
 Future _loadHtmlFromAssets(controller) async {
   //HTMLファイルを読み込んでHTML要素を文字列で返す
   final fileText = await rootBundle.loadString('assets/html/contact_us.html');
   final String contentBase64 =
         base64Encode(const Utf8Encoder().convert(fileText));
     await controller.loadUrl('data:text/html;base64,$contentBase64');
 }
}

このまま動かしてもエラー出る。

pubspec.yamlに以下を追加。htmlファイルはassets/html/内に配置している。

assets:
  - assets/html/

追加して動かしてみたけどメソッドが無いエラー。

Unhandled Exception: NoSuchMethodError: Class '_AsyncCompleter<WebViewController>' has no instance method 'loadUrl'

数時間経過。。。

onWebViewCreated:
                       (WebViewController webViewController) async {
                     _controller.complete(webViewController);
                     // HTMLファイルのURL(ローカルファイルの情報)をControllerに追加する処理
                     await _loadHtmlFromAssets(_controller);
                   },

onWebViewCreated:
                       (WebViewController webViewController) async {
                     _controller.complete(webViewController);
                     // HTMLファイルのURL(ローカルファイルの情報)をControllerに追加する処理
                     await _loadHtmlFromAssets(webViewController);
                   },

_loadHtmlFromAssets()の引数を変えて通った。とりあえずエラー出無さそうなのでこのままで。

contact_us.htmlは以下のようになっています。

<!DOCTYPE html>
<html lang="ja">
 <head>
   <meta charset="utf-8">
   <meta http-equiv="X-UA-Compatible" content="IE=edge">
   <!-- ビューポートの設定 -->
   <meta name="viewport" content="width=device-width,initial-scale=1">
 </head>
 <body>
   <form action="https://docs.google.com/forms/u/0/d/e/xxxxktyO7KfMEbVH33oW5526Xy-w/formResponse" target="_self" method="POST" id="mG61Hd" jsmodel="TOfxwf Q91hve" data-response="%.@.[]]" data-first-entry="0" data-last-entry="2" data-is-first-page="true">

     <h1>お問い合わせ</h1>
   
     <!-- 件名入力 -->      
     <div class="p-formGroup u-mb20">
       <label for="subject">件名</label>
       <input name="entry.2345677" type="text" required="required" id="textfield" class="g_form" placeholder="件名">
     </div>
     <!--//End 件名入力 -->
   
     <!-- お問い合わせ内容入力 -->
     <div class="p-formGroup u-mb20">
       <label for="content">お問い合わせ内容</label>
       <textarea name="entry.123456789" required class="g_form_text" id="entry.952897594"
placeholder="お問い合わせ"></textarea>
     </div>      
     <!--//End お問い合わせ内容入力 -->
   
     <!-- 送信 -->
     <div class="p-form__btn">
       <input type="submit" value="送信する">
     </div>
     <!--//End 送信 -->
   </form>
 </body>
</html>

ここで重要なのは、form action='xxxx'、input name="entry.xxxx"、textarea name="entry.xxxx"この値をグーグルフォームの値と合わせていく。詳しくわ(2020年6月最新版【仕様変更対応済み】Googleフォームを好きなようにカスタマイズする方法)をご覧ください。

これでローカルにあるコンタクトフォームのhtmlをflutterからwebviewを通して呼び出して、グーグルフォームと連携することができる。

この記事が気に入ったらサポートをしてみませんか?