HTMLファイルを表示する

2024年7月15日

開発環境
OS:Windows 11
SDK:VS Code + Flutter 3.7.12

概要

アプリ内のローカルストレージに格納したhtmlファイルを画面に表示します。

WebViewウィジェットを準備する

HTMLファイルはWebViewウィジェットを通して表示します。

そのため、WebViewパッケージをインストールする必要があります。

サンプルプロジェクトを生成して動作確認してみます。

webview_flutterをインストールします。

HTMLファイルを準備する

次にHTMLファイルを準備します。

<!DOCTYPE html>
<html lang="ja">

  <head>
    <meta charset="UTF-8">
    <title>Top Page</title>
  </head>

  <script>
    function sendData1() {
      // Flutterへデータ送信
      sample.postMessage("1");
    }
    function sendData2() {
      // Flutterへデータ送信
      sample.postMessage("2");
    }
  </script>

  <body>
    <h1>Please tap a button.</h1>
    <br>
    <br>
    <button onclick="sendData1()">Send Data 1</button>
    <br>
    <br>
    <button onclick="sendData2()">Send Data 2</button>
  </body>
</html>

ボタンが2つあるHTMLファイル(top.html)を作成しました。

プロジェクトフォルダ内に「html」フォルダを作成し、その中に作成したhtmlファイルを格納します。

次にpubspec.yamlのassets項目にhtmlファイルを定義します。

  assets:
    - html/top.html

WebViewウィジェット実装

main.dartにWebViewウィジェットを追加します。

ネットワーク上のurlにアクセスして表示するわけではないため、htmlのロード処理もあわせて追加する必要があります。

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:webview_flutter/webview_flutter.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

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

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  late WebViewController controller;
  late Future<void> controllerInitialization;

  @override
  void initState() {
    super.initState();
    controllerInitialization = initController();
  }

  Future<void> initController() async {
    final html = await rootBundle.loadString('html/top.html');
    controller = WebViewController()
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..addJavaScriptChannel('sample', onMessageReceived: (result) async {
          switch (result.message) {
            case "1":
              print("call 1.");
              break;
            case "2":
              print("call 2.");
              break;
          }
        })
      ..loadRequest(
        Uri.dataFromString(
          html,
          mimeType: "text/html",
          encoding: Encoding.getByName("utf-8"),
        ),
      );
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<void>(
      future: controllerInitialization,
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.done) {
          return Scaffold(
            appBar: AppBar(title: const Text("Test Page")),
            body: WebViewWidget(controller: controller),
          );
        } else {
          return const CircularProgressIndicator();
        }
      },
    );
  }
}

※Android向けのビルドが失敗した場合はこちら↓をチェックしてみてください。

動作確認

デバッグモードで起動しました。

HTMLのテキストと2つのボタンは期待通りに表示されています。

次にボタンを押し分けてみると・・・

ターミナルに「call 1.」、「call 2.」が表示されました。

ボタン操作も処理できることが確認できました。

今回は以上です。

Webサイトを表示する

2023年8月5日

開発環境
OS:Windows 11
SDK:VS Code + flutter 3.7.5

概要

Webサイトを表示します。

Webサイトを表示する方法

flutterでWebサイトを表示する方法は2パターンあります。

Webブラウザを起動させて表示する方法と

ウィジェットWebViewを用意し、ウィジェットに表示させる方法です。

パターン1.Webブラウザを起動させて表示する

まずはパッケージ、url_launcher(ver 6.1.11)を導入します。

パッケージ詳細はこちら

コマンド入力する場合は、プロジェクトフォルダまで移動した後、下記を入力します。

flutter pub add url_launcher

あとは、launchUrlString(URL)をコールするだけです。

今回は、関数化し、ボタンタップ時に実行させるようにしました。

import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher_string.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

void _openUrl() async {
  const url = 'https://messageexchanger-fa3e1.web.app';
  if (await canLaunchUrlString(url)) {
    await launchUrlString(url);
  } else {
    throw 'can not access this url.';
  }
}

class _MyHomePageState extends State<MyHomePage> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        width: double.infinity,
        height: double.infinity,
        alignment: Alignment.center,
        child: Column(
          children: <Widget>[
            Expanded(
              flex: 1,
              child: Container(
                alignment: Alignment.center,
                child:Image.asset('images/sample.jpg'),),),
            Expanded(
              flex :1,
              child: Container(
                alignment: Alignment.center,
                child: ElevatedButton(
                  onPressed: () async {
                    _openUrl();
                  },
                  style: ElevatedButton.styleFrom(
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(5),
                    ),
                  ),
                  child: const Text('Web'),
                  ),))
          ],
        ),
      ),
    );
  } 
}

Chromeで実行した結果、Webサイトが表示されました。

起動時
ボタンタップ後

Androidで実行する場合は、AndroidManifest.xmlにqueries定義を追加する必要があります。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.sample">

    <queries>
        <intent>
            <action android:name="android.intent.action.VIEW" />
            <data android:scheme="https" />
        </intent>
    </queries>

   <application
        android:label="sample"
        android:name="${applicationName}"
        android:icon="@mipmap/ic_launcher">

  ・・・
起動時
ボタンタップ後

パターン2.ウィジェットWebViewを用意し、ウィジェットに表示させる

まずはパッケージ、webview_flutter(ver4.2.2)を導入します。

パッケージ詳細はこちら

コマンド入力する場合は、プロジェクトフォルダまで移動した後、下記を入力します。

flutter pub add webview_flutter

あとは、ScaffoldのbodyにWebViewWidgetを配置するだけです。

今回は、メイン画面とサブ画面の2画面を作成し、メイン画面でボタンタップするとWebViewWidgetを配置したサブ画面に遷移させるようにしてみました。

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';

class SubPage extends StatelessWidget  {
  const SubPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body:WebViewWidget(
            controller: WebViewController()
              ..setJavaScriptMode(JavaScriptMode.unrestricted)
              ..loadRequest(Uri.parse("https://messageexchanger-fa3e1.web.app"))
          ),
    );
  }
}

Androidアプリで実行した結果、Webサイトが表示されました。

メイン画面
サブ画面

WebViewの注意点

webview_flutterのパッケージ詳細を見ると

サポート対象機種が、AndroidとiOSとなっています。

サポート対象に記載のないChromeで表示するとサブ画面表示のタイミングでダウンしました。

Chromeでは使用できないようです。

今回は以上です。