말랑한 하루

[Flutter] (Project) Todo List 본문

개발/Flutter

[Flutter] (Project) Todo List

지수는말랑이 2023. 12. 25. 10:58
반응형

※ reference : https://riverpod.dev/docs/introduction/getting_started

※ github : https://github.com/Jisup/practice-projects/tree/main/fluttertodolist_jisu

 

이번 글은, Todo List Project를 만들면서 배워나간 Flutter/Dart에 대한 기본적인 내용과 Widget의 개념/활용에 대한 글을 서식합니다. Todo List를 구현해 놓은 전반적인 내용은 없지만, Github를 참조하여 함께 개발해나가길 바랍니다.

 

🥕 main.dart는 MaterialApp으로 시작해요

 

🥕 SingleTickerProviderStateMixin

TabController를 사용하기 위해선, _AppState에 SingleTickerProviderStateMixin이 함께 상속되어야 해요

 

🥕 AppBar, BottomNavigationBar 그리고 DefaultTabController, TabController

AppBar나 BottomNavigationBar를 사용하기 위해선, DefaultTabController 또는 TabController가 필요해요.

저는 DefaultTabController로 AppBar를 만드는 작업을 진행했어요. 이 Widget은 length와 child가 필수적으로 명시해주어야 합니다.

 

DefaultTabController의 child는 Scaffold를 사용해요. Scafflod는 이런친구인데, appBar, body, bottomNavigationBar 속성을 활용해서 우리가 원하는 기본적인 앱의 모습을 만들어갈 수 있어요

 

만약 appBar나 bottomNavigationBar에 TabBar를 사용하게 되면, body에는 TabBarView가 필요합니다.

또한, DefaultTabController에서 명시한 length의 길이에 맞게 appBar와 body를 구현해주어야 해요. 그래서 내가 원하는 tabBar를 리스트로 구현해놓고, length와 appBar에 적절하게 사용하는 것이 일반적입니다.

 

appBar는 leading, title, actions, flexibleSpace, bottom으로 구성되어 있어요.

Tab리스트 형식의 appBar를 구성하면 bottom에는 TabBar를 사용하게 됩니다.

 

🥕 initState

BuildContext의 값을 initState에서 사용할 땐 무수히 많은 오류를 발생시킨다. 그 이유는 initState가 종료되었을 때 context를 이용한 모든 기능을 사용할 수 있기 때문이다.

 

만약, 상속된 위젯이 변경되면 위젯이 다시 빌드를 하는데, 이 때 사용하는 코드가 initState함수 내에서 사용하게 되면 다시 빌드가 되지 않아 갱신이 안되는 문제가 발생할 수 있기 때문이다.

 

그래서 일반적으로 build함수에서 사용하거나 didChangedDependencies함수에서 사용하는 것을 권장한다.

 

굳이 initState에서 사용하려면 Future.delayed(Duration.zero, () {})로 동기화 처리를 할 수 있다고 한다.

 

🥕 flutter Class

flutter는 다양한 변수를 model을 통해 정립하고 Widget에서 사용한다. 가장 기초적인 방법으로는 다음을 진행했다

  1. final 변수 만들기
  2. fromMap
  3. toString override

🥕 BoxDecoration

BoxDecoration은 width를 지정할 수 없고 무언가의 decoration이기 때문에 Container 또는 Widget으로 꼭 감싸주어야 합니다.

 

Container는 width 및 decoration 속성을 가지고 있기 때문에 BoxDecoration과 적합합니다.

decoration 속성에서 유의할 것은 바로 색상 지정입니다.

Container( decoration: BoxDecoration())이 존재할 때, Container의 color와 BoxDecoration의 color를 동시에 사용할 수 없습니다.

color에서 값이 추가되어도, decoration에서 다시 한번 그릴 수 있기 때문에 개발자가 인지할 수 없습니다. 개인적인 생각으로는 decoration 하위에 color를 구현하는 것이 좋습니다.

 

BoxDecoration에서 가장 중요한 속성은 color, image, border, borderRadius입니다.

 

image는 DecorationImage Widget을 활용해, image를 설정하고 fit속성과 함께 BoxFit Class를 사용하면 BoxDecoration의 크기에 맞게 이미지를 설정할 수 있습니다.

border는 Border Class를 사용하며, width 속성을 이용해 테두리의 너비를 지정할 수 있습니다

