リバース・エンジニアリング

Flultterとテックブログと時々iOS

20. Flutter公式のプラグインを使ってWebViewを表示させる

今回はFlutterでWebViewウィジェットを使ってみたいと思います。

前回の続きになりますが、念の為、前回どこまでしたのかを復習する場合はこちらになります。

blog.tamappe.com

FlutterのWebViewプラグイン

Flutter公式にWebViewのパッケージwebview_flutterがあります。

pub.dev

これを使ってFlutterでWebViewを導入してみます。

webview_flutterの使い方

それではwebview_flutterの使い方について紹介します。

まずはpubspec.yamlファイルのdependenciesに次のコードを記載します。

dependencies:
  flutter:
    sdk: flutter

  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^0.1.2
  webfeed: ^0.4.2
  http: ^0.12.0+4
  webview_flutter: ^0.3.19+7 # こちらを追加する

これでパッケージを更新するとwebview_flutterが使えるようになります。 webview_flutter.dartをimportして使います。

import 'package:webview_flutter/webview_flutter.dart';

サンプルコード

それではWebViewを表示させるサンプルコードを書きます。

custom_webview.dart

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

class CustomWebPage extends StatefulWidget {
  @override
  _CustomWebPageState createState() => _CustomWebPageState();
}

class _CustomWebPageState extends State<CustomWebPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: Text("WebPage")),
        body: WebView(
          initialUrl: "https://qiita.com",
          javascriptMode: JavascriptMode.unrestricted,
        ));
  }
}

main.dart

import 'package:flutter/material.dart';
import 'package:rss_app/custom_webview.dart';
import 'package:rss_app/rss_list_page.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'WebPage',
      theme: ThemeData(
        primarySwatch: Colors.green,
      ),
      home: CustomWebPage(),
    );
  }
}

これでビルドしてQiitaのページが表示されれば完成です。

f:id:qed805:20200216233535p:plain
QiitaのWebページ

RSSアプリに適用させる

それでは、前回RSSの基礎になるアプリを開発しましたので、 今回はさらに一覧ページでitemをタップすると詳細ページをWebViewで表示させるところまで実装したいと思います。

item_detail_page.dart

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

class ItemDetailPage extends StatefulWidget {
  final AtomItem item;

  ItemDetailPage({
    @required this.item
  });

  @override
  _ItemDetailPageState createState() => _ItemDetailPageState(item: item);
}

class _ItemDetailPageState extends State<ItemDetailPage> {
  AtomItem item;

  _ItemDetailPageState({@required this.item});

  @override
  Widget build(BuildContext context) {
    print(item.links.first.href);
    return Scaffold(
      appBar: AppBar(
        title: Text(item.title),
      ),
      body: Center(
          child: WebView(
            initialUrl: item.links.first.href,
            javascriptMode: JavascriptMode.unrestricted,
          )
      ),
    );
  }
}

rss_list_page.dart

import 'package:flutter/material.dart';
import 'package:rss_app/item_detail_page.dart';
import 'package:webfeed/webfeed.dart';
import 'package:http/http.dart';

class RssListPage extends StatefulWidget {
  final String title;
  final String url;

  RssListPage({@required this.title, @required this.url});

  @override
  _RssListPageState createState() => _RssListPageState(title: title, url: url);
}

class _RssListPageState extends State<RssListPage> {
  final String _rssUrl = "https://qiita.com/tamappe/feed.atom";
  final String title;
  final String url;
  List<Widget> _items = [];

  _RssListPageState({@required this.title, @required this.url}) {
    convertItemFromXML();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("RSS リーダー"),
      ),
      body: Center(
        child: ListView(
          padding: EdgeInsets.all(10.0),
          children: _items,
        ),
      ),
    );
  }

  void convertItemFromXML() async {
    List<Widget> list = [];
    Response res  = await get(_rssUrl);
    var atomFeed = new AtomFeed.parse(res.body);
    for (AtomItem item in atomFeed.items) {
      list.add(ListTile(
        contentPadding: EdgeInsets.all(10.0),
        title: Text(
          item.title,
        ),
        subtitle: Text(
            item.published
        ),
        onTap: () {
          Navigator.push(context, MaterialPageRoute(
              builder: (_) =>
                  ItemDetailPage(
                    item: item,
                  )
          ));
        },
      ));
    }
    setState(() {
      _items = list;
    });
  }
}

main.dart

import 'package:flutter/material.dart';
import 'package:rss_app/rss_list_page.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'RSSアプリ',
      theme: ThemeData(
        primarySwatch: Colors.green,
      ),
      home: RssListPage(),
    );
  }
}

これをビルドすると最初の画面ではQiitaの私のフィードのRSSが一覧で表示されます。 そのどれかのitemをタップするとそのitemの詳細ページをWebViewで表示させることができます。

これで前回のRSSのパースからページ遷移して詳細ページまでの実装ができたことになります。

以上今回はWebViewの実装について学習しました。