10일차는 조건문을 통해 원하는 상황에 맞는 위젯을 보여줄 수 있는 방법을 학습했다.
학습한 내용
- dart if문
- Flutter에서 위젯에 조건문 사용방법
- 삼항 연산자
- Checkbox와 Visibility 위젯
if 조건문은 기본적인 문법이지만 간단히 사용법만 작성해 보고자 한다. 다른 프로그래밍 언어들과 사용방법은 같다.
if (조건1) {
// 실행해야 될 코드
} else if (조건2) {
// 실행해야 될 코드
} else {
// 실행해야 될 코드
}
삼항 연산자는 [Flutter] 스나이퍼팩토리 2주차 도전하기 에서 정리한 적이 있지만 이번에 학습하게 되어 간단히 다시 정리하고자 한다.
삼항 연산자는 ? 앞의 수식이 true이면 콜론 앞쪽을 반환하고, false이면 콜론 뒤쪽을 반한다. 아래는 삼항 연산자의 예시 코드이다.
void main(){
bool isChecked = false;
isChecked ? print('please check!') : print('ok! Checked!');
}
삼항 연산자를 사용하면 조건문을 더 간결하게 표현할 수 있다.
Flutter에서는 상황에 따라 다른 위젯을 그리는 경우가 있는데 이때 삼항 연산자를 사용할 수 있다.
아래와 같은 코드처럼 boolean 타입의 isSignIn
값에 따라 RaisedButton()
을 그리거나 아무것도 그리지 않고 SizedBox()
를 반환하는 등의 활용이 가능하다.
isSignIn
? RaisedButton(
child: Text('SingUP')
onPressed:(){}
)
: SizedBox(),
onSubmitted
사용자가 TextField
에서 작업이 끝났을 때 onSubmitted
콜백을 통해서 알려준다. 이때 현재 text를 String 값으로 넘겨준다.
onEditingComplete
TextField
에서 작업이 끝났을 때 nSubmitted
와 마찬가지로onEditingComplete
콜백을 통해서 알려준다.
onEditingComplete
는 텍스트 컨트롤러를 업데이트하고 키보드 focus를 yeild의 기본값으로 갖고 있다는 점에서 onSubmitted
와 차이가 있다.
즉, onEditingComplete
는 예를 들어서 채팅 앱에서 메세지를 보낼 때마다 키보드를 내려가지 않도록 설정하는 등의 코드를 작성하기 좋고, onSubmitted
는 전달된 값을 사용할 때 사용하기 좋다.
자세한 TextField
의 컨트롤러, 이벤트 등의 내용은 아래의 링크를 참고
[플러터] TextField 위젯
안드로이드 에뮬레이터를 처음 생성하면 한글 키보드를 사용할 수 없고, PC의 키보드와 연동도 되지 않는다.
우선 한글 키보드 설정은 에뮬레이터의 핸드폰 설정의 Language에서 한국어를 추가하는 방식으로 설정 가능하다.
키보드는 연동은 안드로이드 스튜디오를 사용할 경우 만들 때 체크박스로 설정 가능하다. 하지만 안드로이드 스튜디오를 사용하지 않을 경우 직접 설정을 변경할 수 있다.
- 윈도우의 경우 AVD의 저장 경로로 이동해야 하는데 보통 아래와 같다.
C:\Users\[사용자 아이디]\.android\avd\[Virtual Device 이름]
- 해당 경로로 이동한 후에
config.ini
파일을 연다.- 이 파일에서
hw.keyboard
부분의 값을 no에서 yes로 변경한다.hw.keyboard = yes
Checkbox
위젯은 StatefulWidget
으로 생성해야 하며 setState
함수를 같이 사용해야 변경된 UI가 화면에 적용된다.
아래는 Checkbox
위젯의 사용 예시이다.
var _isChecked = false;
...
child: Center(
child: Checkbox(
value = _isChecked,
onChanged: (value) {
setState(() {
_isChecked = value;
});
},
),
),
...
Visibility
는 위젯을 상황에 따라 보이게 하거나 숨기는데 사용한다. Visibility
위젯도 setState
를 사용해 화면을 바꾸기 때문에 StatefulWidget
을 사용한다. 아래 코드는 사용 예시이다.
...
class _MyHomePageState extends State<MyHomePage> {
bool _visibility = true;
void _show() {
setState(() {
_visibility = true;
});
}
void _hide() {
setState(() {
_visibility = false;
});
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('widget.title'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Visibility(
child: Text('이 글자를 안보이게 하고 싶습니다.',
style: Theme.of(context).textTheme.headline4,
),
visible: _visibility,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => {_visibility? _hide() : _show()},
tooltip: 'show/hide',
child: Icon(Icons.add),
),
);
}
}
_visibility
변수에 따라 아래의 Text
위젯을 보여주거나 숨기는 예시로 미리 _show()
와 _hide()
함수를 setState
메소드를 사용하여 작성해 놓았다.
Text
위젯은 Visibility
위젯으로 감싸고 visible
속성은 앞에서 생성한 _visibility
변수로 저장했다.
FAB을 클릭하면 _visibility
의 값에 따라 _show()
또는 _hide()
함수가 실행된다.
- Dart if문 사용 연습
- Dart Switch Case문
- 주어진 UI 만들기
- 3번의 코드에 추가하여 UI 구성
아래와 같은 데이터를 사용하여 12가지의 if문을 만들어보고자 한다.
var myMoney = 4500;
var accountMoney = 4000000;
var minTaxiFare = 4800;
var iPadPrice = 1000000;
var iPhonePrice = 960000;
var friend1Name = "Teddy";
var friend2Name = "Chris";
var friend3Name = "Juno";
var mathScore = [59,24,62,44,94,61,42];
var minPassScore = 80;
var emailAddress = 'dkanrjskclrl';
var phoneNum = '010-1000-';
var password = '1234';
void main() {
var myMoney = 4500;
var minTaxiFare = 4800;
if (myMoney >= minTaxiFare) {
print('택시를 탈 수 있습니다.');
} else {
print('택시를 탈 수 없습니다.');
}
}
현재 보유하고 있는 금액이 택시 최소 비용보다 작기 때문에 택시를 탈 수 없습니다.
가 출력된다.
void main() {
var myMoney = 4500;
var iPadPrice = 1000000;
if (myMoney >= iPadPrice) {
print('아이패드를 살 수 있습니다ㅎㅎ');
} else {
print('아이패드를 살 수 없습니다!!');
}
}
현재 보유하고 있는 금액이 아이패드의 금액보다 적기 때문에 아이패드를 살 수 없습니다!!
가 출력된다.
void main() {
var accountMoney = 4000000;
var iPadPrice = 1000000;
var iPhonePrice = 960000;
if (accountMoney >= iPadPrice+iPhonePrice) {
print('아이패드와 아이폰을 살 수 있습니다ㅎㅎ');
} else {
print('아이패드와 아이폰을 살 수 없습니다!!');
}
}
계좌의 돈이 아이패드와 아이폰 가격을 합친 것보다 많으므로 아이패드와 아이폰을 살 수 있습니다ㅎㅎ
가 출력된다.
void main() {
var accountMoney = 4000000;
var iPadPrice = 1000000;
if (accountMoney >= iPadPrice*5) {
print('아이패드 5개를 살 수 있습니다ㅎㅎ');
} else {
print('아이패드 5개를 살 수 없습니다!!');
}
}
아이패드 5개를 살 수 없습니다!!
가 출력된다.void main() {
var friend1Name = "Teddy";
var friend2Name = "Chris";
var friend3Name = "Juno";
var nameAdd = friend1Name + friend2Name + friend3Name;
if (nameAdd.length > 10) {
print('이름이 10자리가 넘습니다.(${nameAdd.length-10}자리 초과)');
} else {
print('이름이 10자리가 넘지 않습니다!!');
}
}
세 명의 이름을 합쳐서 nameAdd
변수에 저장하고 nameAdd.length
를 사용해 길이를 비교했다.
이름의 길이가 14자리 이므로 이름이 10자리가 넘습니다.(4자리 초과)
가 출력된다.
void main() {
var mathScore = [59,24,62,44,94,61,42];
var minPassScore = 80;
if (mathScore[0] > minPassScore) {
print('합격ㅎㅎ');
} else {
print('불합격!!');
}
}
mathScore
의 0번째 점수가 59점이기 때문에 80점 보다 낮아 불합격!!
이 출력된다.
void main() {
var mathScore = [59,24,62,44,94,61,42];
if (mathScore[0] + mathScore[1] > mathScore[4]) {
print('0번째와 1번째의 점수 합이 4번째 보다 높음');
} else {
print('0번째와 1번째의 점수 합이 4번째 보다 낮음ㅠㅠ');
}
}
0번째와 1번째의 합이 83점으로 4번째의 점수인 94보다 낮기 때문에 0번째와 1번째의 점수 합이 4번째 보다 낮음ㅠㅠ
가 출력된다.
void main() {
var emailAddress = 'dkanrjskclrl';
if (emailAddress.contains('@')) {
print('확인완료ㅎㅎ');
} else {
print('확인되지 않음!!');
}
}
contains()
함수를 사용해 이메일이 @가 포함되었는지 확인했다. 이메일에 @가 없기 때문에 확인되지 않음!!
이 출력된다.
void main() {
var phoneNum = '010-1000-';
if (phoneNum.length == 13 && phoneNum.split('-').length - 1 == 2) {
print('휴대폰 번호 확인 완료 ㅎㅎ');
} else {
print('잘못된 휴대폰 번호!!');
}
}
if문에서 휴대폰 번호의 길이가 13인지 확인하고 맞다면 "-"의 개수가 두 개인지 확인하여 두 조건 모두 충족한다면 휴대폰 번호를 확인 완료했다는 메세지를 출력한다.
"-"의 개수는 split()
함수를 사용해 "-"를 기준으로 문자열을 나눈 뒤 나눠진 문자열의 개수에서 1을 빼서 구했다.
"-" 개수는 2개가 맞지만 휴대폰 번호의 총 길이가 9이므로 잘못된 휴대폰 번호!!
가 출력된다.
phoneNumCheck(String phone) {
//휴대폰 자리 수 확인
if (phone.length != 13) {
return false;
}
// "-"의 개수가 두 개인지 확인
if (phone.split('-').length - 1 != 2) {
return false;
}
return true;
}
void main() {
var phoneNum = '010-1000-';
if (phoneNumCheck(phoneNum)) {
print('휴대폰 번호 확인 완료 ㅎㅎ');
} else {
print('잘못된 휴대폰 번호!!');
}
}
phoneNumCheck()
함수에서 매개변수로 휴대폰 번호를 입력받고 9번 문제와 마찬가지로 두 가지 조건으로 휴대폰을 검사한다.
이번에는 반대로 13자리가 아니거나 "-"가 두 개가 아닐 경우 false를 리턴한다. 두 가지 조건을 모두 충족했을 경우 true를 리턴한다.
phoneNum
이 잘못된 휴대폰 번호이므로 phoneNumCheck()
의 첫 번째 조건에서 false가 리턴되므로 잘못된 휴대폰 번호!!
가 출력된다.
void main() {
var password = '1234';
if (password.length >= 8) {
print('비밀번화 확인 완료 ㅎㅎ');
} else {
print('비밀번호는 최소 8자 이상을 입력해 주세요');
}
}
password.length
를 사용해 길이를 비교했다. 패스워드의 길이가 4자리 이므로 비밀번호는 최소 8자 이상을 입력해 주세요
가 출력된다.
passwordValidator(String pw) {
if (pw.length < 8) {
return false;
}
return true;
}
void main() {
var password = '1234';
if (passwordValidator(password)) {
print('비밀번화 확인 완료 ㅎㅎ');
} else {
print('비밀번호는 최소 8자 이상을 입력해 주세요');
}
}
passwordValidator()
함수에서 비밀번호를 매개변수로 전달 받고, 이 값이 8보다 작으면 false를 리턴하고 그렇지 않으면 true를 리턴한다.
함수를 호출했을 때 password
가 4자리이기 때문에 false가 리턴되어 비밀번호는 최소 8자 이상을 입력해 주세요
가 출력된다.
Dart에는 여러가지 제어문이 존재한다. 가장 기본적인 제어문 중 하나는 1번에서 연습한 if문이다. 이와 비슷한 문법 중에서 Switch Case문이 있다.
Switch Case문도 if문과 마찬가지로 조건문이다. Switch문의 형태는 아래와 같다.
switch (변수명){
case 값A :
//값이 A일 때 실행할 명령문;
break;
case 값B :
//값이 B일 때 실행할 명령문;
break;
case 값C :
//값이 C일 때 실행할 명령문;
break;
case 값D :
//값이 D일 때 실행할 명령문;
break;
default :
//위의 값이 모두 아닐때 실행할 명령문;
}
위의 코드에서 변수명은 값을 검사할 변수를 넣고 case문에 있는 값과 일치하면 해당 블록의 명령문이 실행된다. case문의 끝에는 break를 꼭 작성해야 한다.
일치하는 값이 존재하지 않는다면 default
블록의 명령문이 실행된다.
Switch Case문을 활용하여 아래와 같은 예시 코드를 작성해 보았다.
void main() {
String favoriteFood = "kimbap";
switch (favoriteFood){
case 'kimbap' :
print('I Love kimbap');
break;
case 'beer' :
print('I Love beer');
break;
case 'ramen' :
print('I Love ramen');
break;
case 'bread' :
print('I Love bread');
break;
default :
print('nothing');
}
}
favoriteFood
에 "kimbap"이 저장되어 있기 때문에 이에 맞는 case의 명령문이 출력되었다.
Swtich문과 if문은 기본적으로 성격이 같다. 주어진 조건이 성립할 때, 기능이 수행되기 때문이다.
하지만 Switch문은 if else if... 처럼 다중 조건을 사용하기에는 약간의 불편함이 있다. 대신 Switch문은 if문 보다 속도가 빠르다.
예시로는 우선 아래와 같은 if문이 있다고 생각해 보자
void main() {
int num = 20;
if (num % 4 == 0) {
print('num은 4의 배수');
} else if (num % 3 == 0) {
print('num은 3의 배수');
} else {
print('알 수 없음');
}
}
if문은 위의 예시처럼 4로 나눈 나머지의 값, 3으로 나눈 나머지의 값 등의 여러 값으로 조건을 비교할 수 있지만 Switch문은 4로 나눈 나머지 값 하나의 결과 값을 가지고 비교할 수 있다.
따라서 하나의 결과 값을 가지고 조건을 비교한다면 속도가 좀 더 빠른 Switch문을 사용하는 것이 좋을 것 같다. (개인적으로는 Switch문이 가독성도 더 좋은 것 같은 느낌?) 하지만 여러 결과 값을 비교한다면 if문을 사용하는 것이 좋다.
아래와 같은 예시의 화면을 만들고자 한다.
요구사항
1. Sun, Moon, Star라는 값이 있으며, 오른쪽의 버튼을 눌렀을 때, 스위칭이 각각 될 수 있도록 함.
2. 이 때 스위칭이란, 활성화 여부를 뜻하며 불이 들어와 있을 땐 끄고, 꺼져있을 땐 켜는 것을 뜻함.
3. FAB를 클릭하면 모든 활성화되어있는 아이콘이 비활성화됨.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// root Widget
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool isSunClicked = false; //태양 버튼 클릭 확인
bool isMoonClicked = false; //달 버튼 클릭 확인
bool isStarClicked = false; //별 버튼 클릭 확인
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
children: [
//태양 타일
ListTile(
title: Text('Sun'),
leading: Icon(
color: isSunClicked ? Colors.red : Colors.grey,
Icons.light_mode,
),
trailing: IconButton(
onPressed: () => setState(() {
isSunClicked = !isSunClicked;
}),
icon: Icon(Icons.play_arrow),
),
),
//달 타일
ListTile(
title: Text('Moon'),
leading: Icon(
color: isMoonClicked ? Colors.yellow : Colors.grey,
Icons.nightlight_round,
),
trailing: IconButton(
onPressed: () => setState(() {
isMoonClicked = !isMoonClicked;
}),
icon: Icon(Icons.play_arrow),
),
),
//별 타일
ListTile(
title: Text('Star'),
leading: Icon(
color: isStarClicked ? Colors.yellow : Colors.grey,
Icons.star,
),
trailing: IconButton(
onPressed: () => setState(() {
isStarClicked = !isStarClicked;
}),
icon: Icon(Icons.play_arrow),
),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
isSunClicked = false;
isMoonClicked = false;
isStarClicked = false;
});
},
child: Icon(Icons.refresh),
),
);
}
}
우선 MyHomePage
에 각 타일의 클릭 여부를 확인할 세 가지 변수를 선언했다.(isSunClicked
, isMoonClicked
, isStarClicked
)
아이콘을 포함한 3개의 리스트타일을 SafeArea
와 Column
으로 구성했다.
각 타일은 ListTile
로 만들었고, leading
에서 아이콘 위젯을 넣었다. 이 아이콘 위젯의 색상을 각 타일에 맞는 boolean 값에 따라 색상이 변경되도록 했다.
trailing
에서는 IconButton
위젯을 사용해 onPressed
이벤트를 구현했는데 setState
메소드를 사용해서 클릭체크 boolean 값을 변경해 주었다.
FAB은 onPressed
이벤트에서 setState
메소드를 사용해 모든 체크 boolean 값을 false로 변경했다.
3번에서 작성한 코드에 추가하여 TextField
를 만들고 각 아이콘을 입력했을 때 해당 아이콘에 색이 켜지도록 만들어 보았다. 아래는 예시 결과이다.
요구사항
1. 아이콘의 색이 켜졌을 땐 끄고, 꺼져있을 때는 켜는 시스템을 제작함.
2. “태양” 입력 후 “엔터(혹은 제출)”하였을 때, 태양 아이콘의 색상이 스위칭이 되도록 함.
3. “달” 입력 후 “엔터(혹은 제출)”하였을 때, 달 아이콘의 색상이 스위칭이 되도록 함.
4. “별” 입력 후 “엔터(혹은 제출)”하였을 때, 별 아이콘의 색상이 스위칭이 되도록 함.
5. FAB를 클릭하면 모든 활성화되어있는 아이콘이 비활성화됨.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// root Widget
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool isSunClicked = false; //태양 버튼 클릭 확인
bool isMoonClicked = false; //달 버튼 클릭 확인
bool isStarClicked = false; //별 버튼 클릭 확인
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
children: [
//태양 타일
ListTile(
title: Text('Sun'),
leading: Icon(
color: isSunClicked ? Colors.red : Colors.grey,
Icons.light_mode,
),
trailing: IconButton(
onPressed: () => setState(() {
isSunClicked = !isSunClicked;
}),
icon: Icon(Icons.play_arrow),
),
),
//달 타일
ListTile(
title: Text('Moon'),
leading: Icon(
color: isMoonClicked ? Colors.yellow : Colors.grey,
Icons.nightlight_round,
),
trailing: IconButton(
onPressed: () => setState(() {
isMoonClicked = !isMoonClicked;
}),
icon: Icon(Icons.play_arrow),
),
),
//별 타일
ListTile(
title: Text('Star'),
leading: Icon(
color: isStarClicked ? Colors.yellow : Colors.grey,
Icons.star,
),
trailing: IconButton(
onPressed: () => setState(() {
isStarClicked = !isStarClicked;
}),
icon: Icon(Icons.play_arrow),
),
),
TextField(
decoration: InputDecoration(
hintText: '키고 끄고싶은 아이콘을 입력하세요.',
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(4.0)),
),
),
onSubmitted: (value) {
setState(() {
switch (value) {
case '태양':
isSunClicked = !isSunClicked;
break;
case '달':
isMoonClicked = !isMoonClicked;
break;
case '별':
isStarClicked = !isStarClicked;
break;
default:
print('잘못된 입력 단어!');
}
});
},
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
isSunClicked = false;
isMoonClicked = false;
isStarClicked = false;
});
},
child: Icon(Icons.refresh),
),
);
}
}
별 리스트타일 아래에 TextField
를 만들고 decoration
속성에서 hintText
와 테두리 선을 적용했다.
onSubmitted
이벤트에 Switch문을 사용하여 전달된 값에 따라서 맞는 체크 boolean 값이 true 또는 false로 변경되도록 작성했다.
10일차가 시작되었다. 후기도 매일 쓰다보니 무슨말을 써야될지 모르겠다. ㅋㅋㅋㅋ 이번에는 if와 같은 조건문을 사용했는데 다른 언어와 다른점은 없어서 어렵지 않았다. 조건문을 쓰고 StatefulWidet을 쓰다보니 처음에 정적인 화면들과 다르게 사용자에 입력에 따라 화면이 변화하는 UI가 만들어진다. ㅎㅎ 아 본문에서 까먹은 내용이 있는데 위젯에서 child에 if문이 안써지는 이유는 삼항 연산자는 식(expresson) 이지만 if문은 문(statement) 이기 때문에 사용이 불가능하다고 한다. 그렇구나....😮 그나저나 삼항 연산자는 정말 편하고 좋은거 같다. ㅎㅎ