保存済みの試合データをPDF形式でエクスポートできる機能(仮)を追加しました。”(仮)”とつけていますが、今回のバージョンは試合名やチーム名を表示しているだけのため実際のランニングスコアは含んでいません。次回以降に含める予定です。
機能の詳細
PDFエクスポート機能は、保存済み試合データの一覧から特定の試合を選択し、その試合データをPDFファイルとして保存するものです。PDFファイルは日本語フォント「NotoSansJP-Regular」を使用しており、試合名、会場、日付、チームIDなどの情報を含みます。
実装手順
1. 必要なライブラリのインストール
まず、pubspec.yaml
ファイルに pdf
ライブラリとフォントファイルを追加しました。
dependencies:
flutter:
sdk: flutter
pdf: ^3.6.5
path_provider: ^2.0.11
flutter:
uses-material-design: true
assets:
- assets/fonts/NotoSansJP-Regular.ttf
2. PDFエクスポートの実装
次に、GameDataScreen
クラスにPDFエクスポート機能を追加しました。以下が関連するソースコードです。
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:pdf/widgets.dart' as pw;
import 'package:path_provider/path_provider.dart';
import 'dart:io';
import 'game_entry_provider.dart';
import 'score_input_screen.dart';
class GameDataScreen extends StatefulWidget {
@override
_GameDataScreenState createState() => _GameDataScreenState();
}
class _GameDataScreenState extends State<GameDataScreen> {
final GameEntryProvider _gameProvider = GameEntryProvider();
List<GameEntry> _games = [];
Set<int> _selectedGameIds = Set<int>();
@override
void initState() {
super.initState();
_loadGames();
}
Future<void> _loadGames() async {
List<GameEntry> games = await _gameProvider.getAllGames();
setState(() {
_games = games;
});
}
Future<void> _deleteGame(int gameId) async {
await _gameProvider.deleteGame(gameId);
_loadGames();
}
// 日本語フォントを適用したPDF生成
Future<void> _exportGameToPdf(GameEntry game) async {
try {
final pdf = pw.Document();
// フォントの読み込み
final fontData =
await rootBundle.load("assets/fonts/NotoSansJP-Regular.ttf");
final ttf = pw.Font.ttf(fontData);
// PDFページを追加
pdf.addPage(
pw.Page(
build: (pw.Context context) => pw.Center(
child: pw.Column(
mainAxisAlignment: pw.MainAxisAlignment.center,
children: [
pw.Text(
'試合名: ${game.name}',
style: pw.TextStyle(font: ttf, fontSize: 24),
),
pw.Text('会場: ${game.venue}', style: pw.TextStyle(font: ttf)),
pw.Text('日付: ${game.date}', style: pw.TextStyle(font: ttf)),
pw.Text('チームA ID: ${game.teamAId}',
style: pw.TextStyle(font: ttf)),
pw.Text('チームB ID: ${game.teamBId}',
style: pw.TextStyle(font: ttf)),
],
),
),
),
);
// ドキュメントディレクトリにPDFを保存
final directory = await getApplicationDocumentsDirectory();
final file = File('${directory.path}/game_${game.id}.pdf');
await file.writeAsBytes(await pdf.save());
// 保存成功メッセージ
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('PDFが ${file.path} に保存されました')),
);
} catch (error) {
// エラーメッセージを表示
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('エラーが発生しました: $error')),
);
}
}
// その他のコード...
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('保存済みの試合データ'),
actions: [
IconButton(
icon: Icon(Icons.delete),
onPressed: _selectedGameIds.isNotEmpty
? () => _showDeleteConfirmationDialog(null)
: null,
),
],
),
body: ListView.builder(
itemCount: _games.length,
itemBuilder: (context, index) {
final game = _games[index];
final isSelected = _selectedGameIds.contains(game.id);
return ListTile(
leading: Checkbox(
value: isSelected,
onChanged: (bool? value) {
setState(() {
if (value == true) {
_selectedGameIds.add(game.id!);
} else {
_selectedGameIds.remove(game.id);
}
});
},
),
title: Text(game.name),
subtitle: Text('会場: ${game.venue} - 日付: ${game.date}'),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
icon: Icon(Icons.picture_as_pdf),
onPressed: () => _exportGameToPdf(game),
),
IconButton(
icon: Icon(Icons.edit),
onPressed: () => _showEditGameDialog(game),
),
IconButton(
icon: Icon(Icons.delete),
onPressed: () => _showDeleteConfirmationDialog(game.id),
),
],
),
onTap: () => _showLoadGameDialog(game),
);
},
),
);
}
}
3. 実装後の動作確認
上記のコードを実装した後、保存済み試合データの一覧画面に表示されるPDFアイコンをクリックすると、指定したフォルダに試合データがPDFとして保存されます。
コメント