すらぼうの開発ノート

flutterエンジニアのメモ

【Flutter】fl_chartで曲線・折れ線グラフを作成する方法

本エントリではfl_chartで曲線・折れ線グラフを作成する方法を以下の流れで説明する。



fl_chartとは

概要

fl_chartはFlutterでグラフを作成するためのパッケージ。 簡単にインタラクティブなグラフを作成することができる。

公式ページは以下。

pub.dev

作成可能なグラフ

2022年8月15日現在fl_chartを用いることで以下のグラフを作成することができる。

  • Line Chart (曲線・折れ線グラフ)

line chart

  • Bar Chart (棒グラフ)

bar chart

  • Pie Chart (円グラフ)

    pie chart

  • Scatter Chart (散布図)

scatter chart

  • Radar Chart (レーダーチャート)

radar chart

またfl_chartgithubリポジトリはドキュメントが充実しており、興味があればそちらも確認して欲しい。 各クラスのパラメータについて詳細に記載されており大変参考になる。

github.com

曲線・折れ線グラフ作成方法

ここからfl_chartを用いた曲線・折れ線グラフの作成方法を説明する。

使用するクラス

グラフ作成に使用するクラスは以下。

LineChart

曲線・折れ線グラフ作成の大元のクラス。 このクラスに各種設定を指定していく。

LineChartData

LineChartデザイン(座標範囲や背景色、軸ラベルの表示など)を扱うクラス。

LineChartBarData

LineChart描画するための各データを扱うクラス。

例えば以下のように特定の地域の最高気温と最低気温のグラフを、同じ座標軸に描画した場合を考える。

気温グラフの例

この時LineChartBarDataに相当するのは各線グラフのデータ。 つまり「平均気温のデータ」で一つのLineChartBarDataクラスとなる。

FlSpot

座標上の一つ一つのプロットを扱うクラス。 メンバ変数はxyのみなので直感的にもわかりやすい。

FlDotData

座標上のプロットのデザインを扱うクラス。

FlTitlesData

グラフの軸ラベルのデザイン、表示非表示の設定などを扱うクラス。

AxisTitles

グラフの各軸ラベルの詳細なデザインを扱うクラス。

SideTitles

グラフ各軸の目盛のデザインを扱うクラス。

グラフ化するデータ

本エントリではLine Chart (曲線・折れ線グラフ)の作成方法を「2021年の東京都の年間平均気温」をグラフ化する。

データは気象庁が公開しているデータから引用した。

month avg. temperature
1 5.4
2 8.5
3 12.8
4 15.1
5 19.6
6 22.7
7 25.9
8 27.4
9 22.3
10 18.2
11 13.7
12 7.9

インストール

fl_chartサードパーティのパッケージなので、pubspec.yamlに以下の記述を追加してインストールを行う。

完成グラフ

作成するグラフの見た目は以下。

完成グラフ

fl_chartで作成した曲線・折れ線グラフは、特に設定をしなくてもタップすることで値を表示してくれる機能が実装されている。

タップすることで値を表示

コード

解説

基本設定

LineChart()を線グラフを描画する位置に配置する。

LineChart()のプロパティにはLineChartData()を指定する。

グラフ最小値・最大値の設定

x軸、y軸それぞれでグラフの最小値・最大値を以下で指定している。

minX: 1,
maxX: 12,
minY: 0,
maxY: 30,

タイトル設定

グラフのラベルにtitlesDataプロパティを指定することで設定する。 titlesDataプロパティに指定している値は以下。

FlTitlesData(
     # グラフ上部ラベル
      topTitles: AxisTitles(
          axisNameWidget: Text(
            "2021 Tokyo Avg Temperature",
            style: _titleStyle,
          ),
          axisNameSize: 48),

    # グラフ右部ラベル
      rightTitles: AxisTitles(
          sideTitles: SideTitles(
        showTitles: false,
      )),

     # グラフ下部ラベル
      bottomTitles: AxisTitles(
        sideTitles: _bottomTitles(),
        axisNameWidget: Container(
          alignment: Alignment.centerRight,
          child: Text(
            "month",
            style: _labelStyle,
          ),
        ),
      ),

     # グラフ左部ラベル
      leftTitles: AxisTitles(
          sideTitles: SideTitles(
            showTitles: true,
            getTitlesWidget: (value, meta) => Text(
              value.toInt().toString(),
              style: const TextStyle(
                fontSize: 12,
              ),
            ),
          ),
          axisNameWidget: Text(
            "temperature",
            style: _labelStyle,
          ),
          axisNameSize: 32),
    );

