📧

GoogleFormをレスポンシブ対応する

2023/02/02に公開

レスポンシブに自動ではしてくれない

GoogleFormはタダで使えて便利ですよね。最近はお問い合わせフォームでよく使われているみたいです。
Flutterで使いたいなと、思いWebViewに組み込もうとしたらうまくいかなかった!
WebViewのpackageがもうサポートされてないぽい?

url_launcherを使えばWebページを表示することができるので、こちらの方法でやってみました。
https://pub.dev/packages/url_launcher

で、表示はできたのですが画面に収まっていないので、レスポンシブ対応できてないようです。

レスポンシブ対応の方法

こちらのサイトが参考になりました。
Defaultだと、width="640"なので、こちらをwidth="100%"に変更します。

https://form.run/media/contents/form-creation-tools/google-form-responsive-embed/#Google3

Netlifyにhostingした、サイトを使ってます。
https://www.netlify.com/
Deployする方法
https://inno-tech-life.com/dev/infra/publish_netlify/

Webサイトのコード

index.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.0">
  <title>お問い合わせフォーム</title>
  <style>
    .web-form {
      display: block;
      margin-left: auto;
      margin-right: auto;
    }
  </style>
</head>
<body>
  <iframe class="web-form" src="Netlifyで公開しているGoogleFormのURLをはる" width="100%" height="539" frameborder="0" marginheight="0" marginwidth="0">読み込んでいます…</iframe>
</body>
</html>

Flutterのコード

以前書いた記事を参考に、OSごとの設定をしてもらえると使えると思います。
なぜか、新しく作ったプロジェクトでiOSだけBuildできないことがあったのですが、Podfile.lockを削除して、flutte cleanしたらできました😇
Flutter謎が多いですね。。。。

iOSの設定

info.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
	<dict>
		<!-- ここから -->
		<key>LSApplicationQueriesSchemes</key>
		<array>
			<string>sms</string>
			<string>tel</string>
		</array>
		<!-- ここまで -->
		<key>CFBundleDevelopmentRegion</key>
		<string>$(DEVELOPMENT_LANGUAGE)</string>
		<key>CFBundleDisplayName</key>
		<string>Google Form</string>
		<key>CFBundleExecutable</key>
		<string>$(EXECUTABLE_NAME)</string>
		<key>CFBundleIdentifier</key>
		<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
		<key>CFBundleInfoDictionaryVersion</key>
		<string>6.0</string>
		<key>CFBundleName</key>
		<string>google_form</string>
		<key>CFBundlePackageType</key>
		<string>APPL</string>
		<key>CFBundleShortVersionString</key>
		<string>$(FLUTTER_BUILD_NAME)</string>
		<key>CFBundleSignature</key>
		<string>????</string>
		<key>CFBundleVersion</key>
		<string>$(FLUTTER_BUILD_NUMBER)</string>
		<key>LSRequiresIPhoneOS</key>
		<true />
		<key>UILaunchStoryboardName</key>
		<string>LaunchScreen</string>
		<key>UIMainStoryboardFile</key>
		<string>Main</string>
		<key>UISupportedInterfaceOrientations</key>
		<array>
			<string>UIInterfaceOrientationPortrait</string>
			<string>UIInterfaceOrientationLandscapeLeft</string>
			<string>UIInterfaceOrientationLandscapeRight</string>
		</array>
		<key>UISupportedInterfaceOrientations~ipad</key>
		<array>
			<string>UIInterfaceOrientationPortrait</string>
			<string>UIInterfaceOrientationPortraitUpsideDown</string>
			<string>UIInterfaceOrientationLandscapeLeft</string>
			<string>UIInterfaceOrientationLandscapeRight</string>
		</array>
		<key>UIViewControllerBasedStatusBarAppearance</key>
		<false />
		<key>CADisableMinimumFrameDurationOnPhone</key>
		<true />
		<key>UIApplicationSupportsIndirectInputEvents</key>
		<true />
	</dict>
