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
볡사