본문 바로가기

Flutter/App Making Learn

[플러터] 약관 동의 페이지 만들기1 (on/off 토글키 및 bool타입 선언)

Flutter v3.22.2
Dart v3.4.3
DevTools v2.34.3

 

우선은 동의하느냐 안 하느냐의 문제이기 때문에 bool로 접근하여 빌드해보았습니다.

필수동의 2개, 선택동의 1개가 있으며
필수동의 2개를 반드시 true값으로 만들어줘야 확인버튼을 활성화시켜
다음 페이지로 넘어가는 기능을 구현해 보겠습니다

// agreement_condition_text.dart

bool isAllChecked = false;
bool isRequireChecked = false;
bool isConditionChecked = false;
bool isInfoChecked = false;
bool isThirdChecked = false;

void updateAllChecked() {
  isAllChecked = isConditionChecked && isInfoChecked && isThirdChecked;
}

void updateRequireChecked() {
  isRequireChecked = isConditionChecked && isInfoChecked;
}

void resetState() {
  isAllChecked = false;
  isRequireChecked = false;
  isConditionChecked = false;
  isInfoChecked = false;
  isThirdChecked = false;
}

 

먼저 알아보기 쉽게 총 다섯 가지의 bool값을 선언해 줍니다.

isAllChecked는 가장 위에 존재하는 버튼이며
isRequireChecked는 필수동의항목을 체크하였는지에 대한 bool값입니다.

updateAllChecked이란 함수는
isConditionChecked(필수항목)와 isInfoChecked(필수항목)와 isThirdChecked(선택항목)의 값이 ture가 될 때 isAllchecked를 true로 만드는 함수 입니다. 반대로 isAllchecked가 true면 나머지 3개의 bool들에게 영향을 미칩니다.

그리고

역시 updateRequireChecked란 함수는
isConditionChecked(필수항목)와 isInfoChecked(필수항목)의 값이 true가 될때 isRequireChecked가 true가 됩니다.
이 또한 반대로 isRequireChecked가 true면 나머지 2개의 bool들에게 영향을 미칩니다.

마지막으로

resetState라는 함수를 선언해 주었는데
이는 약관동의 페이지를 벗어난 뒤 다시 약관동의 페이지로 진입하였을 때 이전에 bool값들이 그대로 남아있는 걸 방지하고자
전 bool값들을 초기화시켜주는 함수입니다.

이 페이지를 토대로

버튼들을 구현해 보겠습니다. 저는 아이폰의 토글키 버튼이 마음에 들어 CupertinoSwitch로 진행하였습니다.


전체동의

CupertinoSwitch(
 value: isAllChecked,
 onChanged: (bool value) {
  setState(() {
   isAllChecked = value;
   isConditionChecked = value;
   isInfoChecked = value;
   isThirdChecked = value;
   isRequireChecked = value;
  });
 },
)

코드 해석을 해보자면
CupertinoSwitch라는 함수가 기본적으로 가지고 있는 value와 onChanged를 선언해 줍니다. 왜냐하면

쿠퍼티노스위치 자체가 필수로 value(bool)와 onChanged를 받게 돼있거든요..
참고로 내가 사용하는 함수 또는 변수 위에 마우스 커서를 올려두고 있으면 이 코드에서 어떤 걸 필수로 요하는지 또는 어떤걸 사용할 수 있는지 나옵니다. (안드로이드 스튜디오 기준) 모르시는 분들은 안 읽히더라도 한두 번 얹어보셔서 읽어라도 보시면 좋을 것 같습니다.
저도 잘 모르지만 얹어놓고 읽어보긴 하거든요..

여기서
"value :"란 지금 현재 CupertinoSwitch의 상태를 나타냅니다.
isAllChecked라는 bool값이 true인지 false인지 결정합니다.

그리고
"onChanged :() {}"는 스위치의 상태가 변경될 때 호출되는 콜백 함수입니다.
사용자가 스위치를 켜거나 끌 때 onChanged 함수가 호출되며, 함수는 스위치의 새로운 상태(value라는 매개변수로 전달됨)를 받습니다.

 

여기서 초보인 제가 짚고 넘어가고 싶은 점.

 

이 좌 우의 차이점이 보이시나요?

왼쪽은 onChanged의 매개변수인 "value"의 값이 명시돼있지 않다는 것입니다.
반대로 오른쪽은 "value"의 값이 명시가 돼있습니다.

이는

어지간하면 오른쪽처럼 타입을 명시해 주는 게 협업을 할 때에나, 먼 훗날 내가 쓴 코드를 다시 훑어볼 때에나 도움이 되기 때문에
매개변수의 타입을 정확히 지정해 주는 게 좋습니다.
Dart는 정적 언어타입이므로 타입을 명시적으로 지정하면 오류가 발생하였을 시 더 명확한 오류메시지도 제공받을 수 있습니다.

물론 왼쪽처럼 적어놔도 Dart의 타입추론 덕분에 오류가 발생하지 않지만,
가독성, 타입검사, 명시적 타입이 3가지의 장점이 있기 때문에 타입을 명시해 주는 게 좋습니다.

그리고
"onChanged"의 출력단에
"setState( () {} )"를 선언해 주어 true, false값이 뒤바뀔 때 위젯을 리빌드 하도록 해주고,
value 매개변수(스위치의 새로운 상태)에 따라

  • isAllChecked
  • isConditionChecked
  • isInfoChecked
  • isThirdChecked
  • isRequireChecked

이 다섯 가지의 bool들을 "value"값으로 맞춰 줍니다.


이용약관동의 (필수)

CupertinoSwitch(
 value: isConditionChecked,
 onChanged: (bool value) {
  setState(() {
   isConditionChecked = value;
   updateRequireChecked();
   updateAllChecked();
  });
 },
)

이용약관동의는 필수로 체크해야 하는 항목이기 때문에
"updateRequireChecked();"도 함께 선언해 줍니다. 이렇게 되면

"isConditionChecked"와 "isInfoChecked"가 둘 다 활성화(true) 돼야 "isRequireChecked"도 true가 되는데 
이용약관동의만 체크하였기 때문에 "isRequireChecked"는 true가 되지 않고 호출되지 않습니다.


정보수집동의 (필수)

CupertinoSwitch(
 value: isInfoChecked,
 onChanged: (bool value) {
  setState(() {
   isInfoChecked = value;
   updateRequireChecked();
   updateAllChecked();
  });
 },
)

위 코드와 동일합니다.


제3자제공동의 (선택)

CupertinoSwitch(
 value: isThirdChecked,
 onChanged: (bool value) {
  setState(() {
   isThirdChecked = value;
   updateAllChecked();
  });
 },
)

제3자제공동의는 선택사항이기 때문에

"updateRequireChecked()" 함수를 호출해 줄 필요가 없습니다.
다만 전체동의를 눌렀을 때 활성화 되는 버튼이기 때문에
"updateAllChecked()" 함수만 호출해 줍니다.

여기까지가 버튼별 true, false 및 조건부 true, false를 해보았습니다.

사실 여기까지는 참, 거짓의 이해도만 있으면 충분히 할 수 있기 때문에 최초의 bool 들과 함수만 잘 선언해 주면 문제없을 부분인 것 같습니다!

다음번엔 텍스트를 클릭하였을 시 아래로 본문내용이 나오게 되는 "ExpansionTile"에 대해서 알아보겠습니다.

*제가  써놓은 최종 코드는 2편에 기재하겠습니다.
많이 부족하나 혹시나 필요하시면 참고 부탁드립니다.