borderRadius는 BorderRadius Class를 사용해 circlular method로 테두리 부분을 원형으로 바꿀 사이즈를 지정할 수 있습니다

 

🥕 TextFiled

TextFiled는 controller, decoration, onChanged, onSubmitted속성을 가지고 있다.

 

TextFiled의 controller로는 TextEditingController를 사용할 수 있는데, TextFiled에 대한 value를 관리하고 addListener를 통해 특정 콜백 함수를 실행시킬 수 있다.

decoration속성은 BoxDecoration Class를 활용해 테두리, 색상 등 요소를 꾸미기 위한 진행을 할 수 있다.

onChanged, onSubmitted는 사용자의 행위에 따라 진행되는 속성으로 onChanged는 TextFiled의 value가 변경될 때마다 호출되며, onSubmitted는 키보드의 입력 완료를 눌렀을 때 호출된다.

 

더 발전된 TextFiled를 사용하고 싶다면 TextFormFiled Widget과 onEditingCompleted속성을 사용해보자.

 

🥕 CheckBox

CheckBox는 bool값으로 변경되는 value속성을 지녔습니다. value에 따라 Box가 선택되었는지, 되지 않았는지 표현하기 위해 사용합니다.

checkColor를 통해 선택 아이콘의 색상을 지정할 수 있습니다.

fillColor를 통해 체크박스의 색상을 지정할 수 있습니다. 단, fillColor는 MaterialStateProperty를 통해 색상을 지정해야 사용할 수 있습니다. fillColor를 사용하기 위한 구현은 다음과 같습니다

  1. Set<MaterialState> interactiveStates = {};

 

MaterialState로 다양한 상태를 지닐 때 값을 처리할 수 있습니다. 우리는 Color에 대한 값을 처리하기 때문에, state가 interactiveStates의 값을 어떤 것이라도 지니게 되면 색상을 변경할 수 있도록 구현할 수 있습니다.

Color getColor(Set<MaterialState> states) {
    Set<MaterialState> interactiveStates = {
      MaterialState.pressed,
      MaterialState.hovered,
      MaterialState.focused,
    };
    if (states.any(interactiveStates.contains))
      return Colors.blue;
    else
      return Colors.red;
  }

마지막으로 fillColor속성에 getColor함수를 사용할 땐, MaterialStateProperty Class의 resolveWith method를 함께 사용하면 됩니다

fillColor: MaterialStateProperty.resolveWith(getColor)
  1. onChanged: (bool? value) ⇒ SetState(() {})

onChanged속성을 통해 StatefulWidget의 변수를 변경할 수 있습니다. 자세한 구현은 다음과 같습니다

onChanged: (bool? value) => setState(() {
  isCheck = value!;
},),

 

 

🥕 SingleChildScrollView

document: https://api.flutter.dev/flutter/widgets/SingleChildScrollView-class.html

SingleChildScrollView는 LayoutBuilder를 활용해서 생성 해야한다. BuildContext와 BoxConstraints 매개변수를 활용해야 하기 때문이다.

 

BuildContext는 위젯 트리의 위젯 위치에 대한 핸들입니다. WidgetBuilder에 전달되며, Satate.context 멤버에서 사용할 수 있습니다. 일부 정적 함수들도 BuildContext를 호출하여 위젯을 대신하여 동작하거나, 특정 컨텍스트에 대한 데이터를 얻을 수 있습니다.

BoxConstraints는 RenderBox 레이아웃에 대한 불변 레이아웃 제약 조건입니다. Size는 다음 관계가 모두 유지되는 경우에만 BoxConstraints를 존중합니다. 이때 double.infinity는 각 제약조건에 대해 유효한 값입니다.

  1. minWidth ≤ Size.width ≤ maxWidth
  2. minHeight ≤ Size.hegiht ≤ maxHeight

 

SingleChildScrollView가 다른 스크롤 뷰와 차이점은 자식으로 단일 개체만 포함하는 스크롤 뷰이다.

단일 자식으로 ContsraintedBox를 가지는데, ConstraintedBox는 BoxConstraints Widget를 통해 max/min width/height를 가지기 위한 값을 설정할 수 있다.

나는 이 Box의 자식으로 내가 원하는 Column을 삽입하여 사용하였다.

 

반응형
Comments