강의

멘토링

커뮤니티

Cộng đồng Hỏi & Đáp của Inflearn

Hình ảnh hồ sơ của cloud5k8132
cloud5k8132

câu hỏi đã được viết

[Code Factory] [Nhập môn] Phát triển ứng dụng Flutter 3.0 - Thoát khỏi trình độ sơ cấp ngay hôm nay với 10 dự án!

모달창이 안뜹니다.

Viết

·

738

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 파일 입니다.

캡처.JPG

Flutter클론코딩

Câu trả lời 6

0

cloud5k8132님의 프로필 이미지
cloud5k8132
Người đặt câu hỏi

강사님~ 처음부터 차근차근 다시 했는데 같은곳에서 같은 에러가 생겼습니다. 도저히 뭐를 잘못했는지 모르겠습니다.

https://github.com/cloud5k/test111

 

레포지토리 이렇게 올리면 되는건가요?

codefactory님의 프로필 이미지
codefactory
Người chia sẻ kiến thức

안녕하세요!

제가 오늘 오후에 리뷰해보고 확인드리겠습니다

codefactory님의 프로필 이미지
codefactory
Người chia sẻ kiến thức

강의 혹시 어디까지 들으셨나요?

제가 확인하는거로는 schedule_bottom_sheet.dart 파일의 78번줄에 selectedColorId가 null인 상황을 예외처리하면 에러가 사라집니다.

제 완료코드에는 이 부분이 있는것으로 보아 이 코드 작성을 까먹으셨거나 이 코드를 작성하는 강의 직전에 멈추신 것 같습니다.

cloud5k8132님의 프로필 이미지
cloud5k8132
Người đặt câu hỏi

안녕하세요~ 강사님
다음 강의 Schedule 저장해버리기~!에 바로 나오네요. ㅜㅜ 감사합니다~ 해결했습니다~

codefactory님의 프로필 이미지
codefactory
Người chia sẻ kiến thức

다행입니다~! 질문 또 있으시면 언제든 문의주세요~

0

cloud5k8132님의 프로필 이미지
cloud5k8132
Người đặt câu hỏi

터미널 창에 flutter pub run build_runner build 실행하고 앱삭제 후에 다시 실행해봤습니다 그래도 같은 현상입니다. ㅜㅜ

import 'package:calendar_scheduler/model/category_color.dart';

import 'package:calendar_scheduler/database/drift_database.dart';

이거 2개가 비활성처럼 보이는데 혹시 이것 때문일까요?

codefactory님의 프로필 이미지
codefactory
Người chia sẻ kiến thức

레포지토리 올려주시면 제가 직접 한번 봐드리겠습니다

cloud5k8132님의 프로필 이미지
cloud5k8132
Người đặt câu hỏi

레포지토리 만든다고 해보다가 파일이 다 날라 갔네요~ ㅎㅎ 처음부터 다시 한번 해보겠습니다. 감사합니다~

codefactory님의 프로필 이미지
codefactory
Người chia sẻ kiến thức

또 안되시면 여기에 댓글 달아주시면 제가 바로 레포지토리 봐드릴게요~

0

cloud5k8132님의 프로필 이미지
cloud5k8132
Người đặt câu hỏi

삭제후 재설치하고image

이 버튼 눌렀는데 이거 말고 다른걸 해야 하는건가요?

codefactory님의 프로필 이미지
codefactory
Người chia sẻ kiến thức

Hive 관련 파일을 수정하시고 flutter pub run build_runner build를 안하시면 .g.dart 파일 갱신이 안됩니다.

강의에서 Hive파일 수정할때마다 실행해주고 있습니다.

하신대로 앱 삭제 후 코드제너레이션 "꼭" 실행해주시고 다시 앱 실행 해보세요.

codefactory님의 프로필 이미지
codefactory
Người chia sẻ kiến thức

flutter pub run build_runner build 커맨드가 기억이 아예 안나신다면 다시 처음부터 강의를 들어보시는걸 추천드립니다. 플러터에서 코드제너레이션은 상당히 중요한 부분이라 놓치고 가시면 안됩니다.

cloud5k8132님의 프로필 이미지
cloud5k8132
Người đặt câu hỏi

네 답변 감사합니다. 다시 한번 보겠습니다~

codefactory님의 프로필 이미지
codefactory
Người chia sẻ kiến thức

코드제너레이션 생성 후 앱 삭제 후 재실행했는데 또 안되시면 말씀 주세요. 레포지토리 봐드리겠습니다. (하지만 벌써 수백명의 수강생이 완강한만큼 높은 확률로 되실겁니다.) 제 생각엔 Hive 코드 수정 후 코드제너레이션 실행을 안하셔서 생기는 문제로 보입니다.

0

codefactory님의 프로필 이미지
codefactory
Người chia sẻ kiến thức

null 값이 들어가면 안되는데 null 값이 들어가서 그렇습니다.

앱 삭제 후 코드제너레이션 다시 하신거 맞나요? flutter pub run build_runner build

0

cloud5k8132님의 프로필 이미지
cloud5k8132
Người đặt câu hỏi

에뮬레이터 다시 설치 했는데도 똑같습니다~ ㅜㅜ 에러 메시지 입니다~

======== 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

codefactory님의 프로필 이미지
codefactory
Người chia sẻ kiến thức

안녕하세요.

먼저 에뮬레이터에서 앱을 완전 삭제한 후 flutter pub build_runner build 커맨드를 다시 실행해보시고 앱을 실행해보세요.

그래도 안되면 에러메세지 첨부 부탁드립니다.

Hình ảnh hồ sơ của cloud5k8132
cloud5k8132

câu hỏi đã được viết

Đặt câu hỏi