Flutter
[Flutter] 34. Form 따라 만들어보기
Song hyun
2024. 11. 8. 11:16
728x90
반응형
[Flutter] 34. Form 따라 만들어보기
(1) IconButton 만들기
import 'package:flutter/material.dart';
void main() {
runApp(FeedbackFormApp());
}
// 한 파일안에 여러개의 클래스를 만들 수 있다.
class FeedbackFormApp extends StatelessWidget {
const FeedbackFormApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(seedColor: Colors.redAccent),
),
home: FeedbackForm(),
);
}
}
// 상태 변경 가능한 UI 선언
class FeedbackForm extends StatefulWidget {
const FeedbackForm({super.key});
@override
State<FeedbackForm> createState() => _FeedbackFormState();
}
class _FeedbackFormState extends State<FeedbackForm> {
final _formKey = GlobalKey<FormState>(); // 폼 상태를 추적하기 위한 글로벌 키
int _rating = 0;
bool _subscribe = false;
String _name = '';
String _email = '';
String _comments = '';
String _successMessage = '';
double _satisfaction = 0;
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text('FeedbackForm'),
backgroundColor: Theme.of(context).colorScheme.primaryContainer,
),
body: SingleChildScrollView(
// formField 터치시 소프트 키보드가 올라 옴. 여백 공간 적절히 줘야 함
padding: EdgeInsets.all(16.0),
child: Form(
key: _formKey,
child: Column(
children: [
TextFormField(
decoration: InputDecoration(
labelText: '이름',
hintText: '홍길동',
border: OutlineInputBorder()),
validator: (value) {
// 입력 값 검증
if (value == null || value.isEmpty) {
return '이름을 입력해주세요.';
} else {
// 정상적으로 입력 했다면
return null;
}
}, // end of validator
onSaved: (value) {
_name = value!;
},
),
const SizedBox(height: 16.0),
TextFormField(
decoration: InputDecoration(
labelText: '이메일',
hintText: 'abc@naver.ocm',
border: OutlineInputBorder()),
validator: (value) {
// 입력 값 검증
if (value == null || value.isEmpty) {
return '이메일을 입력해주세요.';
} else {
// 정상적으로 입력 했다면
return null;
}
}, // end of validator
onSaved: (value) {
_email = value!;
},
),
const SizedBox(height: 16.0),
TextFormField(
maxLines: 4, // 여러줄 입력 가능
decoration: InputDecoration(
labelText: '코멘트',
hintText: '경혐을 공유해주세요',
border: OutlineInputBorder()),
validator: (value) {
// 입력 값 검증
if (value == null || value.isEmpty) {
return '코멘트를 입력해주세요.';
} else {
// 정상적으로 입력 했다면
return null;
}
}, // end of validator
onSaved: (value) {
_comments = value!;
},
),
const SizedBox(height: 16.0),
Text('우리 앱을 어떻게 평가하시겠습니까?',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.primary)),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(5, (index) {
return IconButton(
onPressed: () {
setState(() {
// 버그는 추후 수정
_rating = index + 1; // 선택한 점수로 설정
});
},
color: Colors.deepPurpleAccent,
icon: Icon(
_rating > index ? Icons.star : Icons.star_border
),
);
}),
// [
// IconButton(onPressed: (){}, icon: Icon(Icons.star_border)),
// IconButton(onPressed: (){}, icon: Icon(Icons.star_border)),
// IconButton(onPressed: (){}, icon: Icon(Icons.star_border)),
// IconButton(onPressed: (){}, icon: Icon(Icons.star_border)),
// IconButton(onPressed: (){}, icon: Icon(Icons.star_border))
// ],
),
const SizedBox(height: 24),
Text(
'고객 서비스 만족도는 어느 정도입니까?',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.primary
)),
Slider(
value: _satisfaction,
min: 0,
max: 10,
divisions: 10,
label: '슬라이더 라벨값 설정',
onChanged: (value){
setState(() {
print(value);
_satisfaction = value;
});
}),
const SizedBox(height: 16,),
SwitchListTile(
title: const Text('뉴스레터를 구독하시겠습니까?'),
value: _subscribe,
onChanged: (value){
setState(() {
_subscribe = value;
});
}),
const SizedBox(height: 16,),
ElevatedButton(
onPressed: (){
if(_formKey.currentState!.validate()){
// 통과
_formKey.currentState!.save();
// 변수에 값 할당
setState(() {
_successMessage = '제출이 완료 되었습니다';
});
} else {
// 실패
setState(() {
_successMessage = '';
});
}
},
child: const Text('제출')
),
// 다트 문법 활용
if(_successMessage.isNotEmpty)
Padding(
padding: EdgeInsets.symmetric(vertical: 16),
child: Text(
_successMessage,
style: TextStyle(
color: Theme.of(context).colorScheme.primary,
fontSize: 16
),
textAlign: TextAlign.start,
),
)
],
),
),
),
),
);
}
}
728x90
반응형