flutter의 다양한 입력들
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Flutter Gesture'),
),
body: const Body(),
),
),
);
}
class Body extends StatelessWidget {
const Body({super.key});
@override
Widget build(BuildContext context){
return const Column(
children: [
TestCheckbox(),
],
);
}
}
class TestCheckbox extends StatefulWidget {
const TestCheckbox({super.key});
@override
State<TestCheckbox> createState() => _TestCheckboxState();
}
class _TestCheckboxState extends State<TestCheckbox> {
late List<bool> values;
@override
void initState() {
super.initState();
values = [false, false, false];
}
@override
Widget build(BuildContext context) {
return Row(
children: [
Checkbox(value: values[0], onChanged: (value) => changeValue(0, value: value)),
Checkbox(value: values[1], onChanged: (value) => changeValue(1, value: value)),
Checkbox(value: values[2], onChanged: (value) => changeValue(2, value: value)),
],
);
}
void changeValue(int index, {bool? value = false}){
setState(() {
values[index] = value!;
});
}
}
저번 시간에 했던 stateful과 stateless를 활용한 입력으로
stateless를 통해 checkbox 칸을 만들고 stateful을 통해 checkbox의 list와 그에 상호작용이 되도록 하는 입력

화면에서 체크 버튼을 누르지 않았을 때

눌렀을 때
class TestRadioButton extends StatefulWidget {
const TestRadioButton({super.key});
@override
State<TestRadioButton> createState() => _TestRadioButtonState();
}
enum TestRadioValue {
test1,
test2,
test3;
}
class _TestRadioButtonState extends State<TestRadioButton> {
TestRadioValue? selectValue;
@override
Widget build(BuildContext context) {
return Column(
children: [
Radio<TestRadioValue>(value: TestRadioValue.test1,
groupValue: selectValue,
onChanged: (value) =>
setState(() {
selectValue = value!;
})),
Radio<TestRadioValue>(value: TestRadioValue.test2,
groupValue: selectValue,
onChanged: (value) => setState(() {
selectValue = value!;
})),
Radio<TestRadioValue>(value: TestRadioValue.test3,
groupValue: selectValue,
onChanged: (value) => setState(() {
selectValue = value!;
})),
],
);
}
}
- check box와 마찬가지로 버튼이 눌리는 입력 하나하나를 위젯에 반응시켜야 하기 때문에 stateful을 통해 작업하였고, Column 혹은 Row를 결정하는 기준은 위젯을 만들 때 분위기에 맞게 만들면 된다 여기서는 coulum으로 작업하였지만 row로 작업하여도 아무 문제 없다.
- 또한 check box처럼 setstate를 하지 않으면 radio button은 만들어지더라도 동작이 위젯에 들어나지는 않는다.


만약 button에 이름을 붙이고 싶다면?
class _TestRadioButtonState extends State<TestRadioButton> {
TestRadioValue? selectValue;
@override
Widget build(BuildContext context) {
return Column(
children: [
ListTile(
leading: Radio<TestRadioValue>(value: TestRadioValue.test1,
groupValue: selectValue,
onChanged: (value) =>
setState(() {
selectValue = value!;
})),
title: Text(TestRadioValue.test1.name),
),
ListTile(
leading: Radio<TestRadioValue>(value: TestRadioValue.test2,
groupValue: selectValue,
onChanged: (value) =>
setState(() {
selectValue = value!;
})),
title: Text(TestRadioValue.test2.name),
),
ListTile(
leading: Radio<TestRadioValue>(value: TestRadioValue.test3,
groupValue: selectValue,
onChanged: (value) =>
setState(() {
selectValue = value!;
})),
title: Text(TestRadioValue.test3.name),
),
],
);
}
}
위에서 보였던 raido부분을 ListTile로 감싸고 title을 통해 이름을 설정하면 된다.

class TestSlider extends StatefulWidget {
const TestSlider({super.key});
@override
State<TestSlider> createState() => _TestSliderState();
}
class _TestSliderState extends State<TestSlider> {
double value = 0;
@override
Widget build(BuildContext context) {
return Slider(
value: value,
onChanged: (newValue)=> setState(() => value = newValue),
);
}
}
- 초기값이 필요하기 때문에 초기값을 0으로 설정해줌
- onchaged 부분은 원래 2~3줄이 더 있지만 한줄 짜리 코드로 2~3줄이 있는거라 중괄호에 alt+enter누르면 한 줄 짜리 코드를 저런식으로 변환 가능
- state에 형태를 변화시키는 것이기 때문에 stateful 사용

만약 Slider 위치에 따른 값을 설정하고 싶다면?
class _TestSliderState extends State<TestSlider> {
double value = 0;
@override
Widget build(BuildContext context) {
return Column(
children: [
Text('${value.round()}'),
Slider(
value: value,
onChanged: (newValue)=> setState(() => value = newValue),
divisions: 100,
max: 100,
min: 0,
label: value.round().toString(),
),
],
);
}
}
이런식으로 Slider를 Column으로 감싼 후 슬라이더의 최대값과 최솟값을 설정 한 후에 위치에 따라 값이 출력되도록 코드를 작성할 수 있다.

class TestSwitch extends StatefulWidget {
const TestSwitch({super.key});
@override
State<TestSwitch> createState() => _TestSwitchState();
}
class _TestSwitchState extends State<TestSwitch> {
bool value = false;
@override
Widget build(BuildContext context) {
return Switch(value: value, onChanged: (newValue) => setState(() => value = newValue));
}
}
Switch 또한 Slider처럼 초기값이 필요한데 Switch는 False와 True로 이루어져 있으니 bool값을 Swtich가 꺼져있을 때 기준인 False로 설정해줌

class TestPopupMenu extends StatefulWidget {
const TestPopupMenu({super.key});
@override
State<TestPopupMenu> createState() => _TestPopupMenuState();
}
class _TestPopupMenuState extends State<TestPopupMenu> {
TestValue selectValue = TestValue.test1;
@override
Widget build(BuildContext context) {
return PopupMenuButton(itemBuilder: (context) {
return TestValue.values
.map((value) => PopupMenuItem(value: value, child: Text(value.name)))
.toList();
});
}
}
- builder 함수에는 항상 builder context 객체가 들어감
- return으로 위젯을 만드는 작업이 필요한데 item 목록을 만들거기 때문에 popupmenuitem을 통해 목록에 나올 item들에 대한 value와 value의 이름을 설정해줌
- 여기서는 위에 value에 대한 name을 설정 해 놓은게 있기 때문에(test1,test2,test3) 그 목록들을 item 목록에 나오게 value.name으로 모든 이름을 입력
- popupmenuitem에 대해서도 return을 해야되는데 그냥 return을 앞에 붙이면 에러가 나기 때문에 맨 뒤에 .toList()를 붙임

popupmenu의 기본 모습

클릭했을 때 모습