FlutterでMTGライフカンター

7 min読了の目安(約6800字TECH技術記事

Flutterにて、シンプルにMTGライフカンター(20カウントダウンアプリ)を作ってみました。

MTGライフカンターDartPad実行」でブラウザ実行できます。

20カウントダウンアプリ

import 'package:flutter/material.dart';

// #########################################################################
// ##### Start:constants.dart#####
const kDefaultLife = 20;

const kLifeTextStyle = TextStyle(
  fontSize: 70,
);

const kIncrement1Color = Colors.blue;
const kIncrement2Color = Colors.indigo;
const kDecrement1Color = Colors.red;
const kDecrement2Color = Colors.orange;
// ##### Finish:constants.dart#####
// #########################################################################

// #########################################################################
// ##### Start:main.dart#####
void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
        highlightColor: Colors.pink,
      ),
      home: LifeCounterScreen(),
    );
  }
}
// ##### Finish:main.dart#####
// #########################################################################

// #########################################################################
// ##### Start:life_counter_screen.dart#####
PlayerData playerData = PlayerData();

class LifeCounterScreen extends StatelessWidget {
  Widget _buildCategoryWidgets(List<Widget> counters) {
    return GridView.builder(
      gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
        crossAxisCount: 2,
      ),
      itemBuilder: (BuildContext context, int index) => counters[index],
      itemCount: counters.length,
    );
  }

  
  Widget build(BuildContext context) {
    // 画面を横に固定する場合
//     SystemChrome.setPreferredOrientations([
//       DeviceOrientation.landscapeRight,
//       DeviceOrientation.landscapeLeft,
//     ]);

    final counters = <LifeCounter>[];

    for (var i = 0; i < playerData.playerCount; i++) {
      counters.add(LifeCounter(
        player: playerData.players[i],
      ));
    }

    final gridView = Container(
      padding: EdgeInsets.symmetric(vertical: 8.0, horizontal: 8.0),
      child: _buildCategoryWidgets(counters),
    );

    return Scaffold(
      body: SafeArea(child: gridView),
    );
  }
}
// ##### Finish:life_counter_screen.dart#####
// #########################################################################

// #########################################################################
// ##### Start:player_data.dart#####
class PlayerData {
  List<Player> players = [
    Player(name: 'Player1'),
    Player(name: 'Player2'),
  ];

  int get playerCount {
    return players.length;
  }
}
// ##### Finish:player_data.dart#####
// #########################################################################

// #########################################################################
// ##### Start:player.dart#####
class Player {
  final String name;
  int life;

  Player({this.name, this.life = kDefaultLife});

  void changeLifeCounter(int number) {
    life += number;
  }

  void reset() {
    life = kDefaultLife;
  }
}
// ##### Finish:player.dart#####
// #########################################################################

// #########################################################################
// ##### Start:life_counter.dart#####
class LifeCounter extends StatefulWidget {
  final Player player;

  LifeCounter({this.player});

  
  _LifeCounterState createState() => _LifeCounterState();
}

class _LifeCounterState extends State<LifeCounter> {
  
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        FloatingActionButton(
          onPressed: () {
            setState(() {
              widget.player.reset();
            });
          },
          tooltip: 'Reset',
          child: Icon(Icons.update),
        ),
        Expanded(
          child: Text(
            widget.player.name,
          ),
        ),
        FlatButton(
          shape: CircleBorder(),
          child: Text(
            '${widget.player.life}',
            style: kLifeTextStyle,
          ),
          onPressed: () {
            setState(() {
              widget.player.changeLifeCounter(-1);
            });
          },
          splashColor: kDecrement1Color,
        ),
        Expanded(
          child: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                IconButton(
                  icon: Icon(Icons.exposure_neg_1),
                  tooltip: 'Decrease count by 1',
                  onPressed: () {
                    setState(() {
                      widget.player.changeLifeCounter(-1);
                    });
                  },
                  splashColor: kDecrement1Color,
                ),
                const SizedBox(width: 20.0),
                IconButton(
                  icon: Icon(Icons.exposure_plus_1),
                  tooltip: 'Increase count by 1',
                  onPressed: () {
                    setState(() {
                      widget.player.changeLifeCounter(1);
                    });
                  },
                  splashColor: kIncrement1Color,
                ),
              ]),
        ),
        const SizedBox(height: 20.0),
        Expanded(
          child: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                IconButton(
                  icon: Icon(Icons.exposure_neg_2),
                  tooltip: 'Decrease count by 2',
                  onPressed: () {
                    setState(() {
                      widget.player.changeLifeCounter(-2);
                    });
                  },
                  splashColor: kDecrement2Color,
                ),
                const SizedBox(width: 20.0),
                IconButton(
                  icon: Icon(Icons.exposure_plus_2),
                  tooltip: 'Increase count by 2',
                  onPressed: () {
                    setState(() {
                      widget.player.changeLifeCounter(2);
                    });
                  },
                  splashColor: kIncrement2Color,
                ),
              ]),
        ),
      ],
    );
  }
}
// ##### Finish:life_counter.dart#####
// #########################################################################