Flutter APP 만들기 : 일정관리 Step 5th

이 전 글(Step 4th)에서 달력에 날짜 선택시 선택된 날짜에 대한 표시와 콜백함수의 틀을 작성했습니다.

이제 드디어 선택된 날짜의 일정을 보여주는 카드 디자인의 위젯을 작성해 보려고 합니다.


일정을 보여주는 카드 위젯

카드는 좌측에 시간을 보여주는 영역과 우측에 내용을 보여줄 영역으로 구성하겠습니다.

먼저 좌측의 시간을 표현할 영역에 들어갈 시간 위젯부터 시작하겠습니다.

lib/component/schedule_card.dart

import 'package:planner_example/const/colors.dart';
import 'package:flutter/material.dart';

class ScheduleCard extends StatelessWidget {
  final String content; // 일정 내용
  final int startTime; // 시작 시간 (0-23)
  final int endTime; // 종료 시간 (0-23)

  const ScheduleCard({
    super.key,
    required this.content,
    required this.startTime,
    required this.endTime,
  });

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: const EdgeInsets.symmetric(vertical: 4.0, horizontal: 8.0),
      padding: const EdgeInsets.all(8.0),
      decoration: BoxDecoration(
        color: lightGrayColor,
        borderRadius: BorderRadius.circular(8.0),
      ),
      child: Padding(
        padding: const EdgeInsets.all(16.0),
        child: IntrinsicHeight( // 높이를 일정 내용에 맞게 조정
          child: Row(
            children: [
              _Time(startTime: startTime, endTime: endTime),  // 시간 표시
              const SizedBox(width: 16.0),
              _Content(content: content), // 일정 내용 표시
            ],
          ),
        ),
      ),
    );
  }
}

class _Time extends StatelessWidget {
  final int startTime; // Start time in hours (0-23)
  final int endTime; // End time in hours (0-23)

  const _Time({required this.startTime, required this.endTime});

  @override
  Widget build(BuildContext context) {
    final textStyle = TextStyle(
      fontWeight: FontWeight.w600,
      fontSize: 16.0,
      color: primaryColor,
    );

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text('${startTime.toString().padLeft(2, '0')}:00', style: textStyle),
        Text(
          '${endTime.toString().padLeft(2, '0')}:00',
          style: textStyle.copyWith(fontSize: 10.0),
        ),
      ],
    );
  }
}

class _Content extends StatelessWidget {
  final String content;

  const _Content({required this.content});

  @override
  Widget build(BuildContext context) {
    return Expanded(child: Text(content));
  }
}
  • 시작 시간과 종료 시간은 외부에서 입력해줄 수 있도록 매개변수로 선언합니다.
  • 현재 시간 정보는 시작 시간이 위에, 종료 시간이 아래에 Column 위젯을 활용하여 세로로 배치되었습니다.
  • 부모 위젯에서 내용을 String으로 입력해주고 Expandes 위젯에 감싸서 좌우로 최대한 크기를 채웁니다.
  • IntrinsicHeight 위젯은 내부 위젯들의 높이를 최대 높이로 맞춰줍니다. 예를 들어 _Time 위젯은 Column 위젯을 사용 중이기 때문에 ScheduleCard 위젯의 최대 크기만큼 높이를 차지 하지만 _Content 위젯은 Column 위젯을 사용하지 않기 때문에 최소 크기만 차지하며 세로로 가운데 정렬이 됩니다. 이런 경우 _Time 위젯과 _Content 위젯의 높이를 똑같이 맞춰주려면 IntrinsicHeight 위젯을 사용해서 최대 크기를 차지하는 위젯만큼 다른 위젯들 크기를 동일하게 맞춰줍니다.

lib/screen/home_screen.dart

import 'package:flutter/material.dart';
import 'package:planner_example/component/main_calendar.dart';
import 'package:planner_example/component/schedule_card.dart';

class HomeScreen extends StatefulWidget {
  const HomeScreen({super.key});

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  DateTime selectedDay = DateTime.now();

  void onDaySelected(DateTime selectedDay, DateTime focusedDay) {
    setState(() {
      this.selectedDay = selectedDay;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Home')),
      body: SafeArea(
        child: Column(
          children: [
            MainCalendar(
              selectedDay: selectedDay,
              onDaySelected: onDaySelected,
            ),
            ScheduleCard(content: 'Sample Schedule', startTime: 9, endTime: 10),
          ],
        ),
      ),
    );
  }
}
  • MainCalendar 위젯 아래에 샘플로 ScheduleCard 위젯을 샘플 데이터와 함께 위치시켰습니다.

실행화면


참고

댓글 남기기