snovaのブログ

主にプログラミングやデジタルコンテンツについて書きます。最近はPython, Flutter, VRに興味があります。

Flutterで時計、ストップウォッチを表示するアプリを作成

イントロダクション

Flutterの勉強です。 時計、ストップウォッチのアプリを作成しました。

目次

初期化

前回の記事を参考に新規のアプリを作成します。

snova301.hatenablog.com

インポートするモジュールは以下の通りです。

import 'dart:async';
import "package:intl/intl.dart";
import 'package:flutter/material.dart';

pubspec.yamlも書き換えておきます。

dependencies:
  flutter:
    sdk: flutter
  intl: 0.15.8

タブウィジェットの作成

公式ドキュメントを参考にタブを作ります。 FlutterではDefaultTabControllerクラスを使います。

今回は時計、ストップウォッチのタブを作成します。 タブ名にはそれぞれの名前とし、タブの中身を各クラスに任せるようにします。

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Timer App',
      theme: ThemeData(
        primarySwatch: Colors.blueGrey
      ),

      home: DefaultTabController(
        length: 2,
        child: Scaffold(
          appBar: AppBar(
            bottom: TabBar(
              tabs: [
                Tab(text: '時計'),
                Tab(text: 'ストップウォッチ'),
              ],
            ),
            title: Text('時間アプリ'),
          ),
          body: TabBarView(
            children: [
              ClockPage(),
              StopwatchPage(),
            ],
          ),
        ),
      ),
    );
  }
}

また、各ウィジェットStatefulWidgetを定義しておきます。

class ClockPage extends StatefulWidget {
  @override
  _ClockPageState createState() => _ClockPageState();
}

class StopwatchPage extends StatefulWidget {
  @override
  _StopwatchPageState createState() => _StopwatchPageState();
}

時計の作成

時計タブでは時間を表示していきます。 TimerAPIを使って繰り返し時間を設定、DateTimeで時間を出力します。

class _ClockPageState extends State<ClockPage> {
  Timer _timer;
  final _formatter = DateFormat('y/MM/dd HH:mm:ss');

  @override
  void initState() {
    super.initState();
    _timer = Timer.periodic(
      Duration(seconds: 1),
      (_t) => setState(() {}),
    );
  }

  @override
  void dispose() {
    _timer.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              '現在時間',
              style: TextStyle(fontSize: 25),
              ),
            Text(
              '${_formatter.format(DateTime.now())}',
              style: TextStyle(fontSize: 30),
            )
          ],
        )
      )
    );
  }
}

ストップウォッチの作成

時計と同様にTimerを使っていきます。 時間の表示では間隔をミリ秒オーダーにし、日付を削除します。 時間差の計算では、Unix時間に変換したあとDateTime型に戻す作業をしています。

スタートボタン、ストップボタンの挙動はvoid型のメソッド内で制御しています。

また、ボタン自体はIconButtonを使い、マテリアルデザインのアイコンにしました。

class _StopwatchPageState extends State<StopwatchPage> {
  Timer _timer;
  final _formatter = DateFormat('HH:mm:ss.S');

  var StartTime = 0;
  var NowTime = 0;
  var RunState = 0; // 0:stop, 1:run

  @override
  void initState() {
    super.initState();
    _timer = Timer.periodic(
      Duration(milliseconds: 123), // 数値小->高速に時間刻む
      (_t) => setState(() {}),
    );
  }

  @override
  void dispose() {
    _timer.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    if (RunState==1){
      NowTime = DateTime.now().millisecondsSinceEpoch.toInt();
    }

    void _StartButton(){
      if (RunState == 0){
        StartTime = DateTime.now().millisecondsSinceEpoch.toInt();
        NowTime = DateTime.now().millisecondsSinceEpoch.toInt();
        RunState = 1;
      }
    }

    void _StopButton(){
      if (RunState == 1){
        RunState = 0;
      }
      else{
        StartTime = 0;
        NowTime = 0;
      }
    }

    var DiffTime = DateTime.fromMillisecondsSinceEpoch(NowTime - StartTime).toUtc();

    var ButtonWidget = Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        IconButton(
          icon: Icon(Icons.play_circle_filled),
          iconSize: 50,
          onPressed: _StartButton,
          color: Colors.green,
        ),
        
        IconButton(
          icon: Icon(Icons.stop),
          iconSize: 50,
          onPressed: _StopButton,
          color: Colors.red,
        ),
      ],
    );



    var DiffWidget = Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Column(
        mainAxisAlignment: MainAxisAlignment.center,
          children:[
            Text(
              '時間差',
              style: TextStyle(fontSize: 25),
            ),
            Text(
              '${_formatter.format(DiffTime)}',
              style: TextStyle(fontSize: 30),
            ),
          ],
        ),
      ],
    );


    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        DiffWidget,
        ButtonWidget,
      ],
    );
  }
}

完成図

完成イメージです。 Android端末でスクショ取っていますが、iOSでもちゃんと動作しました。

時計

ストップウォッチ

コード全体

ソースコードはGistにあげています。

flutter_stopwatch

また、githubにファイルを上げておきます。

github.com

まとめ

Flutterで時計、ストップウォッチを作りました。 次回は、別のアプリを開発します。

参考サイト

Google Play and the Google Play logo are trademarks of Google LLC.