Search
Duplicate

Dismissible

Dismissible๋Š” ๋ฆฌ์ŠคํŠธ ์•„์ดํ…œ์„ ์ขŒ์šฐ๋กœ ์Šค์™€์ดํ”„ํ•ด์„œ ์‚ญ์ œ, ๋ณด๊ด€, ์™„๋ฃŒ ๊ฐ™์€ ์•ก์…˜์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” Flutter ์œ„์ ฏ์ž…๋‹ˆ๋‹ค.
โ€ข
child: ํ™”๋ฉด์— ๋ณด์ด๋Š” ์‹ค์ œ ์ฝ˜ํ…์ธ 
โ€ข
background / secondaryBackground: ์Šค์™€์ดํ”„ ์ค‘ ๋’ค์—์„œ ๋ณด์ด๋Š” ๋ฐฐ๊ฒฝ
โ€ข
direction: ์Šค์™€์ดํ”„ ๋ฐฉํ–ฅ ์ œํ•œ
โ€ข
confirmDismiss: ์‹ค์ œ๋กœ ์ œ๊ฑฐํ•˜๊ธฐ ์ „ ํ™•์ธ ๋‹ค์ด์–ผ๋กœ๊ทธ ๋“ฑ ์ฒ˜๋ฆฌ
โ€ข
onDismissed: ์Šค์™€์ดํ”„ ์™„๋ฃŒ ํ›„ ์‚ญ์ œ ์ฒ˜๋ฆฌ์™€ ์Šค๋‚ต๋ฐ” ํ‘œ์‹œ ๋“ฑ์— ์‚ฌ์šฉ

Dismissible ์œ„์ ฏ

์–ธ์ œ ์‚ฌ์šฉํ•˜๋Š”๊ฐ€

โ€ข
ํ•  ์ผ ๋ชฉ๋ก (Todo List)
โ€ข
์ด๋ฉ”์ผ ์•ฑ (์ฝ์Œ ์ฒ˜๋ฆฌ / ์‚ญ์ œ)
โ€ข
์ฑ„ํŒ… ๋ฆฌ์ŠคํŠธ (๋Œ€ํ™” ์‚ญ์ œ)
โ€ข
๊ฐค๋Ÿฌ๋ฆฌ ๋ฆฌ์ŠคํŠธ (์‚ฌ์ง„ ์ œ๊ฑฐ)
๋ฆฌ์ŠคํŠธ ๊ธฐ๋ฐ˜ UI์—์„œ๋Š” ๊ฑฐ์˜ ํ•„์ˆ˜ ํŒจํ„ด

๊ธฐ๋ณธ ๊ตฌ์กฐ

Dismissible( key: Key(item.id), // ๋ฐ˜๋“œ์‹œ ๊ณ ์œ ๊ฐ’ child: ListTile( title: Text(item.title), ), )
Dart
๋ณต์‚ฌ

ํ•ต์‹ฌ ์†์„ฑ ์ •๋ฆฌ

child

์‹ค์ œ ํ™”๋ฉด์— ๋ณด์ด๋Š” UI
child: ListTile(title: Text("ํ•  ์ผ"))
Dart
๋ณต์‚ฌ

background / secondaryBackground

์Šค์™€์ดํ”„ํ•  ๋•Œ ๋’ค์—์„œ ๋ณด์ด๋Š” UI
background: Container( color: Colors.red, alignment: Alignment.centerLeft, padding: EdgeInsets.only(left: 20), child: Icon(Icons.delete, color: Colors.white), ), secondaryBackground: Container( color: Colors.blue, alignment: Alignment.centerRight, padding: EdgeInsets.only(right: 20), child: Icon(Icons.archive, color: Colors.white), ),
Dart
๋ณต์‚ฌ
โ€ข
background ์™ผ์ชฝ โ†’ ์˜ค๋ฅธ์ชฝ ์Šค์™€์ดํ”„
โ€ข
secondaryBackground ์˜ค๋ฅธ์ชฝ โ†’ ์™ผ์ชฝ ์Šค์™€์ดํ”„

direction

์Šค์™€์ดํ”„ ๋ฐฉํ–ฅ ์ œํ•œ
direction: DismissDirection.horizontal
Dart
๋ณต์‚ฌ
์˜ต์…˜:
โ€ข
horizontal ์ขŒ์šฐ ๊ฐ€๋Šฅ
โ€ข
vertical ์œ„์•„๋ž˜ ๊ฐ€๋Šฅ
โ€ข
endToStart ์˜ค๋ฅธ์ชฝ โ†’ ์™ผ์ชฝ
โ€ข
startToEnd ์™ผ์ชฝ โ†’ ์˜ค๋ฅธ์ชฝ

confirmDismiss

์‚ญ์ œ ์ „์— ํ™•์ธ ( ์ค‘์š”)
confirmDismiss: (direction) async { return await showDialog( context: context, builder: (context) => AlertDialog( title: Text("์‚ญ์ œํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?"), actions: [ TextButton( onPressed: () => Navigator.pop(context, false), child: Text("์ทจ์†Œ"), ), TextButton( onPressed: () => Navigator.pop(context, true), child: Text("์‚ญ์ œ"), ), ], ), ); },
Dart
๋ณต์‚ฌ
์‹ค๋ฌด์—์„œ๋Š” ๊ฑฐ์˜ ํ•ญ์ƒ ์‚ฌ์šฉ (์‹ค์ˆ˜ ๋ฐฉ์ง€)

onDismissed

์‹ค์ œ ์‚ญ์ œ ์ฒ˜๋ฆฌ (ํ•ต์‹ฌ ๋กœ์ง)
onDismissed: (direction) { setState(() { items.removeAt(index); }); ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text("์‚ญ์ œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค")), ); },
Dart
๋ณต์‚ฌ