グラフ右部を非表示にするため、showTitlesプロパティをfalseに指定する。

データ設定

LineChartData()lineBarsDataプロパティにList<LineChartBarData>ウィジェットを渡すことで設定する。

LineChartBarData(
  isCurved: true,
  color: Colors.red[400],
  barWidth: 4,
  dotData: FlDotData(show: true),
  
  # プロットデータ
  spots: const [
    FlSpot(1, 5.4),
    FlSpot(2, 8.5),
    FlSpot(3, 12.8),
    FlSpot(4, 15.1),
    FlSpot(5, 19.6),
    FlSpot(6, 22.7),
    FlSpot(7, 25.9),
    FlSpot(8, 27.4),
    FlSpot(9, 22.3),
    FlSpot(10, 18.2),
    FlSpot(11, 13.7),
    FlSpot(12, 7.9),
  ],
),

各プロット位置はspotsプロパティに渡すFlSpot()ウィジェットで指定する。 第一引数がx、第二引数がyを表す。

プロットを表示する場合は

dotData: FlDotData(show: true),

と設定する。非表示にしたい場合はshowプロパティにfalseを指定する。

【Flutter】ウィジェットを傾ける方法

本エントリではウィジェットを傾けて表示する方法を以下の流れで説明する。



ウィジェットを傾ける方法

傾いていることがわかりやすいように、上を向いた矢印のアイコンIcon(Icons.arrow_upward)を傾ける。

傾いていない状態では次の画像の様な表示になる。

傾いていない状態

また以降で説明する方法を用いて傾けた状態は次の画像の様になる。

90度傾けた状態

Containertransformプロパティで傾ける

ContainertransformプロパティにMatrix4.rotationZ(回転角)を指定することでchildに指定した子ウィジェットを回転させることができる。

回転角に入る値の単位はラジアンになる点に注意。回転角度 * pi / 180で指定するのが楽。

piは円周率のことで、dart:mathライブラリに含まれている。

Transform.rotate()で傾ける

Transform.rotate()childに指定したウィジェットを回転させることができる。 Containerを用いた方法よりも素直に記述できる。

回転させる角度はangleプロパティに回転角度をラジアンで指定する。

RotatedBoxで傾ける

RotatedBoxを用いる方法は、前述の2つの方法と比べて制限がある。 それは「90度単位でしか回転角度を指定できない」という点。

quarterTurnsプロパティにint型の値を指定する。指定した値 × 90度childプロパティに指定した子ウィジェットが回転する。


3つの方法の違い

Containerを用いる方法とTransform.rotate()を用いる方法は大きな差はない。 回転角度を細かく設定できるのでどちらでも良いが、筆者的にはTransform.rotate()の方がシンプルに書ける気がする。 またRotatedBoxは90度単位でしか回転ができないので使用する場面が限られそうと感じた。

【Flutter / Dart】Json形式のデータを読み込む方法

本エントリではJson形式のデータを読み込む方法を以下の流れで説明する。



Json形式データ読み込み方法

準備

取得データ

以下のJsonデータを説明用に読み込む。

ちなみにこちらのデータはJSONPlaceholderというテスト用のWebAPIで取得できる。 自前でAPI用のサーバーなどを作成しなくてもWebAPIを利用できるので開発時に結構便利。

本エントリではWebAPIを叩く方法の説明は割愛する。

使用ライブラリ

サードパーティのライブラリは使用せず、dart:convertというビルトインのライブラリを利用する。

api.dart.dev

読み込み方法

jsonDecode()メソッドを使用してJson形式のString型データをパースしてMap<String, dynamic>型に変換することができる。

上記のコードではparsedDataMap<String, dynamic>型のデータが格納される。

【Flutter】shared_preferencesを用いてデータの保存・読み取りをする

本エントリでは以下の流れでshared_preferencesの使い方を説明する。



shared_preferencesとは

shared_preferencesとはデータをローカルに保存するためのパッケージ。

