버튼을 누르면 팝업창이 나타나고 팝업창에 정보를 입력하면 화면에 계속 쌓이는 코드를 짜보겠습니다.
먼저 팝업창을 띄울 버튼을 만들어 줍니다.
ElevatedButton(
style: ElevatedButton.styleFrom(
elevation: 0.0,
backgroundColor: Colors.blueGrey,
minimumSize: Size(150, 30)),
onPressed: () {
_showDialog(context);
},
child: Text('팝업',
style: TextStyle(
color: Colors.black,
fontSize: 20,
)
)
),
onpressed에 있는 _showDialog를 이름으로 하는 팝업창 함수를 만들어 보겠습니다.
팝업창은 AlertDialog를 사용해서 만들어 주겠습니다.
먼저 팝업창에서 textfeild에서 받을 정보를 저장할 변수가 필요합니다.
final _todoEditController = TextEditingController();
final _dateEditController = TextEditingController();
그리고 저장할 데이터를 담을 리스트를 만들어 줍니다.
final List<String> todo = ["할일1"];
final List<String> date = ["날짜1"];
다음으로는 팝업창을 만들어 보겠습니다.
AlertDialog(
title: Text("팝업창",
style: TextStyle(color: Color(0xFF7D5A50),),
),
content: Column(
children: [
TextField(
maxLength: 20,
decoration: InputDecoration(
hintText: '할일',
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.black54,),
),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.black54,),
),
),
controller: _questionEditController,
),
TextField(
maxLength: 20,
decoration: InputDecoration(
hintText: '날짜',
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.black54,),
),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.black54,),
),
),
controller: _answerEditController,
),
],
),
actions: <Widget>[
ElevatedButton(
style: ElevatedButton.styleFrom(
elevation: 0.0,
backgroundColor: Color(0x4D968C83),
minimumSize: Size(150, 30)),
onPressed: () => Navigator.of(context).pop(),
child: Text('취소',
style: TextStyle(
color: Colors.black,
fontSize: 20,)
)
),
ElevatedButton(
style: ElevatedButton.styleFrom(
elevation: 0.0,
backgroundColor: Color(0xFF7D5A50),
minimumSize: Size(150, 30)),
onPressed: () {
setState(() {
String questionText = _questionEditController.text;
String answerText = _answerEditController.text;
question.add(questionText);
answer.add(answerText);
});
Navigator.of(context).pop();
},
child: Text('확인',
style: TextStyle(
color: Colors.black,
fontSize: 20,)
)
),
],
);
textfield를 두 개 사용하여 할 일을 적는 칸과 날짜를 적는 칸을 만들어줍니다.
다음으로는 actions에 elevatedbutton을 두 개 만들어 확인 버튼과 취소 버튼을 만들어 주었습니다.
취소 버튼에는 onPressed: () => Navigator.of(context).pop(), 을 사용하여 팝업창이 닫히는 기능을 구현해 주었고
확인 버튼에는 setState를 통해 텍스트 필드에서 작성한 데이터를 변수에 저장하고 변수를 다시 리스트에 넣어주는 작업을 하였습니다.
setState(() {
String todoText = _questionEditController.text;
String dateText = _answerEditController.text;
todo.add(todoText);
date.add(dateText);
});
화면에 나타나는 컨테이너는 커스텀 컨테이너를 활용하였습니다.
class TodoData {
final String todo;
final String date;
TodoData({
required this.todo,
required this.date,
});
}
컨테이너에서 필요한 변수들을 설정해 줍니다.
class CustomContainer extends StatelessWidget {
final String vtodo;
final String vdate;
CustomContainer({super.key,
required this.vtodo,
required this.vdate,
});
@override
Widget build(BuildContext context) {
final SizeX = MediaQuery.of(context).size.width;
final SizeY = MediaQuery.of(context).size.height;
return Container(
margin: EdgeInsets.fromLTRB(0, 20, 0, 0),
height: SizeY*0.08,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(10)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
children: [
SizedBox(
width: 25,
),
Text(
vtodo,
style: TextStyle(
fontSize: 17,
color: Color(0xFF7D5A50)),
),
],
),
Container(
color: Colors.grey,
width: SizeX*0.8, height: 1,
margin: EdgeInsets.fromLTRB(0, 5, 0, 6),
),//칸 나누는 줄
Row(
children: [
SizedBox(
width: 30,
),
Text(vdate,
style: TextStyle(
fontSize: 17,
))
],
),
],
),
);
}
}
이렇게 생긴 컨테이너를 디자인해 주었습니다.
이제 본문에 팝업창과 컨테이너를 이어주기만 하면 됩니다.
데이터가 쌓일 때마다 화면에 컨테이너가 계속 쌓이도록 ListView.builder를 사용해 주겠습니다.
Expanded(
child: ListView.builder(
itemCount: todo.length,
itemBuilder: (BuildContext context, int index){
return CustomContainer(
vtodo: todo[index],
vdate: date[index]
);
}
),
),
todo 리스트에 쌓인 개수만큼 컨테이너가 쌓이게 하기 위해
itmeCount: todo.length,로 개수를 제한해 주었습니다
그리고 아까 만들어 둔 커스텀 컨테이너를 return 하여 불러주고
커스텀 컨테이너에 팝업에서 받아온 정보를 넘겨줍니다.
이 화면에서 팝업 버튼을 누르면
팝업창이 뜨고 텍스트 필드에 각각 데이터를 입력하고 확인 버튼을 누르면
화면에 데이터가 추가됩니다.
import 'package:flutter/material.dart';
class second extends StatefulWidget {
const second({super.key});
@override
State<second> createState() => _secondState();
}
final _questionEditController = TextEditingController();
final _answerEditController = TextEditingController();
class _secondState extends State<second> {
final List<String> todo = ["할일1"];
final List<String> date = ["날짜1"];
Future<void> _showDialog(BuildContext context) {
return showDialog<void>(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return AlertDialog(
title: Text("팝업창",
style: TextStyle(color: Color(0xFF7D5A50),),
),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(
maxLength: 20,
decoration: InputDecoration(
hintText: '할일',
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.black54,),
),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.black54,),
),
),
controller: _questionEditController,
),
TextField(
maxLength: 20,
decoration: InputDecoration(
hintText: '날짜',
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.black54,),
),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.black54,),
),
),
controller: _answerEditController,
),
],
),
actions: <Widget>[
ElevatedButton(
style: ElevatedButton.styleFrom(
elevation: 0.0,
backgroundColor: Color(0x4D968C83),
minimumSize: Size(150, 30)),
onPressed: () => Navigator.of(context).pop(),
child: Text('취소',
style: TextStyle(
color: Colors.black,
fontSize: 20,)
)
),
ElevatedButton(
style: ElevatedButton.styleFrom(
elevation: 0.0,
backgroundColor: Color(0xFF7D5A50),
minimumSize: Size(150, 30)),
onPressed: () {
setState(() {
String questionText = _questionEditController.text;
String answerText = _answerEditController.text;
todo.add(questionText);
date.add(answerText);
});
Navigator.of(context).pop();
},
child: Text('확인',
style: TextStyle(
color: Colors.black,
fontSize: 20,)
)
),
],
);
},
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black12,
body: Center(
child: Column(
children: [
Expanded(
child: ListView.builder(
itemCount: todo.length,
itemBuilder: (BuildContext context, int index){
return CustomContainer(
vtodo: todo[index],
vdate: date[index]
);
}
),
),
Container(
child: ElevatedButton(
style: ElevatedButton.styleFrom(
elevation: 0.0,
backgroundColor: Colors.blueGrey,
minimumSize: Size(150, 30)),
onPressed: () {
_showDialog(context);
},
child: Text('팝업',
style: TextStyle(
color: Colors.black,
fontSize: 20,))),
)
],
),
),
);
}
}
class TodoData {
final String todo;
final String date;
TodoData({
required this.todo,
required this.date,
});
}
class CustomContainer extends StatelessWidget {
final String vtodo;
final String vdate;
CustomContainer({super.key,
required this.vtodo,
required this.vdate,
});
@override
Widget build(BuildContext context) {
final SizeX = MediaQuery.of(context).size.width;
final SizeY = MediaQuery.of(context).size.height;
return Container(
margin: EdgeInsets.fromLTRB(0, 20, 0, 0),
height: SizeY*0.08,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(10)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
children: [
SizedBox(
width: 25,
),
Text(
vtodo,
style: TextStyle(
fontSize: 17,
color: Color(0xFF7D5A50)),
),
],
),
Container(
color: Colors.grey,
width: SizeX*0.8, height: 1,
margin: EdgeInsets.fromLTRB(0, 5, 0, 6),
),//칸 나누는 줄
Row(
children: [
SizedBox(
width: 30,
),
Text(vdate,
style: TextStyle(
fontSize: 17,
))
],
),
],
),
);
}
}