작성
·
580
0
import 'package:calendar_scheduler/component/custom_text_feild.dart';
import 'package:calendar_scheduler/const/colors.dart';
import 'package:calendar_scheduler/database/drift_database.dart';
import 'package:calendar_scheduler/model/category_color.dart';
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'package:calendar_scheduler/database/drift_database.dart';
class ScheduleBottomSheet extends StatefulWidget { //form 3. StatefulWidget이어야한다.
const ScheduleBottomSheet({Key? key}) : super(key: key);
@override
State<ScheduleBottomSheet> createState() => _ScheduleBottomSheetState();
}
class _ScheduleBottomSheetState extends State<ScheduleBottomSheet> {
final GlobalKey<FormState> formKey = GlobalKey(); //form 4. formKey변수만들어준다.
int? startTime; //3개의 값을 반복적으로 사용하기 위해 저장을한다.
int? endTime;
String? content;
int? selectedColorId; //color를 id로 관리하기 위해 id값을 넣기 위해 변수를 만든다.
@override
Widget build(BuildContext context) {
final bottomInset = MediaQuery.of(context).viewInsets.bottom; //키보드같은 시스템의 높이를 알 수 있음. 상하좌우 가능
return GestureDetector(
onTap: (){
FocusScope.of(context).requestFocus(FocusNode());
},
child: SafeArea(
child: Container(
color: Colors.white,
height: MediaQuery.of(context).size.height /2 + bottomInset, //핸드폰 전체높이에 /2 절반
child: Padding(
padding: EdgeInsets.only(bottom: bottomInset),
child: Padding(
padding: EdgeInsets.only(left: 8.0, right: 8.0, top: 16.0),
child: Form( //form 2. _Time,_Content 이거 있는거 상위에 form을 해준다. key가 컨트롤러가 된다.
key: formKey, //form 5. formKey변수 넣어준다. 컨트롤러가 된다.
autovalidateMode: AutovalidateMode.always, //에러메시지를 실시간 표현해줌.
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_Time(
onStartSaved: (String? val){
startTime = int.parse(val!); //String으로 값이 들어오니 int로 파싱 그걸 위에서 만든 변수에 넣는다.
},
onEndSaved: (String? val){
endTime = int.parse(val!); //val이 값이 없으면 에러메시지뜨도록 했으니 값이 없을수 없다.
},
),
SizedBox(height: 16.0,),
_Content(
onSaved: (String? val){
content = val; //String이니 걍 넣는다.
},
),
SizedBox(height: 16.0,),
FutureBuilder<List<CategoryColor>>(
future: GetIt.I<LocalDatabase>().getCategoryColors(),
//디비가져오기 4 이페이지에서 디비값 가져올수 있게 세팅, LocalDatabase이거는 drift_database파일에서 import
builder: (context, snapshot) {
//print(snapshot.data); //디비가져오기 5 디비에서 가져온 색깔 출력
if(snapshot.hasData && selectedColorId == null && snapshot.data!.isNotEmpty){
//if(데이터가 있고, selectedColorId를 클릭하지 않았음, 하나라도 값이 있거나)
selectedColorId = snapshot.data![0].id; //0번째 빨강색으로 셀렉트 한다.
}
return _ColorPicker(
colors: snapshot.hasData ? snapshot.data! : [],
//디비가져오기 6 hasData 값이 있으면 .hasData 값이 없으면 : [] 걍 빈값을 보낸다.
selectedColorId: selectedColorId!,
);
}
),
SizedBox(height: 8.0,),
_SaveButton(onPressed: onSavePressed,), //form 7 onSavePressed 함수 만든다.
],
),
),
),
),
),
),
);
}
void onSavePressed(){
if(formKey.currentState == null){ //현재 null이 나올수는 없으나 혹시나 null인경우 그냥 리턴해 버린다.
return;
}
if(formKey.currentState!.validate()){ //form 8 에러가 없으면 null값을 리턴하면서 true
print('에러 없음');
formKey.currentState!.save();
print('--------------------');
print('startTime : $startTime');
print('endTime : $endTime');
print('content : $content');
}else{
print('에러 있음');
}
}
}
class _SaveButton extends StatelessWidget {
final VoidCallback onPressed;
const _SaveButton({required this.onPressed, Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Row(
children: [
Expanded(
child: ElevatedButton(
onPressed: onPressed, //form 6 외부로 보낼수 있게 required 만든다.
style: ElevatedButton.styleFrom(
primary: PRIMARY_COLOR,
),
child: Text('저장'),
),
),
],
);
}
}
class _ColorPicker extends StatelessWidget {
final List<CategoryColor> colors; //디비가져오기 1.디비에 있는 칼라를 이걸로 가져올 거임
final int selectedColorId; // 아이디 값을 받아준다.
const _ColorPicker({
required this.colors,
required this.selectedColorId,
Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Wrap(
spacing: 8.0, //좌우간격
runSpacing: 10.0, //상하 간격
children: colors.map((e) => renderColor(e, selectedColorId == e.id)).toList(), //디비가져오기 2. colors값 렌더링하기 ->main에서 GetIt한다.
//여기 e=<CategoryColor>
);
}
Widget renderColor(CategoryColor color, bool isSelected){
return Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Color(
int.parse(
'FF${color.hexCode}', //hexCode 컬럼에 있는 값을 가져온다.
radix: 16, //16진수로 표현한다.
),
),
border: isSelected //선택 되었을대 보더를 넣어준다.
? Border.all(
color: Colors.black,
width: 4.0,
)
: null,
),
height: 32.0,
width: 32.0,
);
}
}
class _Content extends StatelessWidget {
final FormFieldSetter<String> onSaved;
const _Content({required this.onSaved, Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Expanded( //1.텍스필드 꽉차게 다음은 custom_text_feild에
child: CustomTextField(
label: '내용',
isTime: false,
onSaved: onSaved,
),
);
}
}
class _Time extends StatelessWidget {
final FormFieldSetter<String> onStartSaved;
final FormFieldSetter<String> onEndSaved;
const _Time({
required this.onStartSaved,
required this.onEndSaved,
Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Row(
children: [
Expanded(
child: CustomTextField(
label: '시작시간',
isTime: true,
onSaved: onStartSaved,
),
),
SizedBox(width: 8.0,),
Expanded(
child: CustomTextField(
label: '종료시간',
isTime: true,
onSaved: onEndSaved,
),
),
],
);
}
}
초급 섹션 19. [프로젝트] [★★★★☆] 캘린더 스케쥴러에 > 색상 상태관리 강의 따라 하고 있습니다.
그런데 3:25초 부분에서 selectedColorId: selectedColorId!, 만 넣으면 아래 그림처럼 모달창이 안뜹니다. 몇번을 다시 하고 해봤는데 원인을 모르겠습니다.
schedule_bottom_sheet.dart 파일 입니다.
답변 6
0
강사님~ 처음부터 차근차근 다시 했는데 같은곳에서 같은 에러가 생겼습니다. 도저히 뭐를 잘못했는지 모르겠습니다.
https://github.com/cloud5k/test111
레포지토리 이렇게 올리면 되는건가요?
0
터미널 창에 flutter pub run build_runner build 실행하고 앱삭제 후에 다시 실행해봤습니다 그래도 같은 현상입니다. ㅜㅜ
import 'package:calendar_scheduler/model/category_color.dart';
import 'package:calendar_scheduler/database/drift_database.dart';
이거 2개가 비활성처럼 보이는데 혹시 이것 때문일까요?
0
Hive 관련 파일을 수정하시고 flutter pub run build_runner build를 안하시면 .g.dart 파일 갱신이 안됩니다.
강의에서 Hive파일 수정할때마다 실행해주고 있습니다.
하신대로 앱 삭제 후 코드제너레이션 "꼭" 실행해주시고 다시 앱 실행 해보세요.
flutter pub run build_runner build 커맨드가 기억이 아예 안나신다면 다시 처음부터 강의를 들어보시는걸 추천드립니다. 플러터에서 코드제너레이션은 상당히 중요한 부분이라 놓치고 가시면 안됩니다.
코드제너레이션 생성 후 앱 삭제 후 재실행했는데 또 안되시면 말씀 주세요. 레포지토리 봐드리겠습니다. (하지만 벌써 수백명의 수강생이 완강한만큼 높은 확률로 되실겁니다.) 제 생각엔 Hive 코드 수정 후 코드제너레이션 실행을 안하셔서 생기는 문제로 보입니다.
0
null 값이 들어가면 안되는데 null 값이 들어가서 그렇습니다.
앱 삭제 후 코드제너레이션 다시 하신거 맞나요? flutter pub run build_runner build
0
에뮬레이터 다시 설치 했는데도 똑같습니다~ ㅜㅜ 에러 메시지 입니다~
======== Exception caught by widgets library =======================================================
The following CastError was thrown building FutureBuilder<List<CategoryColor>>(dirty, state: FutureBuilderState<List<CategoryColor>>#f31e4):
Null check operator used on a null value
The relevant error-causing widget was:
FutureBuilder<List<CategoryColor>> FutureBuilder:file:///D:/app/calendar_scheduler/lib/component/schedule_bottom_sheet.dart:60:21
When the exception was thrown, this was the stack:
#0 ScheduleBottomSheetState.build.<anonymous closure> (package:calendarscheduler/component/schedule_bottom_sheet.dart:72:59)
#1 _FutureBuilderState.build (package:flutter/src/widgets/async.dart:615:55)
#2 StatefulElement.build (package:flutter/src/widgets/framework.dart:4919:27)
#3 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4806:15)
#4 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4977:11)
#5 Element.rebuild (package:flutter/src/widgets/framework.dart:4529:5)
#6 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4787:5)
#7 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:4968:11)
#8 ComponentElement.mount (package:flutter/src/widgets/framework.dart:4781:5)
#9 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3817:16)
#10 MultiChildRenderObjectElement.inflateWidget (package:flutter/src/widgets/framework.dart:6350:36)
#11 MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6362:32)
... Normal element mounting (362 frames)
#373 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3817:16)
#374 MultiChildRenderObjectElement.inflateWidget (package:flutter/src/widgets/framework.dart:6350:36)
#375 Element.updateChild (package:flutter/src/widgets/framework.dart:3551:18)
#376 RenderObjectElement.updateChildren (package:flutter/src/widgets/framework.dart:5883:32)
#377 MultiChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6375:17)
#378 Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#379 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4832:16)
#380 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4977:11)
#381 Element.rebuild (package:flutter/src/widgets/framework.dart:4529:5)
#382 StatefulElement.update (package:flutter/src/widgets/framework.dart:5009:5)
#383 Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#384 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4832:16)
#385 Element.rebuild (package:flutter/src/widgets/framework.dart:4529:5)
#386 ProxyElement.update (package:flutter/src/widgets/framework.dart:5154:5)
#387 Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#388 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4832:16)
#389 Element.rebuild (package:flutter/src/widgets/framework.dart:4529:5)
#390 ProxyElement.update (package:flutter/src/widgets/framework.dart:5154:5)
#391 InheritedNotifierElement.update (package:flutter/src/widgets/inheritednotifier.dart:108:11)
#392 Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#393 SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6222:14)
#394 Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#395 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4832:16)
#396 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4977:11)
#397 Element.rebuild (package:flutter/src/widgets/framework.dart:4529:5)
#398 StatefulElement.update (package:flutter/src/widgets/framework.dart:5009:5)
#399 Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#400 SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6222:14)
#401 Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#402 SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6222:14)
#403 Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#404 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4832:16)
#405 Element.rebuild (package:flutter/src/widgets/framework.dart:4529:5)
#406 ProxyElement.update (package:flutter/src/widgets/framework.dart:5154:5)
#407 Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#408 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4832:16)
#409 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4977:11)
#410 Element.rebuild (package:flutter/src/widgets/framework.dart:4529:5)
#411 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2659:19)
#412 WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:891:21)
#413 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:370:5)
#414 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1146:15)
#415 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1083:9)
#416 SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:997:5)
#420 _invoke (dart:ui/hooks.dart:151:10)
#421 PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:308:5)
#422 _drawFrame (dart:ui/hooks.dart:115:31)
(elided 3 frames from dart:async)
====================================================================================================
0
안녕하세요.
먼저 에뮬레이터에서 앱을 완전 삭제한 후 flutter pub build_runner build 커맨드를 다시 실행해보시고 앱을 실행해보세요.
그래도 안되면 에러메세지 첨부 부탁드립니다.
안녕하세요!
제가 오늘 오후에 리뷰해보고 확인드리겠습니다