以下の特徴がある。

  • キーバリュー形式で保存する
  • 特別な準備がなく使用できる
  • Android, iOS, web, macOS, Windows, Linuxで使用できる
  • アプリをインストールするとデータは削除される

またshared_preferencesは以下の様なケースでよく使用される。

  • ユーザーが検索したキーワードのキャッシュ
  • 表示しているタブのインデックス保存

共通点は「サイズは小さいが保存しておきたいデータ」であること。

使用する際の注意事項として、アンインストールするとデータは消えてしまうので、ユーザー登録情報などの重要度の高いデータは保存しない方が良い

shared_preferencesの詳細は公式ページを参照のこと。

pub.dev


shared_preferencesの使い方

準備

インストール

shared_preferencesはサードパーティのパッケージであるので、プロジェクトにあるpubspec.yamlに以下の記述を追記する。

dependencies:
  shared_preferences: ^2.0.15

バージョンは更新されている可能性があるため、以下のインストールページをチェックしておくこと。

pub.dev

インスタンスの作成

データを操作する際にはまずSharedPreferences.getInstance()メソッドを用いてインスタンスを作成する必要がある。 注意点は非同期処理なのでawaitキーワードが必要になる。

final prefs = await SharedPreferences.getInstance();

本エントリではprefsインスタンスを用いて各データ型ごとに保存・読み取りの説明をする。

データ保存・読み取り

キーについて

shared_preferencesはキーバリュー形式でデータを管理している。 そのため開発者は各データごとにユニークなキーを指定する必要がある。

実際のプロジェクトでは、以降の説明コードでキー名称と記載されている部分にユニークなキーが入ると想定している。

int型(整数)のデータ

保存方法

setInt()で値を保存することができる。

prefs.setInt(キー名称, 値);

第二引数に保存したいint型の値を指定する。 データ型に合わない値は保存することができずエラーになる。

読み取り方法

getInt()で保存されている値を取得することができる。

prefs.getInt(キー名称);

キー名称にユニークな文字列を引数に指定する。 もし該当するキー名称が存在しない場合、nullが返される。

double型(実数、小数)のデータ

保存方法

setDouble()で値を保存することができる。

prefs.setDouble(キー名称, 値);

第二引数に保存したいdouble型の値を指定する。 データ型に合わない値は保存することができずエラーになる。

読み取り方法

getDouble()で保存されている値を取得することができる。

prefs.getDouble(キー名称);

キー名称にユニークな文字列を引数に指定する。 もし該当するキー名称が存在しない場合、nullが返される。

String型(文字列)のデータ

保存方法

setString()で値を保存することができる。

prefs.setString(キー名称, 値);

第二引数に保存したいstring型の値を指定する。 データ型に合わない値は保存することができずエラーになる。

読み取り方法

getString()で保存されている値を取得することができる。

prefs.getString(キー名称);

キー名称にユニークな文字列を引数に指定する。 もし該当するキー名称が存在しない場合、nullが返される。

List<String>(文字列のリスト)のデータ

保存方法

setStringList()で値を保存することができる。

prefs.setStringList(キー名称, 値);

第二引数に保存したいList<string>型の値を指定する。 データ型に合わない値は保存することができずエラーになる。

読み取り方法

getStringList()で保存されている値を取得することができる。

prefs.getStringList(キー名称);

キー名称にユニークな文字列を引数に指定する。 もし該当するキー名称が存在しない場合、nullが返される。

bool型(ブール)のデータ

保存方法

setBool()で値を保存することができる。

prefs.setBool(キー名称, 値);

第二引数に保存したいbool型の値を指定する。 データ型に合わない値は保存することができずエラーになる。

読み取り方法

getBool()で保存されている値を取得することができる。

prefs.getBool(キー名称);

キー名称にユニークな文字列を引数に指定する。 もし該当するキー名称が存在しない場合、nullが返される。

データの削除方法

データを削除する場合remove()メソッドを用いる。 非同期処理なのでawaitが必要。削除が成功するとtrueが返される。

await prefs.remove(キー名称);

shared_preferencesを用いたサンプルアプリ

カウンターアプリ(int型データの保存・読み取り例)

動作画像

カウンターアプリ動作

コード

解説

int型データ_counterの管理にshared_preferencesを用いたサンプル。 キー名称は「counter」としている。