</plist>

Androidの設定

app/build.gradle
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
    localPropertiesFile.withReader('UTF-8') { reader ->
        localProperties.load(reader)
    }
}

def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
    throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}

def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
    flutterVersionCode = '1'
}

def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
    flutterVersionName = '1.0'
}

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"

android {
    compileSdkVersion 33 // 33に設定
    ndkVersion flutter.ndkVersion

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    kotlinOptions {
        jvmTarget = '1.8'
    }

    sourceSets {
        main.java.srcDirs += 'src/main/kotlin'
    }

    defaultConfig {
        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
        applicationId "com.example.google_form"
        // You can update the following values to match your application needs.
        // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
        minSdkVersion 21 // 21に設定
        targetSdkVersion 33 // 33に設定
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
    }

    buildTypes {
        release {
            // TODO: Add your own signing config for the release build.
            // Signing with the debug keys for now, so `flutter run --release` works.
            signingConfig signingConfigs.debug
        }
    }
}

flutter {
    source '../..'
}

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
app/src/main/AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.google_form">
    <uses-permission android:name="android.permission.INTERNET"/>
<!-- ここから -->
<queries>
    <!-- If your app checks for SMS support -->
    <intent>
      <action android:name="android.intent.action.VIEW" />
      <data android:scheme="sms" />
    </intent>
    <!-- If your app checks for call support -->
    <intent>
      <action android:name="android.intent.action.VIEW" />
      <data android:scheme="tel" />
    </intent>
    <!--#enddocregion android-queries-->
    <!-- The "https" scheme is only required for integration tests of this package.
         It shouldn't be needed in most actual apps, or show up in the README! -->
    <intent>
      <action android:name="android.intent.action.VIEW" />
      <data android:scheme="https" />
    </intent>
    <!--#docregion android-queries-->
  </queries>
<!-- ここまで -->
   <application
        android:label="google_form"
        android:name="${applicationName}"
        android:icon="@mipmap/ic_launcher">
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">
            <!-- Specifies an Android theme to apply to this Activity as soon as
                 the Android process has started. This theme is visible to the user
                 while the Flutter UI initializes. After that, this theme continues
                 to determine the Window background behind the Flutter UI. -->
            <meta-data
              android:name="io.flutter.embedding.android.NormalTheme"
              android:resource="@style/NormalTheme"
              />
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <!-- Don't delete the meta-data below.
             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />
    </application>
</manifest>
googleform_page.dart
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';

class GoogleForm extends StatelessWidget {
  const GoogleForm({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('URL Launcher'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            IconButton(
                onPressed: () async {
                  final url = Uri.parse(
                    'NetlifyのURL',
                  );
                  if (await canLaunchUrl(url)) {
                    launchUrl(url);
                  } else {
                    // ignore: avoid_print
                    print("Can't launch $url");
                  }
                },
                icon: const Icon(
                  Icons.mail,
                  color: Colors.red,
                  size: 50.0,
                )),
          ],
        ),
      ),
    );
  }
}
main.dart
import 'package:flutter/material.dart';
import 'package:google_form/googleform_page.dart';
import 'package:url_launcher/url_launcher.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('URL Launcher'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
                onPressed: () {
                  Navigator.push(context,
                      MaterialPageRoute(builder: (context) => GoogleForm()));
                },
                child: Text('お問い合わせ'))
          ],
        ),
      ),
    );
  }
}

アプリの画面

Android



iPhone

送信すると確認できたので成功していますね!



まとめ

SendGrid契約したので、こっち使いたいなと思ったのですが、GoogleFormは無料で使えるし採用している企業は多いので、レスポンシブ対応してモバイルで使えるようにした方が工数削減になるので、見た目は、カッコよくないですが、メリットは大きいです。
皆さんも試してみてください!

Flutter大学

Discussion