이번에는 Key 에 대해서 알아보겠습니다.
개발환경 : 윈도우11, 안드로이드 스튜디오, flutter 3.0.1
소스코드 위치 - Release 03_global_key · mike-bskim/key_test · GitHub
초기 화면은 아래와 같습니다.
Key 는 우리가 생각없이 지나치지만 위젯을 이동/삭제할 경우 아주 중요한 핵심 포인트입니다.
Todo 리스트 처럼 일정 순서를 이동/삭제 등 변경할때 주로 사용된다.
Flutter 는 기본적으로 위젯의 타입으로 각자 구분하지만
동일한 위젯을 여러개 사용할때 구분할수 있는 포인트가 key 입니다.
Key 종류는 아래와 같은데, 여기서는 상위 3개에 대해서 알아보겠습니다.
- Unique key
- Value key
- Global key
- Object key
- Page storage key
Unique key 사용 예시 - floatingActionButton 클릭시 2개의 컨테이너가 서로 위치를 바꾼다
unique_key.dart
import 'package:flutter/material.dart';
import 'dart:math';
import 'package:fluttertoast/fluttertoast.dart';
class UniqueKeyTest extends StatefulWidget {
const UniqueKeyTest({Key? key}) : super(key: key);
@override
State<StatefulWidget> createState() => UniqueKeyTestState();
}
class UniqueKeyTestState extends State<UniqueKeyTest> {
// key 를 주지않으면 2개의 변경결과를 rendering 시 매칭하지 못한다
List<Widget> tiles = [
StatefulColorfulTile(
key: UniqueKey(),
),
StatefulColorfulTile(
key: UniqueKey(),
),
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: const Text('Unique Key'),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: tiles,
),
],
),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.double_arrow_rounded),
onPressed: () {
swapTiles();
flutterToast();
}),
);
}
// 첫째 배열을 제거해서 그것을 2번째 배열에 넣는다
void swapTiles() {
setState(() {
tiles.insert(1, tiles.removeAt(0));
});
}
}
class StatefulColorfulTile extends StatefulWidget {
const StatefulColorfulTile({Key? key}) : super(key: key);
@override
StatefulColorfulTileState createState() => StatefulColorfulTileState();
}
class StatefulColorfulTileState extends State<StatefulColorfulTile> {
Color myColor = getRandomColor();
@override
Widget build(BuildContext context) {
debugPrint('StatefulColorfulTile.key :${widget.key}');
return Container(
color: myColor,
child: const Padding(
padding: EdgeInsets.all(70.0),
),
);
}
}
getRandomColor() {
var r = Random();
return Color.fromARGB(255, r.nextInt(255), r.nextInt(255), r.nextInt(255));
}
void flutterToast() {
Fluttertoast.showToast(
msg: 'Color has been changed',
gravity: ToastGravity.BOTTOM,
backgroundColor: Colors.blue,
textColor: Colors.white,
toastLength: Toast.LENGTH_SHORT);
}
Value key 사용 예시 - 버튼 클릭시, 첫번째 텍스트필드가 삭제되며 입력값을 유지하는지 확인
value_key.dart
import 'package:flutter/material.dart';
class ValueKeyTest extends StatefulWidget {
const ValueKeyTest({Key? key}) : super(key: key);
@override
ValueKeyTestState createState() => ValueKeyTestState();
}
class ValueKeyTestState extends State<ValueKeyTest> {
bool emailField = true;
TextEditingController idController = TextEditingController();
TextEditingController pwController = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Value Key'),
centerTitle: true,
),
body: GestureDetector(
onTap: () {
FocusScope.of(context).unfocus();
},
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
if (emailField)
const TextField(
key: ValueKey(1),
// controller 를 사용하면 key 를 사용한 것과 동일한 결과임
// controller: idController,
decoration: InputDecoration(labelText: 'Enter "dice"'),
keyboardType: TextInputType.emailAddress,
),
const TextField(
key: ValueKey(2),
// controller 를 사용하면 key 를 사용한 것과 동일한 결과임
// controller: pwController,
decoration: InputDecoration(labelText: 'Enter Password'),
keyboardType: TextInputType.text,
),
const SizedBox(
height: 40.0,
),
ButtonTheme(
minWidth: 100.0,
height: 50.0,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
minimumSize: const Size(150, 50),
),
// color:
child: const Icon(
Icons.visibility_off,
color: Colors.white,
size: 35.0,
),
onPressed: () {
setState(() {
emailField = false;
});
},
),
),
],
),
),
),
);
}
}
Global key
키값은 전체 프로그램에서 유일한 값이어야 한다.
요소들을 유일하게 구분한다.
Context 등과 같은 다른 요소들과 연관된 Object 들에 접근할수 있어야 하고 상태(StatefulWidget 경우)에 접근할 수 있다
하위 속성중 하나인 currentState 을 이용하면 특정위젯의 하위 객체에 접근 가능함
Global key 사용 예시 - 상위 위젯(GlobalKeyTest)에서 하위 위젯(Counter)의 객체를 접근
global_key.dart
import 'package:flutter/material.dart';
class GlobalKeyTest extends StatefulWidget {
const GlobalKeyTest({Key? key}) : super(key: key);
@override
State<GlobalKeyTest> createState() => _GlobalKeyTestState();
}
class _GlobalKeyTestState extends State<GlobalKeyTest> {
// 다른 StatefulWidget 의 상태를 접근하기 위해서 GlobalKey 키를 이용해서 접근
final counterKey = GlobalKey<CounterState>();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Global key'),
),
body: Center(
child: Counter(
key: counterKey,
),
),
floatingActionButton: FloatingActionButton(
child: const Icon(
Icons.add,
color: Colors.white,
),
onPressed: () {
// 다른 StatefulWidget 의 상태를 접근하기 위해서 GlobalKey 키를 이용해서 접근
counterKey.currentState!.increment();
debugPrint(counterKey.currentState!.count.toString());
},
),
);
}
}
class Counter extends StatefulWidget {
const Counter({Key? key}) : super(key: key);
@override
CounterState createState() => CounterState();
}
class CounterState extends State<Counter> {
int count = 0;
void increment() {
setState(() {
count++;
});
// debugPrint(count.toString());
}
@override
Widget build(BuildContext context) {
return Center(
child: Text(
'Count number: $count',
style: const TextStyle(fontSize: 20.0),
),
);
}
}
[참고자료] 코딩셰프 -
https://www.youtube.com/watch?v=lQB6HjleLMs&list=PLQt_pzi-LLfoOpp3b-pnnLXgYpiFEftLB&index=20
'Flutter > 06 Basic' 카테고리의 다른 글
[Flutter] 안드로이드 스튜디오 설정 - 자동완성 기능 추가 (0) | 2022.08.18 |
---|---|
[Flutter] Firestore 구조 알아보기 (0) | 2022.08.12 |
[Flutter] Basic - ScaffoldMessenger (0) | 2022.04.14 |
[Flutter] Basic - Navigator (0) | 2022.04.14 |
[Flutter] Basic - BuildContext context (0) | 2022.04.10 |