【Flutter】CheckBoxListTileとTextStyleを活用してToDoリストのフロントエンドを作ってみた

# はじめに
先日からFlutterを使い始めた初心者です。
制作したいToDoアプリの完成形のイメージは自分の中であるので、それらを実現するために色々調べているので、それらをまとめていきます！
何かおかしな点などがありましたらコメントをお願いします。

# この記事で分かること
完成形はこんな感じ

![スクリーンショット 2021-08-13 222231.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1630025/f14da810-f395-cc12-cb98-6ee9d40a81e0.png)

この記事では主に

- CheckBoxListTileについて
- 取り消し線の実装方法

をまとめています

# ToDoリストのフロントエンドを作る
## そもそものお話
今回のゴールは

- 各リストの左側にチェックボックスを入れる 
- チェックしたら取り消し線が入る

ことです。
私のイメージではListTileを使ってleading: Iconみたいな感じでCheckBoxを入れるのかなーと思ってたのですが、調べていくとどうやらCheckBoxListTileを使うらしい。

私は習うより慣れよ派なのでとりあえずコードを写していろいろいじっていきましょう。

## CheckBoxListTileを実装する
以下のコードをmain.dartにコピペしてください。
（このコードは[こちら](https://medium.com/flutterdevs/checkbox-listtile-in-flutter-50e877cee48c)のサイトを参考にしました）

``` main.dart
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  List<CheckBoxListTileModel> checkBoxListTileModel =
  CheckBoxListTileModel.getUsers();

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        centerTitle: true,
        title: new Text(
          'CheckBox ListTile Demo',
          style: TextStyle(color: Colors.black),
        ),
      ),
      body: new ListView.builder(
          itemCount: checkBoxListTileModel.length,
          itemBuilder: (BuildContext context, int index) {
            return new Card(
              child: new Container(
                padding: new EdgeInsets.all(10.0),
                child: Column(
                  children: <Widget>[
                    new CheckboxListTile(
                        activeColor: Colors.pink[300],
                        dense: true,
                        //font change
                        title: new Text(
                          checkBoxListTileModel[index].title,
                          style: TextStyle(
                              fontSize: 20,
                              fontWeight: FontWeight.w600,
                              letterSpacing: 0.5),
                        ),
                        value: checkBoxListTileModel[index].isCheck,
                        secondary: Container(
                          height: 50,
                          width: 50,
                        ),
                        onChanged: (bool? val) {
                          itemChange(val!, index);
                        })
                  ],
                ),
              ),
            );
          }),
    );
  }

  void itemChange(bool val, int index) {
    setState(() {
      checkBoxListTileModel[index].isCheck = val;
    });
  }
}
class CheckBoxListTileModel {
  int userId;
  String title;
  bool isCheck;

  CheckBoxListTileModel({required this.userId, required this.title, required this.isCheck});

  static List<CheckBoxListTileModel> getUsers() {
    return <CheckBoxListTileModel>[
      CheckBoxListTileModel(
          userId: 1,
          title: "Android",
          isCheck: true),
      CheckBoxListTileModel(
          userId: 2,
          title: "Flutter",
          isCheck: false),
      CheckBoxListTileModel(
          userId: 3,
          title: "IOS",
          isCheck: false),
      CheckBoxListTileModel(
          userId: 4,
          title: "PHP",
          isCheck: false),
      CheckBoxListTileModel(
          userId: 5,
          title: "Node",
          isCheck: false),
    ];
  }
}
```

実行してみると…
![スクリーンショット 2021-08-13 215601.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1630025/8b6fb4c8-0093-40ef-1edf-84abcaed7cf0.png)
こんな感じ。とりあえず各リストにチェックボックスを入れることが出来ました！

## 改善する
### チェックボックスを左側にする
先ほどのコードではチェックボックスが右側になってしまっているので、これを左側に移しましょう。
以下のコードを**CheckboxListTile**のカッコの中に入れるだけでOKです！
（これは[Flutter Doc JP](https://flutter.ctrnost.com/basic/interactive/form/checkbox/)のサイトを参考にしました）

```
controlAffinity: ListTileControlAffinity.leading,
```

実行するとこんな感じ
![スクリーンショット 2021-08-13 220914.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1630025/50a6b815-8fd9-7810-cb4d-b47debb11cbf.png)

### 取り消し線を入れる
だいぶイメージ通りになってきました！次はチェックを入れたら取り消し線が入るようにしましょう。
取り消し線を入れるのはあくまで**チェックした時だけ**です。なので使うコードは以下になります。
（後ほどコードを全文載せます）

```dart
decoration: checkBoxListTileModel[index].isCheck ? TextDecoration.lineThrough : TextDecoration.none,
```
これをTextStyleの中に入れて実行すると

![スクリーンショット 2021-08-13 222231.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1630025/f14da810-f395-cc12-cb98-6ee9d40a81e0.png)

出来たーーー！！これで完成です。

### 完成形のコード
``` main.dart
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  List<CheckBoxListTileModel> checkBoxListTileModel =
  CheckBoxListTileModel.getUsers();

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        centerTitle: true,
        title: new Text(
          'CheckBox ListTile Demo',
          style: TextStyle(color: Colors.black),
        ),
      ),
      body: new ListView.builder(
          itemCount: checkBoxListTileModel.length,
          itemBuilder: (BuildContext context, int index) {
            return new Card(
              child: new Container(
                padding: new EdgeInsets.all(10.0),
                child: Column(
                  children: <Widget>[
                    new CheckboxListTile(
                        controlAffinity: ListTileControlAffinity.leading,
                        activeColor: Colors.pink[300],
                        dense: true,
                        //font change
                        title: new Text(
                          checkBoxListTileModel[index].title,
                          style: TextStyle(
                              fontSize: 20,
                              fontWeight: FontWeight.w600,
                              letterSpacing: 0.5,
                              decoration: checkBoxListTileModel[index].isCheck ? TextDecoration.lineThrough : TextDecoration.none,
                          ),
                        ),
                        value: checkBoxListTileModel[index].isCheck,
                        secondary: Container(
                          height: 50,
                          width: 50,
                        ),
                        onChanged: (bool? val) {
                          itemChange(val!, index);
                        })
                  ],
                ),
              ),
            );
          }),
    );
  }

  void itemChange(bool val, int index) {
    setState(() {
      checkBoxListTileModel[index].isCheck = val;
    });
  }
}
class CheckBoxListTileModel {
  int userId;
  String title;
  bool isCheck;

  CheckBoxListTileModel({required this.userId, required this.title, required this.isCheck});

  static List<CheckBoxListTileModel> getUsers() {
    return <CheckBoxListTileModel>[
      CheckBoxListTileModel(
          userId: 1,
          title: "Android",
          isCheck: true),
      CheckBoxListTileModel(
          userId: 2,
          title: "Flutter",
          isCheck: false),
      CheckBoxListTileModel(
          userId: 3,
          title: "IOS",
          isCheck: false),
      CheckBoxListTileModel(
          userId: 4,
          title: "PHP",
          isCheck: false),
      CheckBoxListTileModel(
          userId: 5,
          title: "Node",
          isCheck: false),
    ];
  }
}
```

## 今回特に参考にさせていただいたサイト

- https://medium.com/flutterdevs/checkbox-listtile-in-flutter-50e877cee48c (メインコード)
- https://flutter.ctrnost.com/basic/interactive/form/checkbox/ (チェックボックスについて)
- https://uki-home.xyz/2020/04/01/1742/ (TextStyleについて)

# おわりに
思っていたものが実装出来て良かったです！

ここまで読んでいただきありがとうございました。何かありましたらコメントをお願いします。