1)
2) component
/calendar.dart
import 'package:calendar_scheduler/const/colors.dart';
import 'package:flutter/material.dart';
import 'package:table_calendar/table_calendar.dart';
class Calendar extends StatelessWidget {
final DateTime? selectedDay;
final DateTime focusedDay;
final OnDaySelected onDaySelected;
const Calendar({
Key? key,
required this.selectedDay,
required this.focusedDay,
required this.onDaySelected,
}) : super(key: key);
@override
Widget build(BuildContext context) {
final defaultBoxDeco = BoxDecoration(
color: Colors.grey[200],
borderRadius: BorderRadius.circular(6.0),
);
final defaultTextStyle = TextStyle(
color: Colors.grey[600],
fontWeight: FontWeight.w700,
);
return SafeArea(
child: Column(
children: [
TableCalendar(
locale: 'ko_KR',
focusedDay: focusedDay,
firstDay: DateTime(1800),
lastDay: DateTime(3000),
headerStyle: HeaderStyle(
titleCentered: true,
formatButtonVisible: false,
titleTextStyle: TextStyle(
fontWeight: FontWeight.w700,
fontSize: 16.0,
),
),
calendarStyle: CalendarStyle(
isTodayHighlighted: false,
defaultDecoration: defaultBoxDeco,
weekendDecoration: defaultBoxDeco,
selectedDecoration: defaultBoxDeco.copyWith(
color: Colors.white,
border: Border.all(
color: PRIMARY_COLOR,
width: 1.0,
),
),
outsideDecoration: BoxDecoration(
shape: BoxShape.rectangle,
),
defaultTextStyle: defaultTextStyle,
weekendTextStyle: defaultTextStyle,
selectedTextStyle: defaultTextStyle.copyWith(
color: PRIMARY_COLOR,
),
),
onDaySelected: onDaySelected,
selectedDayPredicate: (DateTime day) {
if (selectedDay == null) {
return false;
}
return day.year == selectedDay!.year &&
day.month == selectedDay!.month &&
day.day == selectedDay!.day;
},
),
],
),
);
}
}
/custom_text_field.dart
import 'package:calendar_scheduler/const/colors.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class CustomTextField extends StatelessWidget {
final String label;
// true - 시간 : false - 내용
final bool isTime;
const CustomTextField({
Key? key,
required this.label,
required this.isTime,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
label,
style: TextStyle(
color: PRIMARY_COLOR,
fontWeight: FontWeight.w600,
),
),
if (isTime) renderTextField(),
if (!isTime) Expanded(child: renderTextField()),
],
);
}
Widget renderTextField() {
return TextField(
maxLines: isTime ? 1 : null,
expands: !isTime,
keyboardType: isTime ? TextInputType.number : TextInputType.multiline,
inputFormatters: isTime ? [FilteringTextInputFormatter.digitsOnly] : [],
cursorColor: Colors.grey,
decoration: InputDecoration(
border: InputBorder.none,
filled: true,
fillColor: Colors.grey[300],
),
);
}
}
/schedule_bottom_sheet.dart
import 'package:calendar_scheduler/component/custom_text_field.dart';
import 'package:flutter/material.dart';
import '../const/colors.dart';
class ScheduleBottomSheet extends StatelessWidget {
const ScheduleBottomSheet({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final bottomInset = MediaQuery.of(context).viewInsets.bottom;
return GestureDetector(
onTap: (){
FocusScope.of(context).requestFocus(FocusNode());
},
child: Container(
height: MediaQuery.of(context).size.height / 2 + bottomInset,
color: Colors.white,
child: Padding(
padding: EdgeInsets.only(bottom: bottomInset),
child: Padding(
padding: const EdgeInsets.only(
left: 8.0,
right: 8.0,
top: 16.0,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_Time(),
SizedBox(height: 8.0),
_Content(),
SizedBox(height: 16.0),
_ColorPicker(),
SizedBox(height: 8.0),
_SaveButton(),
],
),
),
),
),
);
}
}
class _Time extends StatelessWidget {
const _Time({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Row(
children: [
Expanded(
child: CustomTextField(
label: '시작 시간',
isTime: true,
),
),
SizedBox(width: 16.0),
Expanded(
child: CustomTextField(
label: '마감 시간',
isTime: true,
),
),
],
);
}
}
class _Content extends StatelessWidget {
const _Content({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Expanded(
child: CustomTextField(
label: '내용',
isTime: false,
),
);
}
}
class _ColorPicker extends StatelessWidget {
const _ColorPicker({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Wrap(
spacing: 10,
children: [
renderColor(Colors.red),
renderColor(Colors.orange),
renderColor(Colors.yellow),
renderColor(Colors.green),
renderColor(Colors.blue),
renderColor(Colors.indigo),
renderColor(Colors.purple),
],
);
}
Widget renderColor(Color color) {
return Container(
width: 32.0,
height: 32.0,
decoration: BoxDecoration(
color: color,
shape: BoxShape.circle,
),
);
}
}
class _SaveButton extends StatelessWidget {
const _SaveButton({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Row(
children: [
Expanded(
child: ElevatedButton(
onPressed: () {},
style: ElevatedButton.styleFrom(
primary: PRIMARY_COLOR,
),
child: Text(
'저장',
),
),
),
],
);
}
}
/schedule_card.dart
import 'package:calendar_scheduler/const/colors.dart';
import 'package:flutter/material.dart';
class ScheduleCard extends StatelessWidget {
final int startTime;
final int endTime;
final String content;
final Color color;
const ScheduleCard({
Key? key,
required this.startTime,
required this.endTime,
required this.content,
required this.color,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8.0),
border: Border.all(
width: 1.0,
color: PRIMARY_COLOR,
),
),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: IntrinsicHeight(
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
_Time(startTime: startTime, endTime: endTime),
SizedBox(width: 16.0),
_Content(content: content),
SizedBox(width: 16.0),
_Color(color: color),
],
),
),
),
);
}
}
class _Time extends StatelessWidget {
final int startTime;
final int endTime;
const _Time({
Key? key,
required this.startTime,
required this.endTime,
}) : super(key: key);
@override
Widget build(BuildContext context) {
final textStyle = TextStyle(
fontWeight: FontWeight.w600,
color: PRIMARY_COLOR,
fontSize: 16.0,
);
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({
Key? key,
required this.content,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Expanded(
child: Text(content),
);
}
}
class _Color extends StatelessWidget {
final Color color;
const _Color({
Key? key,
required this.color,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: color,
shape: BoxShape.circle,
),
width: 16.0,
height: 16.0,
);
}
}
/today_banner.dart
import 'package:calendar_scheduler/const/colors.dart';
import 'package:flutter/material.dart';
class TodayBanner extends StatelessWidget {
final DateTime selectedDay;
final int scheduleCount;
const TodayBanner({
Key? key,
required this.selectedDay,
required this.scheduleCount,
}) : super(key: key);
@override
Widget build(BuildContext context) {
final textStyle = TextStyle(
fontWeight: FontWeight.w600,
color: Colors.white,
);
return Container(
color: PRIMARY_COLOR,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'${selectedDay.year}년 ${selectedDay.month}월 ${selectedDay.day}',
style: textStyle,
),
Text(
'$scheduleCount개',
style: textStyle,
),
],
),
),
);
}
}
3) const
/colors.dart
import 'package:flutter/material.dart';
const PRIMARY_COLOR = Color(0xFF0DB2B2);
4) screen
/home_screen.dart
import 'package:calendar_scheduler/component/calendar.dart';
import 'package:calendar_scheduler/component/schedule_bottom_sheet.dart';
import 'package:calendar_scheduler/component/schedule_card.dart';
import 'package:calendar_scheduler/component/today_banner.dart';
import 'package:calendar_scheduler/const/colors.dart';
import 'package:flutter/material.dart';
import 'package:table_calendar/table_calendar.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
DateTime selectedDay =
DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day);
DateTime focusedDay = DateTime.now();
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: renderFloatingButton(),
body: Column(
children: [
Calendar(
selectedDay: selectedDay,
focusedDay: focusedDay,
onDaySelected: onDaySelected,
),
SizedBox(height: 8.0),
TodayBanner(
selectedDay: selectedDay,
scheduleCount: 3,
),
SizedBox(height: 8.0),
_ScheduleList(),
],
),
);
}
onDaySelected(DateTime selectedDay, DateTime focusedDay) {
setState(() {
this.selectedDay = selectedDay;
this.focusedDay = selectedDay;
});
}
FloatingActionButton renderFloatingButton() {
return FloatingActionButton(
onPressed: () {
showModalBottomSheet(
isScrollControlled: true,
context: context,
builder: (_) {
return ScheduleBottomSheet();
},
);
},
child: Icon(
Icons.add,
),
);
}
}
class _ScheduleList extends StatelessWidget {
const _ScheduleList({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Expanded(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 8.0),
child: ListView.separated(
itemCount: 100,
separatorBuilder: (context, index) {
return SizedBox(height: 8.0);
},
itemBuilder: (context, index) {
return ScheduleCard(
startTime: 8,
endTime: 9,
content: '프로그래밍 공부하기.',
color: Colors.red,
);
},
),
),
);
}
}
5) main.dart
import 'package:calendar_scheduler/screen/home_screen.dart';
import 'package:flutter/material.dart';
import 'package:intl/date_symbol_data_local.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await initializeDateFormatting();
runApp(
MaterialApp(
theme: ThemeData(
fontFamily: 'NotoSans',
),
home: HomeScreen(),
),
);
}
6)
'개발이 좋아서 > Flutter가 좋아서' 카테고리의 다른 글
[flutter] 켈린더 스케쥴러_최종 (0) | 2023.01.25 |
---|---|
[flutter] 켈린더 스케쥴러_database 생성 (0) | 2023.01.18 |
[flutter] 켈린더 스케쥴러_환경세팅 (0) | 2023.01.12 |
[flutter] 영상통화 앱_만들기 (0) | 2023.01.11 |
[flutter] 영상통화 앱_환경세팅 (0) | 2023.01.10 |