【Flutter】電卓・計算機アプリの作成 1

2020年5月29日金曜日

Flutter

t f B! P L
トップ

Flutterの勉強として電卓アプリ(計算機)を作ったので、その作り方を順を追って、全3回で説明していきます。



私自身、初心者なのでコード等が少し雑かもしれませんが、出来る限り綺麗なコードを目指しました。


今回はレイアウト作成です。
特に難しいコードは書かないので、コードの説明はせず、Flutter Doc JPへのリンクを貼り付けるだけにします。
(次回以降では説明します。)

# 環境
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel master, 1.19.0-2.0.pre.173, on Mac OS X 10.15.4 19E287, locale ja-JP)
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
[✓] Xcode - develop for iOS and macOS (Xcode 11.5)
[✓] Android Studio (version 3.6)
[✓] VS Code (version 1.45.1)

では始めていきます。

プロジェクトの作成

まず、flutterアプリーケーションを新規作成します。

[PIC 1-1]

名前はcalculator_appとしておきます

[PIC 1-2]

パッケージ名はそのままで

[PIC 1-3]

シュミレーターを起動

[PIC 1-4]

私はiPhone8を起動しました。

[PIC 1-5]

こんな感じで準備完了

[PIC 1-6]

適当に "Hello World"
*特に意味はない、やらなくていいです。

[PIC 1-7]

レイアウトを考える

必要なウィジェット

「電卓」に必要なウィジェットは大きく2つ

(1) 計算式を入力、答えの表示をするところ(赤枠)
(2) キーボード(青枠)
(3) キー(黄枠)

[PIC 2-1]

方針

(1) と (2) をColumn
(2) が (3) をchildrenとして持つようにします。

そして、それぞれのウィジェットを

(1) TextFiled
(2) Keyboard
(3) Button
というクラスに分けて作ります。

この時、
TextFiled は StatefullWidget
Keyboard, Button は StatelessWidget
を継承します。

コードを書く

それではコードを書いていきます。

まずは細かい内容は書かず、Widget build まで書きます。


import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
            body: Column(
              mainAxisAlignment: MainAxisAlignment.start,
              children: [
                TextField(),
                Keyboard(),
              ],
            )
        )
    );
  }
}


//=============================================================================
// 表示
class TextField extends StatefulWidget {
    _TextFiledState createState() => _TextFiledState();
}

class _TextFiledState extends State<TextField> {
    @override
    Widget build(BuildContext context) {
        // any code
    }
}

//==============================================================================
// キーボード
class Keyboard extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
        return Container(
            // any code
        );
    }
}

// キーボタン
class Button extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      // any code
    );
  }
}

表示(TextFiled)のレイアウトを作る


確認用として「1+1」を表示させておきます。
コード

//==============================================================================
// 表示
class TextField extends StatefulWidget {
  _TextFiledState createState() => _TextFiledState();
}

class _TextFiledState extends State<TextField> {
  String _expression = '1+1';

  @override
  Widget build(BuildContext context) {
    return Expanded(
      flex: 1,
      child: Container(
        child: Align(
          alignment: Alignment.centerRight,
          child: Text(
            _expression,
            style: TextStyle(
              fontSize: 64.0,
            ),
          ),
        ),
      )
    );
  }
}

シュミレーターの方はこのように表示されました。

[PIC 3-1]

キーボード(Keyboard, Button)のレイアウトを作る

ここでは Keyboard に GridView を使います。
KeyboarderのContainerに色(#87cefa)をつけ、Buttonの Container には色をつけません。
ButtonにはFlatButtonを使います。
コード

//==============================================================================
// キーボード
class Keyboard extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Expanded(
      flex: 2,
      child: Center(
        child: Container(
          color: const Color(0xff87cefa),
          child: GridView.count(
            crossAxisCount: 4,
            mainAxisSpacing: 3.0,
            crossAxisSpacing: 3.0,
            children: [
              '7', '8', '9', '÷',
              '4', '5', '6', '×',
              '1', '2', '3', '-',
              'C', '0', '=', '+',
            ].map((key) {
              return GridTile(
                child: Button(key),
              );
            }).toList(),
          ),
        )
      )
    );
  }
}

// キーボタン
class Button extends StatelessWidget {
  final _key;
  Button(this._key);

  @override
  Widget build(BuildContext context) {
    return Container(
      child: FlatButton(
          child: Center(
              child: Text(
                  _key,
                  style: TextStyle(fontSize: 46.0),
              ),
          ),
      )
    );
  }
}

シュミレーターの方はこのように表示されました。

[PIC 4-1]

レイアウト完成

ここまでで電卓のレイアウトは完成しました。


ここにmain.dartのコード全体を載せておきます。


import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
            body: Column(
              mainAxisAlignment: MainAxisAlignment.start,
              children: [
                TextField(),
                Keyboard(),
              ],
            )
        )
    );
  }
}

//==============================================================================
// 表示
class TextField extends StatefulWidget {
  _TextFiledState createState() => _TextFiledState();
}

class _TextFiledState extends State<TextField> {
  String _expression = '1+1';

  @override
  Widget build(BuildContext context) {
    return Expanded(
      flex: 1,
      child: Container(
        child: Align(
          alignment: Alignment.centerRight,
          child: Text(
            _expression,
            style: TextStyle(
              fontSize: 64.0,
            ),
          ),
        ),
      )
    );
  }
}

//==============================================================================
// キーボード
class Keyboard extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Expanded(
      flex: 2,
      child: Center(
        child: Container(
          color: const Color(0xff87cefa),
          child: GridView.count(
            crossAxisCount: 4,
            mainAxisSpacing: 3.0,
            crossAxisSpacing: 3.0,
            children: [
              '7', '8', '9', '÷',
              '4', '5', '6', '×',
              '1', '2', '3', '-',
              'C', '0', '=', '+',
            ].map((key) {
              return GridTile(
                child: Button(key),
              );
            }).toList(),
          ),
        )
      )
    );
  }
}

// キーボタン
class Button extends StatelessWidget {
  final _key;
  Button(this._key);

  @override
  Widget build(BuildContext context) {
    return Container(
      child: FlatButton(
          child: Center(
              child: Text(
                  _key,
                  style: TextStyle(fontSize: 46.0),
              ),
          ),
      )
    );
  }
}

現在シュミレータは次のようになっています。

[PIC 4-1]

まとめ

今回で電卓のレイアウトが完成しました。
次回はKeyboardのボタン入力、TextFiledへの表示を実装していきます。

次回(電卓・計算機アプリの作成 2)

参考

Flutterで計算機・電卓アプリを作成する方法を整理しました。
Flutterでレイアウトを組み立てる際、ColumnとRowはほぼ必ず使う。そのColumnとRowでmainAxisAlignmentを指定するわけだが、違いがよく分からないので整理してみた。環境Flutter 1.7...

自己紹介

自分の写真
県立高校理数科2年
Unity2年目
Twitter
Note

人気の投稿

[Vim] coc.nvim + coc-clangdの構文チェックでboostのエラーが発生する

C++の拡張ライブラリ、Boost。 AtCoderでも使用が認められているライブラリです。 様々な便利機能が搭載されています。 競技プログラミングで使えるBoostライブラリ 初級編 から一部抜粋すると、 boost...

QooQ