Flutter + Dart/다이어리 프로젝트

flutter 키, 값을 가지는 리스트 만들기

GREEN나무 2025. 5. 14. 18:27
728x90
List<Map<String, dynamic>> diary_item = [];

 

/// 2. 일기 작성 화면 (입력받고 저장 시 콘솔에 출력)
...
class _WriteDiaryScreenState extends State<WriteDiaryScreen> {
  // 제목과 내용을 입력받기 위한 TextEditingController
  final TextEditingController titleController = TextEditingController();
  final TextEditingController contentController = TextEditingController();

  // 저장 버튼 클릭 시 호출되는 함수
  void _saveDiary() {
    final title = titleController.text;
    final content = contentController.text;

    // 아이디 부여: 리스트가 비어있으면 0, 아니면 마지막 id + 1
    final int id = diary_item.isEmpty ? 0 : diary_item.last['id'] + 1;

    // 리스트에 추가
    diary_item.add({'id': id, 'title': title, 'content': content});

    print('제목: $title');
    print('내용: $content');

    // 작성 화면 종료
    Navigator.pop(context);
  }

  @override
  Widget build(BuildContext context) {
 ...
            // 버튼 클릭
            ElevatedButton(
              onPressed: _saveDiary, // 저장 함수 호출
              child: const Text('저장'),
            ),
          ],
        ),
      ),
    );
  }
}

 

일기화면 전체 코드

lib\screens\diary_screen.dart

더보기
import 'package:flutter/material.dart';

// 전역에 선언된 일기 리스트 (임시 저장소)
List<Map<String, dynamic>> diary_item = [
  {'id': 1, 'title': '오늘일기1', 'content': '이모지랑 줄바꿈, 그림 중간에 넣는 방법을 찾아야하는데데'},
  {'id': 2, 'title': '오늘일기2', 'content': '내용내용내용 일기 내용용'},
  {'id': 3, 'title': '오늘일기3', 'content': '내용내용내용 일기 내용용'}
];

/// 1. 일기 목록 화면
class DiaryListScreen extends StatelessWidget {
  const DiaryListScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // 상단 앱바 구성
      appBar: AppBar(
        leading: Padding(
          padding: const EdgeInsets.only(left: 10.0),
          child: IconButton(
            icon: const Icon(Icons.home),
            // 홈 아이콘 클릭 시 홈 화면으로 이동
            onPressed: () => Navigator.pushNamed(context, '/home'),
          ),
        ),
        title: const Text('ઇଓ FLY 다이어리'),
        centerTitle: true,
        elevation: 0,
      ),
      // 본문 영역 구성
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            // 달력 타이틀
            const Text(
              '달력',
              style: TextStyle(fontSize: 24),
            ),
            const SizedBox(height: 8),
            // 일기 등록 날짜 표시 영역 (예시용 컨테이너)
            Container(
              padding: const EdgeInsets.all(16),
              decoration: BoxDecoration(
                border: Border.all(
                  color: Colors.blue,
                  width: 2,
                ),
              ),
              child: const Text(
                '일기 등록한 날짜 표시',
                style: TextStyle(fontSize: 20),
              ),
            ),
            const SizedBox(height: 16),
            // 일기 미리보기 타이틀
            const Text(
              '일기 미리보기',
              style: TextStyle(fontSize: 24),
            ),
            const SizedBox(height: 8),
            // 일기 리스트 출력 영역
            // 일기 리스트 출력 영역
            Expanded(
              child: Container(
                decoration: BoxDecoration(
                  border: Border.all(
                    color: Colors.blue,
                    width: 2,
                  ),
                ),
                child: ListView.builder(
                  itemCount: diary_item.length,
                  itemBuilder: (context, index) {
                    final diary = diary_item[index];
                    return ListTile(
                      title: Text(diary['title']), // 저장된 제목 사용
                      subtitle: Text(
                        (() {
                          final lines = diary['content']
                              .toString()
                              .split('\n'); // 줄바꿈 단위로 자른 배열
                          final firstLine = lines.first; // 첫째줄
                          return firstLine.length > 30
                              ? '${firstLine.substring(0, 30)}...'
                              : firstLine;
                        })(),
                      ),
                      // 내용 일부만 미리보기  첫줄 or 앞에 30자만
                      onTap: () {
                        Navigator.push(
                          context,
                          MaterialPageRoute(
                            builder: (context) =>
                                DiaryDetailScreen(diary: diary), // diary 자체 전달
                          ),
                        );
                      },
                    );
                  },
                ),
              ),
            ),
            const SizedBox(height: 20),
          ],
        ),
      ),
      // 일기 작성 화면으로 이동하는 플로팅 버튼
      floatingActionButton: FloatingActionButton(
        onPressed: () async {
          final result = await Navigator.push(
            context,
            MaterialPageRoute(
              builder: (context) => const WriteDiaryScreen(),
            ),
          );

          if (result == true) {
            // 새 일기가 추가되었음을 감지하고 화면 갱신
            (context as Element).markNeedsBuild(); // 또는 상태관리 적용
          }
        },
        child: const Icon(Icons.add),
      ),
    );
  }
}

/// 2. 일기 작성 화면 (입력받고 저장 시 콘솔에 출력)
class WriteDiaryScreen extends StatefulWidget {
  const WriteDiaryScreen({Key? key}) : super(key: key);

  @override
  State<WriteDiaryScreen> createState() => _WriteDiaryScreenState();
}

class _WriteDiaryScreenState extends State<WriteDiaryScreen> {
  // 제목과 내용을 입력받기 위한 TextEditingController
  final TextEditingController titleController = TextEditingController();
  final TextEditingController contentController = TextEditingController();

  // 저장 버튼 클릭 시 호출되는 함수
  void _saveDiary() {
    final title = titleController.text;
    final content = contentController.text;

    // 아이디 부여: 리스트가 비어있으면 0, 아니면 마지막 id + 1
    final int id = diary_item.isEmpty ? 0 : diary_item.last['id'] + 1;

    // 리스트에 추가
    diary_item.add({'id': id, 'title': title, 'content': content});

    print('제목: $title');
    print('내용: $content');

    // 작성 화면 종료
    Navigator.pop(context, true);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // 상단 앱바
      appBar: AppBar(
        title: const Text('일기 작성'),
        centerTitle: true,
      ),
      // 본문 입력 폼
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            // 제목 입력 필드
            TextField(
              controller: titleController, // 제목 컨트롤러 연결
              decoration: const InputDecoration(
                labelText: '제목',
                border: OutlineInputBorder(),
              ),
            ),
            const SizedBox(height: 16),
            // 내용 입력 필드
            TextField(
              controller: contentController, // 내용 컨트롤러 연결
              decoration: const InputDecoration(
                labelText: '내용',
                border: OutlineInputBorder(),
              ),
              maxLines: 10, // 여러 줄 입력 가능
            ),
            const SizedBox(height: 16),
            ElevatedButton(
              onPressed: _saveDiary,
              child: const Text('저장'),
            ),
          ],
        ),
      ),
    );
  }
}

/// 3. 일기 상세 보기 화면 (선택한 일기의 제목과 내용 표시)

class DiaryDetailScreen extends StatelessWidget {
  final Map<String, dynamic> diary;

  const DiaryDetailScreen({Key? key, required this.diary}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('일기 상세 보기'),
        centerTitle: true,
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            Text(
              diary['title'], // 실제 제목 표시
              style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
            ),
            const Divider(height: 32, thickness: 1),
            Text(
              diary['content'], // 실제 내용 표시
              style: const TextStyle(fontSize: 16),
            ),
          ],
        ),
      ),
    );
  }
}