initStateにて保存されている状態を読み取るため_initSharedPreferencesData()というメソッドを用意している。

メソッド内でprefs.containsKey(_counterKeyName)を用いて既に保存されている値が存在するかを確認。 存在する場合はgetInt()で値を読み取り、プライベート変数の_counterに値を渡してsetState()を実行することで数値を表示している。

_counterの更新処理には以下の3つのメソッドを用意した。

// _counterを1増やす
 void _incrementCounter() async {
    final prefs = await SharedPreferences.getInstance();

    setState(() {
      _counter++;
    });

    prefs.setInt(_counterKeyName, _counter);
  }

// _counterを1減らす
  void _decrementCounter() async {
    final prefs = await SharedPreferences.getInstance();

    setState(() {
      _counter--;
    });

    prefs.setInt(_counterKeyName, _counter);
  }

// _counterを0にする
  void _resetCounter() async {
    final prefs = await SharedPreferences.getInstance();

    setState(() {
      _counter = 0;
    });

    prefs.setInt(_counterKeyName, _counter);
  }

まずprefsインスタンスを作成し、その後_counterを更新してその値を"counter"キーのバリューに保存している。

【Flutter】Text ウィジェットのスタイル設定方法まとめ

Textウィジェットのスタイル設定をパターン別にまとめる。


Textウィジェットのスタイル設定方法

Textウィジェットのスタイルを設定する場合はstyleプロパティにTextStyleを指定することで行う。


Textウィジェットのスタイルパターン

Textスタイル設定方法をパターン別に説明する。

色付き文字

色付き文字

TextStylecolorプロパティで色を指定する。

背景色付き文字

背景色付き文字

TextStylebackgroundColorプロパティで色を指定する。

任意サイズ文字

任意サイズ文字

TextStylefontSizeプロパティでフォントサイズを指定する。

細字文字

細字文字

TextStylefontWeightプロパティでフォントの太さを指定する。 FontWeight.w100を指定することで最も細い文字になる。wに続く数値が大きいほど太くなる。

太字文字

太字文字

TextStylefontWeightプロパティでフォントの重さを指定する。 FontWeight.boldを指定することで太い文字になる。

超太字文字

超太字文字

TextStylefontWeightプロパティでフォントの太さを指定する。 FontWeight.w900を指定することで最も太い文字になる。

イタリック文字

イタリック文字

TextStylefontStyleプロパティでフォントのスタイルを指定する。 FontStyle.italicを指定することでイタリック体になる。

上線付き文字

上線付き文字

TextStyledecorationプロパティでフォントのスタイルを指定する。 TextDecoration.overlineを指定することでテキストの上に線を引くことができる。

下線付き文字

下線付き文字

TextStyledecorationプロパティでフォントのスタイルを指定する。 TextDecoration.underlineを指定することでテキストの下に線を引くことができる。

色下線付き文字

色下線付き文字

TextStyledecorationプロパティでフォントのスタイルを指定する。 TextDecoration.underlineを指定し、さらにdecoraitonColorに色を指定することで色付きの下線を引くことができる。

太下線付き文字

太下線付き文字

TextStyledecorationプロパティでフォントのスタイルを指定する。 TextDecoration.underlineを指定し、さらにdecorationThicknessにて太さを指定することで太い下線を引くことができる。 decorationThicknessに指定する数値が大きいほど線は太くなる。

打ち消し線付き文字

打ち消し線付き文字

TextStyledecorationプロパティでフォントのスタイルを指定する。 TextDecoration.lineThroughを指定することでテキストに打ち消し線を引くことができる。

波線(はせん)下線付き文字

波線下線付き文字

TextStyledecorationプロパティでフォントのスタイルを指定する。 TextDecoration.underlineを指定し、decorationStyleTextDecorationStyle.dashedを指定することで波線状の下線を引くことができる。

二重下線付き文字

二重下線付き文字

TextStyledecorationプロパティでフォントのスタイルを指定する。 TextDecoration.underlineを指定し、decorationStyleTextDecorationStyle.doubleを指定することで二重下線を引くことができる。

波打った下線付き文字

波打った下線付き文字

TextStyledecorationプロパティでフォントのスタイルを指定する。 TextDecoration.underlineを指定し、decorationStyleTextDecorationStyle.wavyを指定することで波打った下線を引くことができる。

