Flutterバスケアプリ | チーム登録・メンバー登録一覧に一括削除機能を追加

バスケットボールスコア入力アプリ(ランニングスコア)にチーム登録およびメンバー登録一覧に一括削除機能を追加しました。

これまでのアプリでは、チームやメンバーを1件ずつ削除する必要があり、複数のデータを管理する際には手間がかかっていました。そこで、複数のチームやメンバーをまとめて削除できるように、チェックボックスを使った一括削除機能を実装しました。

機能の概要

この機能では、チーム登録画面メンバー登録画面において、一覧表示されたデータの左側にチェックボックスを追加しました。ユーザーが削除したい項目にチェックを入れ、画面上部のゴミ箱アイコンをクリックすることで、選択された項目を一括で削除することができます。

削除実行時には確認ダイアログが表示され、ユーザーに本当に削除してよいかの確認が求められます。「はい」を選択すると、選択したすべてのデータが一度に削除されます。


実装の詳細

チーム登録画面のコード例

まず、チーム登録画面の一覧に対してチェックボックスを追加し、一括削除機能を実装した部分を紹介します。

import 'package:flutter/material.dart';
import 'team_provider.dart';
import 'member_registration_screen.dart';

class TeamRegistrationScreen extends StatefulWidget {
  @override
  _TeamRegistrationScreenState createState() => _TeamRegistrationScreenState();
}

class _TeamRegistrationScreenState extends State<TeamRegistrationScreen> {
  final TeamProvider _teamProvider = TeamProvider();
  List<Team> _teams = [];
  Set<int> _selectedTeamIds = Set<int>(); // 一括削除のための選択セット

  @override
  void initState() {
    super.initState();
    _loadTeams();
  }

  Future<void> _loadTeams() async {
    List<Team> teams = await _teamProvider.getAllTeams();
    setState(() {
      _teams = teams;
    });
  }

  Future<void> _deleteSelectedTeams() async {
    for (int teamId in _selectedTeamIds) {
      await _teamProvider.deleteTeam(teamId);
    }
    _loadTeams();
    _selectedTeamIds.clear(); // 削除後、選択をクリア
  }

  // 一括削除確認ダイアログ
  void _showDeleteConfirmationDialog() {
    showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: Text("チーム削除"),
          content: Text("選択されたチームをすべて削除しますか?"),
          actions: [
            TextButton(
              onPressed: () async {
                await _deleteSelectedTeams(); // 一括削除を実行
                Navigator.of(context).pop();
              },
              child: Text("はい"),
            ),
            TextButton(
              onPressed: () {
                Navigator.of(context).pop();
              },
              child: Text("いいえ"),
            ),
          ],
        );
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('チーム登録'),
        actions: [
          IconButton(
            icon: Icon(Icons.delete),
            onPressed: _selectedTeamIds.isNotEmpty
                ? _showDeleteConfirmationDialog
                : null, // チェックされていない場合は無効化
          ),
          IconButton(
            icon: Icon(Icons.add),
            onPressed: () => _addOrEditTeam(),
          ),
        ],
      ),
      body: _teams.isEmpty
          ? Center(child: Text('保存されたチームはありません'))
          : ListView.builder(
              itemCount: _teams.length,
              itemBuilder: (context, index) {
                final team = _teams[index];
                final isSelected = _selectedTeamIds.contains(team.id);

                return ListTile(
                  leading: Checkbox(
                    value: isSelected,
                    onChanged: (bool? value) {
                      setState(() {
                        if (value == true) {
                          _selectedTeamIds.add(team.id!);
                        } else {
                          _selectedTeamIds.remove(team.id);
                        }
                      });
                    },
                  ),
                  title: Text(team.name),
                  subtitle: Text('${team.location} - 順位: ${team.displayOrder}'),
                  onTap: () {
                    Navigator.push(
                      context,
                      MaterialPageRoute(
                        builder: (context) =>
                            MemberRegistrationScreen(team: team),
                      ),
                    );
                  },
                  trailing: Row(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      IconButton(
                        icon: Icon(Icons.edit),
                        onPressed: () => _addOrEditTeam(team: team),
                      ),
                    ],
                  ),
                );
              },
            ),
    );
  }
}

メンバー登録画面でも同様の実装

メンバー登録画面でも同様の実装を行いました。チェックボックスを追加し、選択されたメンバーを一括で削除できるようにしています。

import 'package:flutter/material.dart';
import 'member_provider.dart';
import 'team_provider.dart';

class MemberRegistrationScreen extends StatefulWidget {
  final Team team;

  MemberRegistrationScreen({required this.team});

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

class _MemberRegistrationScreenState extends State<MemberRegistrationScreen> {
  final MemberProvider _memberProvider = MemberProvider();
  List<Member> _members = [];
  Set<int> _selectedMemberIds = Set<int>(); // 一括削除のための選択セット

  @override
  void initState() {
    super.initState();
    _loadMembers();
  }

  Future<void> _loadMembers() async {
    List<Member> members =
        await _memberProvider.getMembersByTeamId(widget.team.id!);
    setState(() {
      _members = members;
    });
  }

  Future<void> _deleteSelectedMembers() async {
    for (int memberId in _selectedMemberIds) {
      await _memberProvider.deleteMember(memberId);
    }
    _loadMembers();
    _selectedMemberIds.clear();
  }

  // 一括削除確認ダイアログ
  void _showDeleteConfirmationDialog() {
    showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: Text("メンバー削除"),
          content: Text("選択されたメンバーをすべて削除しますか?"),
          actions: [
            TextButton(
              onPressed: () async {
                await _deleteSelectedMembers(); // 一括削除を実行
                Navigator.of(context).pop();
              },
              child: Text("はい"),
            ),
            TextButton(
              onPressed: () {
                Navigator.of(context).pop();
              },
              child: Text("いいえ"),
            ),
          ],
        );
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('${widget.team.name} メンバー登録'),
        actions: [
          IconButton(
            icon: Icon(Icons.delete),
            onPressed: _selectedMemberIds.isNotEmpty
                ? _showDeleteConfirmationDialog
                : null,
          ),
          IconButton(
            icon: Icon(Icons.add),
            onPressed: () => _addOrEditMember(),
          ),
        ],
      ),
      body: _members.isEmpty
          ? Center(child: Text('保存されたメンバーはありません'))
          : ListView.builder(
              itemCount: _members.length,
              itemBuilder: (context, index) {
                final member = _members[index];
                final isSelected = _selectedMemberIds.contains(member.id);

                return ListTile(
                  leading: Checkbox(
                    value: isSelected,
                    onChanged: (bool? value) {
                      setState(() {
                        if (value == true) {
                          _selectedMemberIds.add(member.id!);
                        } else {
                          _selectedMemberIds.remove(member.id);
                        }
                      });
                    },
                  ),
                  title: Text(member.name),
                  subtitle: Text('番号: ${member.number}, ポジション: ${member.position}'),
                  trailing: Row(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      IconButton(
                        icon: Icon(Icons.edit),
                        onPressed: () => _addOrEditMember(member: member),
                      ),
                    ],
                  ),
                );
              },
            ),
    );
  }
}

スクリーンショット

チーム登録画面

メンバー登録画面

関連記事

コメント

タイトルとURLをコピーしました