今回は、Flutterアプリのヘッダーを作るサンプルを作ってみます。

Flutterのディレクトリ構成
lib/
├── main.dart
├── widgets/
│ ├── headers/
│ │ ├── header_home.dart
│ │ ├── header_todo.dart
│ │ └── header_setting.dart
│ └── footers/
│ ├── footer_home.dart
│ ├── footer_todo.dart
│ └── footer_setting.dart
└── pages/
└── user_page.dart
コード
ヘッダー
lib/widgets/headers/header_home.dart
// ヘッダー
import 'package:flutter/material.dart';
class HeaderHome extends StatelessWidget {
const HeaderHome({super.key});
@override
Widget build(BuildContext context) {
return Container(
height: 50,
width: double.infinity,
color: Colors.blue,
alignment: Alignment.center,
child: const Text(
'Header Home',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
);
}
}
lib/widgets/headers/header_todo.dart
import 'package:flutter/material.dart';
class HeaderTodo extends StatelessWidget {
const HeaderTodo({super.key});
@override
Widget build(BuildContext context) {
return Container(
height: 50,
width: double.infinity,
color: Colors.green,
alignment: Alignment.center,
child: const Text(
'Header Todo',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
);
}
}
lib/widgets/headers/header_setting.dart
import 'package:flutter/material.dart';
class HeaderSetting extends StatelessWidget {
const HeaderSetting({super.key});
@override
Widget build(BuildContext context) {
return Container(
height: 50,
width: double.infinity,
color: Colors.orange,
alignment: Alignment.center,
child: const Text(
'Header Setting',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
);
}
}
画面表示(page)
lib/pages/user_page.dart
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import '../widgets/headers/header_home.dart';
import '../widgets/headers/header_todo.dart';
import '../widgets/headers/header_setting.dart';
class UserPage extends StatefulWidget {
const UserPage({super.key});
@override
State<UserPage> createState() => _UserPageState();
}
class _UserPageState extends State<UserPage> {
List<dynamic> todos = [];
Future<void> fetchTodos() async {
try {
final response = await http.get(
Uri.parse("http://localhost:3000/todos"),
);
if (response.statusCode == 200) {
setState(() {
todos = jsonDecode(response.body);
});
}
} catch (e) {
debugPrint("API Error: $e");
}
}
@override
void initState() {
super.initState();
fetchTodos();
}
Widget _buildTodoList() {
if (todos.isEmpty) {
return const Center(
child: CircularProgressIndicator(),
);
}
return ListView.builder(
itemCount: todos.length,
itemBuilder: (context, index) {
final todo = todos[index];
return ListTile(
title: Text(todo["title"]),
subtitle: Text("ID: ${todo["id"]}"),
trailing: Icon(
todo["completed"]
? Icons.check
: Icons.close,
),
);
},
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
children: [
Row(
children: const [
Expanded(child: HeaderHome()),
Expanded(child: HeaderTodo()),
Expanded(child: HeaderSetting()),
],
),
Expanded(
child: _buildTodoList(),
),
],
)
),
);
}
}
main.dart
main.dart
import 'package:flutter/material.dart';
import 'pages/user_page.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: UserPage(),
);
}
}
Express.js×Typescript
クロスオリジンをtrueに設定しています。
app.ts
import express from "express";
import session from "express-session";
import dotenv from "dotenv";
import cors from "cors";
import authRouter from './presentation/routes/authRoutes';
import todoRouter from "./presentation/routes/todoRoutes";
import { authMiddleware } from "./middleware/authMiddleware";
dotenv.config();
const app = express();
app.use(express.json());
app.use(cors({
origin:true,//origin:"http://localhost:3001",
credentials:true
}));
app.use(
session({
secret:
process.env.SESSION_SECRET!,
resave:false,
saveUninitialized:false,
cookie:{
secure:false,
httpOnly:true
}
})
);
app.use("/auth", authRouter);
app.use(
"/todos",
//authMiddleware,//一時的にコメントアウト:authMiddleware
todoRouter
);
app.listen(
process.env.PORT,
() => {
console.log("server start");
}
);
todoRoute.ts
import { Router } from "express";
import { todoController } from "../../container/todoContainer";
const todoRouter = Router();
todoRouter.get("/", todoController.getAll);
todoRouter.post("/", todoController.create);
todoRouter.put("/:id", todoController.update);
todoRouter.delete("/:id", todoController.delete);
export default todoRouter;
TodoController.ts
import { Request, Response } from "express";
import { TodoService } from '../../application/services/TodoService';
export class TodoController {
constructor(
private TodoService:TodoService
){}
getAll = async (
req: Request,
res: Response
) => {
req.session.userId = 1;//一時的に設定
if(!req.session.userId){
return res.json(null);
}
const todos = await this.TodoService.getTodos(
req.session.userId
);
console.log('結果:',todos);
res.json(todos);
}
create = async (
req: Request,
res: Response
) => {
if(!req.session.userId){
return res.json(null);
}
const todo = await this.TodoService.createTodo(
req.body.title,
req.session.userId
);
res.json(todo);
}
update = async (
req:Request,
res:Response
) => {
await this.TodoService.updateTodo(
Number(req.params.id),
req.body.title,
req.body.completed
);
res.json({message:"updated"});
};
delete = async (
req:Request,
res:Response
) => {
await this.TodoService.deleteTodo(
Number(req.params.id)
);
res.json({message:"deleted"});
};
}