任意の文字間隔

任意の文字間隔

TextStyleletterSpacingプロパティで文字間隔を指定する。 letterSpacingに指定する数値を大きくするほど文字間隔が広くなる。

任意の単語間隔

任意の単語間隔

TextStylewordSpacingプロパティで単語間隔を指定する。 wordSpacingに指定する数値を大きくするほど単語間隔が広くなる。

影付き文字

影付き文字

TextStyleshadowsプロパティで影のスタイルを指定する。 offsetプロパティで影の位置を指定する。値が大きくなるほど文字本体から離れる。 blurRadiusで影のぼやけ具合を指定する。値が大きくなるほど影がぼやける。 colorで影の色を指定する。

【Flutter】「DEBUG」バナーを消す方法、任意の文字のバナーを表示させる方法

Flutterアプリではデフォルトで右上に「DEBUG」と書かれたバナーが表示されている。

「DEBUG」バナー

本エントリでは以下の流れで「DEBUG」バナーを消す方法、また任意の文字のバナーを表示させる方法を説明する。

「DEBUG」バナーを消す方法

一般的にウィジェットツリーのルート付近にあるMaterialAppdebugShowCheckedModeBannerプロパティにfalseを指定すれば良い。

これで「DEBUG」バナーが非表示になる。

「DEBUG」バナー非表示状態

任意の文字のバナーを表示させる方法

Bannerを用いることで任意の文字が表示されたバナーを作成できる。

api.flutter.dev

例として次の画像のバナー作成方法を説明する。

画面左下に「test」バナーを表示

コードは以下。

各プロパティについて説明する。

message

必須プロパティ。表示される文字列を指定する。

location

必須プロパティ。enumBannerLocationの値で指定する。 画面上がtop、下がbottom。また左がstart、右がendという表記ルール。

api.flutter.dev

textStyle

文字列のスタイルを指定する。

バナーの幅が狭いので、あまり文字サイズを大きくすると見切れる為基本的にはデフォルトで良いと思う。

child

バナーを表示したいページのウィジェットを指定する。

バナーはこのchild上に表示されるので、ページ遷移をするとバナーが表示されないパターンもある点に注意。

color

バナーの色を指定する。

【Flutter】ウォークスルー画面を簡単に作成する方法

アプリ開発時、以下の様な機能を実装したいケースがある。

アプリ起動後に表示するウォークスルー画面

この機能はPageViewクラスとsmooth_page_indicatorで簡単に作成できる。

本エントリでは以下の流れでウォークスルー画面を簡単に作成する方法を説明する。


ウォークスルー画面例

まず動作画像とコードを示す。その後適宜説明を加える

ウォークスルー動作画像

ウォークスルー動作画像

コード


コード説明

本エントリのウォークスルーUIはPageViewクラスとsmooth_page_indicatorを用いて実現している。 まずそれぞれのクラスについて説明し、その後PageControllerについて述べる。

PageView

api.flutter.dev

PageViewはスクロールして特定のchildrenに指定したウィジェットを表示することができる。

ListViewなどのレイアウト系ウィジェットと異なる点として、 「スクロールは中途半端な位置では終わらない」がある。 以下の画像はListViewを用いた例。中途半端な位置でスクロールが止まる。

listviewだと中途半端な位置でスクロールが終わる

PageViewを使用する上ではいくつか注意点がある。

[注意点1] サイズを指定した方がよい

SizedBoxなどでラップして縦横のサイズを指定する。 未指定だとRenderBox was not laid outみたいなエラーが表示される。

[注意点2] controllerプロパティを指定する

本エントリで示している例の様に、PageViewの下に現在のページ位置を示すインディケーターがある場合、 controllerを指定する必要がある。 出ないと現在のページ位置が認識されず、実際のページ位置とインディケーターが示すページ位置がずれる。

smooth_indicator

ウォークスルーでは現在何枚目のページを表示しているかを表すインディケーターがよく併せて表示される。 そこでsmooth_page_indicatorを使用する。

pub.dev

サードパーティのパッケージなのでpubspec.yamlに以下を記述する。

smooth_page_indicator: ^1.0.0+2

使用方法は簡単で、controllerプロパティにPageViewにも指定した共通のコントローラーを指定すれば良い。 またページ数の指定はcountにページ数を渡すことで可能。