【Flutter】Markdown(マークダウン)を表示

対象者

  • Flutterでマークダウンを使用したい人

はじめに

この記事では、Flutterでマークダウン形式のファイルの内容を表示する方法を解説してます。パッケージはメジャーなものと多機能なモノの2種類試しました。

もともとは、Flutterのアプリでプライバシーポリシーを表示したい。マークダウンのファイルを書いて、それをいい感じにWidgetにしてくれないかと思いました。

パッケージ

  • flutter_markdown
    Likeが900近い(2023/02/20 現在)ので、多分一番のメジャーどころです。
    こちらを試しましたが、張ってあるリンクからブラウザに飛べなかったので、他のパッケージを探しました。

  • markdown_widget
    Likeが100を超えているので、一般的にも使われていそうです。また、リンクから飛べそうな記述があり、実際に飛べました。

スクリーンショット

flutter_markdown markdown_widge(上部) markdown_widget(下部)
Mateerial2 Mateerial3 Mateerial3

比較

  • 全体
    flutter_markdown の方が全体にコンパクトに表示できる
  • リンク
    flutter_markdown は色が変わるだけ、markdown_widge はブラウザで開ける
  • 表示できない項目
    flutter_markdown はなかったことにする。markdown_widge はそのまま表示される
  • 改行
    flutter_markdown は改行に空白行が必要。markdown_widge は改行だけで良い
  • テーブル
    両方できない
  • タイトル
    両方できる
  • 画像(外部Webサーバの画像でテスト)
    両方できる
  • リスト
    両方できる
  • 折りたたみ
    両方できない

ソース

ソースのキモです。
importして、それぞれのマークダウン用のWidgetにマークダウン形式のStringを渡すだけです。

flutter_markdown

import 'package:flutter_markdown/flutter_markdown.dart';

child: Markdown(
  data: markdownText,
),

  final String markdownText = '# Markdownパッケージの実線(# h1)';

markdown_widget

import 'package:markdown_widget/widget/markdown.dart';


child: MarkdownWidget(
  data: markdownText,
),

  final String markdownText = '# Markdownパッケージの実線(# h1)';

まとめ

ということで、Flutterのマークダウンのパッケージ2つを見てきました。
プライバシーポリシーから別URLに飛びたいので、「markdown_widget」を今回は採用します。ただこのパッケージ自体も他のパッケージを参照しているので、依存性を増やしたくない場合(実行ファイルの大きさが大きくなる、パッケージのバージョンの不整合が起こる可能性がある)で、リンクを使わない場合は、flutter_markdown を使うつもりです。

参考

ソース全体

現在「markdown_widget」が動くソースになっている。
「flutter_markdown」に切り替えるときは、import文と「child: MarkdownWidget(」の周辺のコメントを切り替える。

import 'package:flutter/material.dart';
//  flutter pub remove markdown_widget
// flutter pub add flutter_markdown
//import 'package:flutter_markdown/flutter_markdown.dart';
//  flutter pub remove flutter_markdown
// flutter pub add markdown_widget
import 'package:markdown_widget/widget/markdown.dart';
void main() {
  runApp(const MyApp());
}
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'flutter_markdown Demo'),
    );
  }
}
class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;
  @override
  State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: MarkdownWidget(
          // child: Markdown(
          data: markdownText,
        ),
      ),
    );
  }
  final String markdownText = '''
# Markdownパッケージの実線(# h1)
## 強調関連(## h2)
### サブタイトル(### h3)
#### サブ・サブタイトル(#### h4)
通常
**強調** 
*斜線* 
~取消~ 
## リンク
[リンク](https://www.google.com)
## 改行
空白行あり→改行できる 
空白行なし
→改行できない
## Details - 折りたたみ
サンプルコード (上に空行が必要) ```rb puts 'Hello, World' ```
### リスト - リスト1 - リスト2 ## 画像 ![Qiita](https://qiita-image-store.s3.amazonaws.com/0/45617/015bd058-7ea0-e6a5-b9cb-36a4fb38e59c.png "Qiita") ## テーブル | Left align | Right align | Center align | |:-----------|------------:|:------------:| | column | column | column | ## 終わり '''; }