PlayStoreλ AppStore μ΄λ μ ν리μΌμ΄μ μ λ€μ΄μ λ°μλ νμκ°μ μ½κ΄ λμ νμ΄μ§λ λ§μ΄ λ΄€μ κ²μ λλ€.
μ€ν μ΄μ μ±μ μ¬λ¦΄λ νμκ°μ /λ‘κ·ΈμΈ/κ°μΈμ 보 λ± μ¬μ©μμ μ 보λ₯Ό λ°μμΌ νκ² λλ€λ©΄
νμμ μΌλ‘ κ°μΈμ 보μ²λ¦¬λ°©μΉ¨μ λ£μ΄μΌλ§ μΉμΈμ ν΄μ£ΌκΈ° λλ¬Έμ΄λ€. κ·Έλμ μ΄ νμ΄μ§λ₯Ό μ μν΄ λ³΄λ €κ³ ν©λλ€.
νκ· μ μΌλ‘ 체ν¬λ°μ€λ 3κ°μ§ νμ μ μ νμ λ°λ‘ λ§λ€μ΄ μ£Όμ΄μΌ ν©λλ€.
1. λͺ¨λ λμ ( λͺ¨λ λμλ₯Ό νλ 체ν¬λ°μ€ )
2. νμ λμ ( λ°λμ ν΄μΌλ§ λ€μνμ΄μ§ λμ΄κ° μ μλ€. )
3. μ νμ λμ ( μν΄λ λ€μ νμ΄μ§λ‘ λμ΄ κ° μ μλ€. )
κ·Έλ¦¬κ³ λ§μ½ νμ λμκ° μ λΆ μ²΄ν¬κ° λμλ€λ©΄ κ°μ νκΈ° λ²νΌμ΄ νμ±ν λμ΄μΌ ν©λλ€.
μ κ·ΈλΌ μ΄μ ꡬνν΄μΌνλ μ리λ λκ° μμμΌλ νλμ© λ―κ³ μΉμ΄ λ§μ λ΄ μλ€.
1. λͺ¨λ λμ λ²νΌ ꡬννκΈ°
쑰건문μΌλ‘λ μ΄ 4κ°μ§ νμ μΌλ‘ κ°λ¨ν©λλ€.
1. λͺ¨λ λμλ₯Ό λλ¬ 5κ° μ²΄ν¬λ°μ€λ₯Ό λͺ¨λ νμ±ν μνλ‘ λ³κ²½
2. 5κ°μ 체ν¬λ°μ€κ° λͺ¨λ νμ±ν λ μνμΌλ λͺ¨λ λμλ₯Ό λ€μ λλ¬ μ 체 ν΄μ
3. 4κ° μ€ 1κ°λΌλ μ νμ΄ λμ΄ μμ§ μμ κ²½μ° λͺ¨λ λμ 체ν¬λ°μ€ νμ±ν ν΄μ
4. 4κ° μ²΄ν¬λ°μ€κ° μ λΆ μ νμ΄ λμ΄ μμ κ²½μ°μ λͺ¨λ λμ 체ν¬λ°μ€ νμ±ν
2. κ°κ°μ 체ν¬λ°μ€ λ²νΌ ꡬννκΈ°
κ°κ°μ 체ν¬λ°μ€λ μ΄ 3κ°μ§ 쑰건문μΌλ‘ μ΄λ£¨μ΄μ§λ©΄ λ©λλ€.
1. λ²νΌμ ν΄λ¦νμ μ toggle (ON / OFF)
2. νμ λ²νΌμ΄ μ λΆ μ²΄ν¬κ° λμμ μ κ°μ νκΈ° λ²νΌ νμ±ν
3. λͺ¨λ λμ λ²νΌμ ν΄λ¦ν΄μκ° μλ κ°κ°μ λ²νΌμ λλ¬μ λͺ¨λ 체ν¬κ° λμμ μ λͺ¨λ λμ λ²νΌ νμ±ν
μΌλ¨ μ΄λ‘μ¨ λ²νΌμ νΈλ¦¬κ±° λΆλΆμ λλ¬μ΅λλ€.
μ΄μ UIλ₯Ό λ§λ€λ©΄μ μ΄ νΈλ¦¬κ±° λΆλΆλ§ μ μκ°νλ©΄μ λ§λ€λ©΄ λμ λλ€. μ΄μ μμ€ μ½λλ₯Ό λ΄ μλ€.
https://dartpad.dev/?id=753b34cd5a6b6b861be6d1deee8af476
μ μ½λλ λ΄κ° μμ±ν μ½λμΈλ° μ μ½μ΄λ³΄λ©΄ ν¬κ² μ΄λ €μ΄ λΆλΆμ μμ΅λλ€.
νκ°μ§ λΆλΆλ§ μ€λͺ νμλ©΄ κ° λ²νΌμ ν΄λ¦ ν λλ§λ€ μ€νλλ _updateCheckState(int index)κ° μμ΅λλ€.
void _updateCheckState(int index) {
setState(() {
// λͺ¨λ λμ 체ν¬λ°μ€μΌ κ²½μ°
if (index == 0) {
bool isAllChecked = !_isChecked.every((element) => element);
_isChecked = List.generate(5, (index) => isAllChecked);
} else {
_isChecked[index] = !_isChecked[index];
_isChecked[0] = _isChecked.getRange(1, 5).every((element) => element);
}
});
}
if(index == 0) / "λͺ¨λ λμ" μ²΄ν¬ λ°μ€ μ²λ¦¬
1. _isChecked 리μ€νΈμ λͺ¨λ νλͺ©μ΄ 체ν¬λμλμ§ κ²μ¬ν©λλ€. λͺ¨λ 체ν¬λμ΄ μμ§ μλ€λ©΄ isAllCheckedλ trueκ° λ©λλ€.
2. _isChecked 리μ€νΈλ₯Ό isAllChecked κ°μΌλ‘ μ¬μ€μ ν©λλ€. μ¦, 'λͺ¨λ λμ' 체ν¬λ°μ€κ° μ νλλ©΄ λͺ¨λ 체ν¬λ°μ€κ° μ νλκ³ , ν΄μ λλ©΄ λͺ¨λ 체ν¬λ°μ€κ° ν΄μ λ©λλ€.
else (index != 0)
1. μ νλ 체ν¬λ°μ€μ μνλ₯Ό ν κΈν©λλ€ (trueλ©΄ falseλ‘, falseλ©΄ trueλ‘).
2. getRange(1, 5)λ₯Ό μ¬μ©νμ¬ 'λͺ¨λ λμ' 체ν¬λ°μ€λ₯Ό μ μΈν λλ¨Έμ§ μ²΄ν¬λ°μ€κ° λͺ¨λ μ νλμ΄ μλμ§ νμΈν©λλ€. λͺ¨λ μ νλμ΄ μλ€λ©΄ 'λͺ¨λ λμ' 체ν¬λ°μ€λ μ νλ©λλ€.
μ¬κΈ°μ List.generate() λΆλΆμ΄ λλ!? λΌκ³ νμ€ μ μλλ° μ²΄ν¬λ°μ€λ₯Ό List ννλ‘ 5κ°λ₯Ό λ§λ€κΈ° μν΄ μ¬μ©νμμ΅λλ€.
μ¦ 0 - 4 κΉμ§ μμλλ‘
0. λͺ¨λ λμ / 1. λ§ 14μΈ μ΄μ / 2. κ°μΈμ 보μ²λ¦¬λ°©μΉ¨ / 3. μλΉμ€ μ΄μ© μ½κ΄ / 4. μ΄λ²€νΈ λ° ν μΈ νν..
μ΄λ κ² μκ°νκ³ μ΄ν΄νλ©΄ λ©λλ€.
μΌλ¨ λ΄κ° ν μ μμ λ§νΌ κ°λ¨νκ² μ€λͺ μ νμλλ° νΉμ μ΄ν΄κ° μλλ λΆλΆμ λκΈλ‘ λ¨κ²¨μ£ΌκΈ° λ°λλλ€.
μ 체 μ½λ
μ½λ 보기
import 'package:flutter/material.dart';
void main() {
runApp(
const MyApp(),
);
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
scaffoldBackgroundColor: Colors.white, // κΈ°λ³Έ λ°°κ²½μμ νμμμΌλ‘ μ€μ
appBarTheme: const AppBarTheme(
backgroundColor: Colors.white,
elevation: 0,
),
),
debugShowCheckedModeBanner: false,
home: const TermsOfServiceAgreement(),
);
}
}
class TermsOfServiceAgreement extends StatefulWidget {
const TermsOfServiceAgreement({super.key});
@override
State<TermsOfServiceAgreement> createState() => _TermsOfServiceAgreementState();
}
class _TermsOfServiceAgreementState extends State<TermsOfServiceAgreement> {
List<bool> _isChecked = List.generate(5, (_) => false);
bool get _buttonActive => _isChecked[1] && _isChecked[2] && _isChecked[3];
void _updateCheckState(int index) {
setState(() {
// λͺ¨λ λμ 체ν¬λ°μ€μΌ κ²½μ°
if (index == 0) {
bool isAllChecked = !_isChecked.every((element) => element);
_isChecked = List.generate(5, (index) => isAllChecked);
} else {
_isChecked[index] = !_isChecked[index];
_isChecked[0] = _isChecked.getRange(1, 5).every((element) => element);
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
onPressed: () {
Navigator.of(context).pop();
},
icon: const Icon(
Icons.arrow_back_ios_new_rounded,
color: Colors.black,
),
),
),
body: Padding(
padding: const EdgeInsets.all(18.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text('νμκ°μ
μ½κ΄ λμ', style: TextStyle(fontSize: 25.0, fontWeight: FontWeight.w700)),
const SizedBox(height: 50),
..._renderCheckList(),
const Spacer(),
Row(
children: [
Expanded(
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: _buttonActive ? Colors.blue : Colors.grey,
),
onPressed: () {},
child: const Text('κ°μ
νκΈ°',style: TextStyle(color: Colors.white),),
),
),
],
),
],
),
),
);
}
List<Widget> _renderCheckList() {
List<String> labels = [
'λͺ¨λ λμ',
'λ§ 14μΈ μ΄μμ
λλ€.(νμ)',
'κ°μΈμ 보μ²λ¦¬λ°©μΉ¨(νμ)',
'μλΉμ€ μ΄μ© μ½κ΄(νμ)',
'μ΄λ²€νΈ λ° ν μΈ νν μλ΄ λμ(μ ν)',
];
List<Widget> list = [
renderContainer(_isChecked[0], labels[0], () => _updateCheckState(0)),
const Divider(thickness: 1.0),
];
list.addAll(List.generate(4, (index) => renderContainer(_isChecked[index + 1], labels[index + 1], () => _updateCheckState(index + 1))));
return list;
}
Widget renderContainer(bool checked, String text, VoidCallback onTap) {
return GestureDetector(
onTap: onTap,
child: Container(
padding: const EdgeInsets.only(top: 20.0, bottom: 20.0),
color: Colors.white,
child: Row(
children: [
Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(color: checked ? Colors.blue : Colors.grey, width: 2.0),
color: checked ? Colors.blue : Colors.white,
),
child: Icon(Icons.check, color: checked ? Colors.white : Colors.grey, size: 18),
),
const SizedBox(width: 15),
Text(text, style: const TextStyle(color: Colors.grey, fontSize: 18)),
],
),
),
);
}
}