안녕하세요 독학코딩입니다. 오늘은 앱을 개발할 때 정말 많이 사용하는 눌러서 열기 기능에 대해서 배워보겠습니다. 위젯 이름은 ExpansionPanel인데 한국어로는 정확한 번역이 있는지 모르겠네요. 직역으로는 확장 패널인데 눈으로 보시면 익숙하실 겁니다.
Flutter ExpansionPanel
class FirstRoute extends StatefulWidget {
const FirstRoute({Key? key}) : super(key: key);
@override
State<FirstRoute> createState() => _FirstRouteState();
}
class _FirstRouteState extends State<FirstRoute> {
bool _expanded = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('App Bar'),
),
body: SingleChildScrollView(
child: ExpansionPanelList(
children: [
ExpansionPanel(
headerBuilder: (context, isExpanded) {
return Text("확장패널 헤더");
},
body: Text("확장패널 바디"),
isExpanded: _expanded,
),
ExpansionPanel(
headerBuilder: (context, isExpanded) {
return Text("확장패널 헤더");
},
body: Text("확장패널 바디"),
isExpanded: _expanded,
),
],
expansionCallback: (panelIndex, isExpanded) {
setState(() {
_expanded = !_expanded;
});
},
),
),
);
}
}
위가 가장 기본적인 ExpansionPanel입니다. 일반적으로는 여러개의 ExpansionPanel를 사용하기 때문에 ExpansionPanelList를 사용합니다. 그리고 위젯 이름 그대로 expansion, 즉 확장되었다가 축소되었다 하기 때문에 유동적인 화면을 위해서 ScrollView를 사용하는 게 일반적입니다. 여기서는 SingleChildScrollView를 사용하였습니다.
위 코드를 복사해서 실행해보셨다면 아시겠지만, 확장패널의 화살표를 누르면 1개의 패널만 열리는 게 아니라 2개의 패널이 전부 다 열리는 걸 확인하실 수 있으실 겁니다. 이는 _expanded를 두 개의 패널이 함께 사용해서 그런데요. 어떻게 수정해야 되는지 알려드리겠습니다.
만약 ExpansionPanel을 많이 사용하지 않거나 다이내믹하게 생성할게 아니라면 단순한 방법이 있습니다.
bool _expanded1 = false;
bool _expanded2 = false;
단순히 _expanded를 필요한 만큼 작성하시고 각각의 ExpansionPanel에 배정해주면 됩니다. 그리고 expansionCallback을 아래와 같이 변경해주시면 됩니다.
expansionCallback: (panelIndex, isExpanded) {
setState(() {
if (panelIndex == 0) {
_expanded1 = !_expanded1;
}
if (panelIndex == 1) {
_expanded2 = !_expanded2;
}
});
},
하지만 보통은 이런 방법으로 만들지는 않으실 겁니다. 대부분 다이내믹하게 ExpansionPanel을 만들어야 하는 경우가 더 많으니깐요.
Futter Dynamic ExpansionPanel
Dynamic이라는건 다른 게 아닙니다. ExpansionPanel을 한 번에 여러 개를 만드는 것입니다.
class FirstRoute extends StatefulWidget {
const FirstRoute({Key? key}) : super(key: key);
@override
State<FirstRoute> createState() => _FirstRouteState();
}
class _FirstRouteState extends State<FirstRoute> {
late List<Item> _items;
@override
void initState() {
super.initState();
setState(() {
_items = _generateItems();
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("ExpansionPanel"),
),
body: SingleChildScrollView(
child: ExpansionPanelList(
expansionCallback: (int index, bool isExpanded) {
setState(() {
_items[index].isExpanded = !isExpanded;
});
},
children: _items.map((item) => _buildExpansionPanel(item))
.toList(),
),
),
);
}
List<Item> _generateItems() {
return List.generate(20, (int index) {
return Item(
id: index,
name: '확장패널 헤더 $index',
description: '확장 패널 바디 $index',
);
});
}
ExpansionPanel _buildExpansionPanel(Item item) {
return ExpansionPanel(
isExpanded: item.isExpanded,
headerBuilder: (BuildContext context, bool isExpanded) {
return Text(item.name);
},
body: Text(item.description),
);
}
}
class Item {
bool isExpanded;
var id;
String name;
String description;
Item({
this.isExpanded = false,
required this.id,
required this.name,
required this.description,
});
}
코드가 조금 길지만, 위가 가장 기본적인 예시입니다. 하나하나 설명해드리겠습니다. 하나하나 설명해드리지는 않겠습니다. 차근차근 살펴보시면 이해되실 겁니다.
Flutter ExpansionPanel 옵션
ExpansionPanelList(
animationDuration: const Duration(seconds: 2),
expandedHeaderPadding: EdgeInsets.all(10),
dividerColor: Colors.red,
)
animationDuration은 ExpansionPanel이 펼쳐지고 접히는 시간을 설정합니다.
expandedHeaderPadding은 ExpansionPanel을 펼쳤을 때 Header의 padding을 설정합니다.
dividerColor는 각각의 ExpansionPanel 사이의 나눔선 색깔입니다.
ExpansionPanel(
backgroundColor: Colors.lightBlueAccent,
canTapOnHeader: true,
)
backgroundColor는 ExpansionPanel의 색을 설정합니다.
canTapOnHeader는 ExpansionPanel의 화살표 뿐만 아니라 header자체를 눌러도 펼치고 접기가 가능하게 합니다.
'Flutter > Flutter 위젯' 카테고리의 다른 글
Flutter - PhysicalModel, BoxDecoration, 위젯 그림자 넣기 (0) | 2022.05.03 |
---|---|
Flutter - RotatedBox, Transform.rotate, AnimatedBuilder, 위젯 회전하기 (0) | 2022.04.30 |
Flutter - Theme, ThemeData, 테마 바꾸기 (0) | 2022.04.19 |
Flutter - RefreshIndicator, Pull to Refresh, 당겨서 새로고침 (0) | 2022.04.16 |
Flutter - Inkwell, GestureDetector, 터치 클릭 인식 (0) | 2022.04.12 |
댓글