์ „์ฒด ์˜ˆ์ œ

ListView.builder( itemCount: items.length, itemBuilder: (context, index) { final item = items[index]; return Dismissible( key: Key(item.id), background: Container( color: Colors.red, alignment: Alignment.centerLeft, padding: EdgeInsets.only(left: 20), child: Icon(Icons.delete, color: Colors.white), ), secondaryBackground: Container( color: Colors.green, alignment: Alignment.centerRight, padding: EdgeInsets.only(right: 20), child: Icon(Icons.check, color: Colors.white), ), confirmDismiss: (direction) async { return await showDialog( context: context, builder: (context) => AlertDialog( title: Text("์ •๋ง ์‚ญ์ œํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?"), actions: [ TextButton( onPressed: () => Navigator.pop(context, false), child: Text("์ทจ์†Œ"), ), TextButton( onPressed: () => Navigator.pop(context, true), child: Text("์‚ญ์ œ"), ), ], ), ); }, onDismissed: (direction) { setState(() { items.removeAt(index); }); ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text("${item.title} ์‚ญ์ œ๋จ")), ); }, child: ListTile( title: Text(item.title), ), ); }, );
Dart
๋ณต์‚ฌ

TIP

1. key๋Š” ์ ˆ๋Œ€ ์ค‘๋ณต๋˜๋ฉด ์•ˆ๋จ

key: Key(item.id)
Dart
๋ณต์‚ฌ
index ์“ฐ๋ฉด ๋ฒ„๊ทธ ๋ฐœ์ƒ ๊ฐ€๋Šฅ

2. confirmDismiss ์—†์ด ์‚ญ์ œํ•˜๋ฉด UX ์•ˆ์ข‹์Œ

์‹ค์ˆ˜๋กœ ๋‚ ๋ฆผ

3. ์ƒํƒœ๊ด€๋ฆฌ๋ž‘ ๊ฐ™์ด ์“ฐ๋ฉด ๋” ๊ฐ•๋ ฅ

โ€ข
Provider
โ€ข
Riverpod
โ€ข
Bloc
์„œ๋ฒ„ ๋ฐ์ดํ„ฐ ์‚ญ์ œ๊นŒ์ง€ ์—ฐ๊ฒฐ ๊ฐ€๋Šฅ

4. ๋ฐฉํ–ฅ๋ณ„ ๋‹ค๋ฅธ ๊ธฐ๋Šฅ ๊ตฌํ˜„ ๊ฐ€๋Šฅ

onDismissed: (direction) { if (direction == DismissDirection.startToEnd) { // ์™„๋ฃŒ ์ฒ˜๋ฆฌ } else { // ์‚ญ์ œ ์ฒ˜๋ฆฌ } }
Dart
๋ณต์‚ฌ