Search

κ²Œμ‹œνŒ μ•±

κ²Œμ‹œνŒ μ•±

β€’
ν”„λ‘œμ νŠΈ ꡬ쑰
β—¦
ν΄λΌμ΄μ–ΈνŠΈ
β—¦
μ„œλ²„
β€’
μ½”λ“œ
β—¦
board.dart
β—¦
main.dart
β—¦
main_screen.dart
β—¦
list_screen.dart
β—¦
read_screen.dart
β—¦
insert_screen.dart
β—¦
update_screen.dart

ν”„λ‘œμ νŠΈ ꡬ쑰

β€’
ν΄λΌμ΄μ–ΈνŠΈ
β€’
μ„œλ²„

ν΄λΌμ΄μ–ΈνŠΈ

Flutter - board_app

πŸ“ board_app β”œβ”€β”€ πŸ“ android β”œβ”€β”€ πŸ“ ios β”œβ”€β”€ πŸ“ build β”œβ”€β”€ πŸ“ lib β”‚ β”œβ”€β”€ πŸ“ models β”‚ β”‚ └── πŸ“„ board.dart β”‚ β”œβ”€β”€ πŸ“ screen β”‚ β”‚ β”œβ”€β”€ πŸ“ board β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ insert_screen.dart β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ list_screen.dart β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“„ read_screen.dart β”‚ β”‚ β”‚ └── πŸ“„ update_screen.dart β”‚ β”‚ └── πŸ“„ main_screen.dart β”‚ └── πŸ“„ main.dart β”œβ”€β”€ πŸ“ test β”œβ”€β”€ πŸ“„ pubspec.yaml β”œβ”€β”€ πŸ“„ pubspec.lock └── πŸ“„ README.md
Dart
볡사

μ„œλ²„

SpringBoot - board

board.war

server.zip
23570.1KB

μ„œλ²„ μ‹€ν–‰ν•˜κΈ°

java -jar board.war
Bash
볡사

μ½”λ“œ

β€’
board.dart
β€’
main.dart
β€’
main_screen.dart
β€’
list_screen.dart
β€’
read_screen.dart
β€’
insert_screen.dart
β€’
update_screen.dart

board.dart

class Board { int? no; String? title; String? writer; String? content; DateTime? regDate; DateTime? updDate; Board({ required this.no, required this.title, required this.writer, required this.content, this.regDate, this.updDate }); }
Dart
볡사

main.dart

import 'package:flutter/material.dart'; import 'package:http_app/main_screen.dart'; import 'package:http_app/screen/board/insert_screen.dart'; import 'package:http_app/screen/board/list_screen.dart'; import 'package:http_app/screen/board/read_screen.dart'; import 'package:http_app/screen/board/update_screen.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, title: 'Flutter Demo', theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), useMaterial3: true, ), initialRoute: '/main', routes: { '/main' : (context) => const MainScreen(), '/board/list' : (context) => const ListScreen(), '/board/read' : (context) => const ReadScreen(), '/board/insert' : (context) => const InsertScreen(), '/board/update' : (context) => const UpdateScreen(), }, ); } }
Dart
볡사

main_screen.dart

import 'package:flutter/material.dart'; class MainScreen extends StatefulWidget { const MainScreen({super.key}); State<MainScreen> createState() => _MainScreenState(); } class _MainScreenState extends State<MainScreen> { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("메인 ν™”λ©΄"), ), body: Center( child: ElevatedButton( onPressed: () { Navigator.pushNamed(context, "/board/list"); }, child: Text("κ²Œμ‹œκΈ€ λͺ©λ‘"), style: ElevatedButton.styleFrom( backgroundColor: Colors.blueAccent, foregroundColor: Colors.white, ), ), ), ); } }
Dart
볡사

list_screen.dart

import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:http_app/models/board.dart'; import 'package:http/http.dart' as http; class ListScreen extends StatefulWidget { const ListScreen({super.key}); State<ListScreen> createState() => _ListScreenState(); } class _ListScreenState extends State<ListScreen> { List<Board> _boardList = []; void initState() { super.initState(); getBoardList().then((result) { setState(() { _boardList = result; }); }); } // 🌞 κ²Œμ‹œκΈ€ λͺ©λ‘ 데이터 μš”μ²­ Future<List<Board>> getBoardList() async { var url = "http://10.0.2.2:8080/board"; List<Board> list = []; try { var response = await http.get(Uri.parse(url)); print("::::: response - body :::::"); print(response.body); // UTF-8 λ””μ½”λ”© var utf8Decoded = utf8.decode(response.bodyBytes); // JSON λ””μ½”λ”© var boardList = jsonDecode(utf8Decoded); for (var i = 0; i < boardList.length; i++) { list.add(Board( no: boardList[i]['no'], title: boardList[i]['title'], writer: boardList[i]['writer'], content: boardList[i]['content'], )); } print(list); } catch (e) { print(e); } return list; } final List<PopupMenuEntry<String>> _popupMenuItems = [ const PopupMenuItem<String>( value: 'update', child: Row( children: [ Icon(Icons.edit, color: Colors.black), // μ•„μ΄μ½˜ SizedBox(width: 8), // μ•„μ΄μ½˜κ³Ό ν…μŠ€νŠΈ 사이에 간격 μΆ”κ°€ Text('μˆ˜μ •ν•˜κΈ°'), // ν…μŠ€νŠΈ ], ), ), const PopupMenuItem<String>( value: 'delete', child: Row( children: [ Icon(Icons.delete, color: Colors.black), // μ•„μ΄μ½˜ SizedBox(width: 8), // μ•„μ΄μ½˜κ³Ό ν…μŠ€νŠΈ 사이에 간격 μΆ”κ°€ Text('μ‚­μ œν•˜κΈ°'), // ν…μŠ€νŠΈ ], ), ), ]; Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text("κ²Œμ‹œκΈ€ λͺ©λ‘")), body: Container( padding: const EdgeInsets.fromLTRB(5, 0, 5, 10), child: ListView.builder( itemCount: _boardList.length, itemBuilder: (context, index) { return GestureDetector( child: Card( child: ListTile( leading: Text(_boardList[index].no.toString() ?? '0'), title: Text(_boardList[index].title ?? "제λͺ©μ—†μŒ"), subtitle: Text(_boardList[index].writer ?? '-'), trailing: PopupMenuButton<String>( itemBuilder: (BuildContext context) { return _popupMenuItems; }, onSelected: (String value) async { if (value == 'update') { Navigator.pushNamed( context, "/board/update", arguments: _boardList[index].no, ); } else if (value == 'delete') { bool check = await _showDeleteConfirmDialog(); if (check) { deleteBoard(_boardList[index].no).then((result) { if (result) { setState(() { _boardList.removeAt(index); }); } }); } } }, ), ), ), onTap: () { Navigator.pushNamed( context, "/board/read", arguments: _boardList[index].no, ); }, ); }, ), ), floatingActionButton: FloatingActionButton( onPressed: () { Navigator.pushReplacementNamed(context, "/board/insert"); }, child: const Icon(Icons.create), ), ); } /// κ²Œμ‹œκΈ€ μ‚­μ œ μš”μ²­ Future<bool> deleteBoard(int? no) async { var url = "http://10.0.2.2:8080/board/$no"; try { var response = await http.delete(Uri.parse(url)); print("::::: response - statusCode :::::"); print(response.statusCode); if (response.statusCode == 200 || response.statusCode == 204) { // μ„±κ³΅μ μœΌλ‘œ μ‚­μ œλ¨ print("κ²Œμ‹œκΈ€ μ‚­μ œ 성곡"); return true; } else { // μ‹€νŒ¨ μ‹œ 였λ₯˜ λ©”μ‹œμ§€ throw Exception('Failed to delete board. Status code: ${response.statusCode}'); } } catch (e) { print(e); return false; } } /// μ‚­μ œ 확인 λ‹€μ΄μ–Όλ‘œκ·Έ ν‘œμ‹œ Future<bool> _showDeleteConfirmDialog() async { bool result = false; await showDialog( context: context, builder: (BuildContext context) { return AlertDialog( title: const Text('μ‚­μ œ 확인'), content: const Text('μ •λ§λ‘œ 이 κ²Œμ‹œκΈ€μ„ μ‚­μ œν•˜μ‹œκ² μŠ΅λ‹ˆκΉŒ?'), actions: [ TextButton( onPressed: () { Navigator.of(context).pop(false); // μ·¨μ†Œλ₯Ό ν΄λ¦­ν•˜λ©΄ false λ°˜ν™˜ }, child: const Text('μ·¨μ†Œ'), ), TextButton( onPressed: () { Navigator.of(context).pop(true); // μ‚­μ œλ₯Ό ν΄λ¦­ν•˜λ©΄ true λ°˜ν™˜ }, child: const Text('μ‚­μ œ'), ), ], ); }, ).then((value) { result = value ?? false; }); return result; } }
Dart
볡사

read_screen.dart

import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'package:http_app/models/board.dart'; class ReadScreen extends StatefulWidget { const ReadScreen({super.key}); State<ReadScreen> createState() => _ReadScreenState(); } class _ReadScreenState extends State<ReadScreen> { late int no; late Future<Board> _board; final List<PopupMenuEntry<String>> _popupMenuItems = [ const PopupMenuItem<String>( value: 'update', child: Row( children: [ Icon(Icons.edit, color: Colors.black), // μ•„μ΄μ½˜ SizedBox(width: 8), // μ•„μ΄μ½˜κ³Ό ν…μŠ€νŠΈ 사이에 간격 μΆ”κ°€ Text('μˆ˜μ •ν•˜κΈ°'), // ν…μŠ€νŠΈ ], ), ), const PopupMenuItem<String>( value: 'delete', child: Row( children: [ Icon(Icons.delete, color: Colors.black), // μ•„μ΄μ½˜ SizedBox(width: 8), // μ•„μ΄μ½˜κ³Ό ν…μŠ€νŠΈ 사이에 간격 μΆ”κ°€ Text('μ‚­μ œν•˜κΈ°'), // ν…μŠ€νŠΈ ], ), ), ]; void didChangeDependencies() { super.didChangeDependencies(); final arguments = ModalRoute.of(context)!.settings.arguments; if (arguments != null) { no = arguments as int; _board = getBoard(no); } else { // κΈ°λ³Έκ°’ μ„€μ • λ˜λŠ” μ˜ˆμ™Έ 처리 no = 0; _board = Future.error('No board number provided'); } } /// /// πŸ‘©β€πŸ’» κ²Œμ‹œκΈ€ 쑰회 μš”μ²­ /// Future<Board> getBoard(int no) async { var url = "http://10.0.2.2:8080/board/$no"; try { var response = await http.get(Uri.parse(url)); print("::::: response - body :::::"); print(response.body); // UTF-8 λ””μ½”λ”© var utf8Decoded = utf8.decode(response.bodyBytes); // JSON λ””μ½”λ”© var boardJson = jsonDecode(utf8Decoded); print(boardJson); return Board( no: boardJson['no'], title: boardJson['title'], writer: boardJson['writer'], content: boardJson['content'], ); } catch (e) { print(e); throw Exception('Failed to load board'); } } /// κ²Œμ‹œκΈ€ μ‚­μ œ μš”μ²­ Future<bool> deleteBoard(int no) async { var url = "http://10.0.2.2:8080/board/$no"; try { var response = await http.delete(Uri.parse(url)); print("::::: response - statusCode :::::"); print(response.statusCode); if (response.statusCode == 200 || response.statusCode == 204) { // μ„±κ³΅μ μœΌλ‘œ μ‚­μ œλ¨ print("κ²Œμ‹œκΈ€ μ‚­μ œ 성곡"); return true; } else { // μ‹€νŒ¨ μ‹œ 였λ₯˜ λ©”μ‹œμ§€ throw Exception('Failed to delete board. Status code: ${response.statusCode}'); } } catch (e) { print(e); return false; } } /// /// ❓ μ‚­μ œ 확인 /// Future<bool> _showDeleteConfirmDialog() async { bool result = false; await showDialog( context: context, builder: (BuildContext context) { return AlertDialog( title: Text('μ‚­μ œ 확인'), content: Text('μ •λ§λ‘œ 이 κ²Œμ‹œκΈ€μ„ μ‚­μ œν•˜μ‹œκ² μŠ΅λ‹ˆκΉŒ?'), actions: [ TextButton( onPressed: () { Navigator.of(context).pop(false); // μ·¨μ†Œλ₯Ό ν΄λ¦­ν•˜λ©΄ false λ°˜ν™˜ }, child: Text('μ·¨μ†Œ'), ), TextButton( onPressed: () { Navigator.of(context).pop(true); // μ‚­μ œλ₯Ό ν΄λ¦­ν•˜λ©΄ true λ°˜ν™˜ }, child: Text('μ‚­μ œ'), ), ], ); }, ).then((value) { // λ‹€μ΄μ–Όλ‘œκ·Έ κ²°κ³Όλ₯Ό result에 μ €μž₯ result = value ?? false; }); return result; } Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text("κ²Œμ‹œκΈ€ 쑰회"), actions: [ PopupMenuButton( itemBuilder: (BuildContext context) { return _popupMenuItems; }, icon: const Icon(Icons.more_vert), onSelected: (String value) async { if (value == 'update') { Navigator.pushReplacementNamed(context, "/board/update", arguments: no,); } else if (value == 'delete') { bool check = await _showDeleteConfirmDialog(); if( check ) { deleteBoard(no).then((result) { if( result ) { Navigator.pop(context); Navigator.pushReplacementNamed(context, "/board/list"); } }); } } }, ) ], ), body: FutureBuilder<Board>( future: _board, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } else if (snapshot.hasError) { return Center(child: Text('Error: ${snapshot.error}')); } else if (!snapshot.hasData) { return const Center(child: Text('No data found')); } else { var board = snapshot.data!; return Padding( padding: const EdgeInsets.fromLTRB(5, 0, 5, 10), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Card( child: ListTile( leading: const Icon(Icons.article), title: Text(board.title ?? '제λͺ©'), ), ), Card( child: ListTile( leading: const Icon(Icons.person), title: Text(board.writer ?? 'μž‘μ„±μž'), ), ), const SizedBox(height: 10.0,), Container( margin: const EdgeInsets.symmetric(horizontal: 4.0), padding: const EdgeInsets.all(12.0), width: double.infinity, height: 320.0, decoration: BoxDecoration( color: Theme.of(context).scaffoldBackgroundColor, boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.3), // 그림자의 색상과 투λͺ…도 spreadRadius: 2, // 그림자의 ν™•μ‚° 정도 blurRadius: 8, // 그림자의 흐림 정도 offset: const Offset(4, 4), // 그림자의 μœ„μΉ˜ (x, y) ), ], borderRadius: BorderRadius.circular(8), // μ˜΅μ…˜: λͺ¨μ„œλ¦¬ λ‘₯κΈ€κΈ° ), child: SingleChildScrollView( child: Text(board.content ?? 'λ‚΄μš©') ) ), ] ), ); } }, ), ); } }
Dart
볡사

insert_screen.dart

import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; class InsertScreen extends StatefulWidget { const InsertScreen({super.key}); State<InsertScreen> createState() => _InsertScreenState(); } class _InsertScreenState extends State<InsertScreen> { final _formKey = GlobalKey<FormState>(); final TextEditingController _titleController = TextEditingController(); final TextEditingController _writerController = TextEditingController(); final TextEditingController _contentController = TextEditingController(); Future<void> insert() async { if (_formKey.currentState!.validate()) { var url = "http://10.0.2.2:8080/board"; try { var response = await http.post( Uri.parse(url), headers: {"Content-Type": "application/json"}, body: jsonEncode({ 'title': _titleController.text, 'writer': _writerController.text, 'content': _contentController.text, }), ); print("::::: response - body :::::"); print(response.body); if (response.statusCode == 200 || response.statusCode == 201) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('κ²Œμ‹œκΈ€ 등둝 성곡!'), backgroundColor: Colors.blueAccent, ), ); Navigator.pushReplacementNamed(context, "/board/list"); } else { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('κ²Œμ‹œκΈ€ 등둝 μ‹€νŒ¨...'), backgroundColor: Colors.redAccent, ), ); } } catch (e) { print(e); ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('μ—λŸ¬: $e')), ); } } } Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text("κ²Œμ‹œκΈ€ μž‘μ„±"), ), body: Padding( padding: const EdgeInsets.all(16.0), child: Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ TextFormField( controller: _titleController, decoration: const InputDecoration(labelText: '제λͺ©'), validator: (value) { if (value == null || value.isEmpty) { return '제λͺ©μ„ μž…λ ₯ν•˜μ„Έμš”'; } return null; }, ), TextFormField( controller: _writerController, decoration: const InputDecoration(labelText: 'μž‘μ„±μž'), validator: (value) { if (value == null || value.isEmpty) { return 'μž‘μ„±μžλ₯Ό μž…λ ₯ν•˜μ„Έμš”'; } return null; }, ), TextFormField( controller: _contentController, decoration: const InputDecoration(labelText: 'λ‚΄μš©'), maxLines: 5, validator: (value) { if (value == null || value.isEmpty) { return 'λ‚΄μš©μ„ μž…λ ₯ν•˜μ„Έμš”'; } return null; }, ), ], ), ), ), bottomSheet: Container( height: 60, color: Colors.white, child: Center( child: ElevatedButton( onPressed: () { insert(); }, style: ElevatedButton.styleFrom( minimumSize: const Size(double.infinity, 50), // κ°€λ‘œ 100% λ²„νŠΌ backgroundColor: Colors.blueAccent, foregroundColor: Colors.white, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.zero, // ν…Œλ‘λ¦¬λ₯Ό λ‘₯글지 μ•Šκ²Œ μ„€μ • ), ), child: const Text('λ“±λ‘ν•˜κΈ°'), ), ), ), ); } }
Dart
볡사

update_screen.dart

import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; class UpdateScreen extends StatefulWidget { const UpdateScreen({super.key}); State<UpdateScreen> createState() => _UpdateScreenState(); } class _UpdateScreenState extends State<UpdateScreen> { final _formKey = GlobalKey<FormState>(); final TextEditingController _titleController = TextEditingController(); final TextEditingController _writerController = TextEditingController(); final TextEditingController _contentController = TextEditingController(); late int no; final List<PopupMenuEntry<String>> _popupMenuItems = [ const PopupMenuItem<String>( value: 'delete', child: Row( children: [ Icon(Icons.delete, color: Colors.black), // μ•„μ΄μ½˜ SizedBox(width: 8), // μ•„μ΄μ½˜κ³Ό ν…μŠ€νŠΈ 사이에 간격 μΆ”κ°€ Text('μ‚­μ œν•˜κΈ°'), // ν…μŠ€νŠΈ ], ), ), ]; void didChangeDependencies() { super.didChangeDependencies(); final arguments = ModalRoute.of(context)!.settings.arguments; if (arguments != null) { no = arguments as int; getBoard(no); // 이름 λ³€κ²½λœ λ©”μ„œλ“œ 호좜 } } /// /// πŸ‘©β€πŸ’» κ²Œμ‹œκΈ€ 쑰회 μš”μ²­ /// Future<void> getBoard(int no) async { var url = "http://10.0.2.2:8080/board/$no"; try { var response = await http.get(Uri.parse(url)); if (response.statusCode == 200) { var utf8Decoded = utf8.decode(response.bodyBytes); var boardJson = jsonDecode(utf8Decoded); _titleController.text = boardJson['title']; _writerController.text = boardJson['writer']; _contentController.text = boardJson['content']; } else { throw Exception('Failed to load board details'); } } catch (e) { print(e); } } /// κ²Œμ‹œκΈ€ μˆ˜μ • μš”μ²­ Future<void> updateBoard() async { if (_formKey.currentState!.validate()) { var url = "http://10.0.2.2:8080/board"; try { var response = await http.put( Uri.parse(url), headers: {"Content-Type": "application/json"}, body: jsonEncode({ 'no' : no, 'title': _titleController.text, 'writer': _writerController.text, 'content': _contentController.text, }), ); if (response.statusCode == 200 || response.statusCode == 204) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('κ²Œμ‹œκΈ€ μˆ˜μ • 성곡!'), backgroundColor: Colors.blueAccent, ), ); Navigator.pushReplacementNamed(context, "/board/list"); } else { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('κ²Œμ‹œκΈ€ μˆ˜μ • μ‹€νŒ¨...'), backgroundColor: Colors.redAccent, ), ); } } catch (e) { print(e); ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('μ—λŸ¬: $e')), ); } } } /// κ²Œμ‹œκΈ€ μ‚­μ œ μš”μ²­ Future<bool> deleteBoard(int no) async { var url = "http://10.0.2.2:8080/board/$no"; try { var response = await http.delete(Uri.parse(url)); print("::::: response - statusCode :::::"); print(response.statusCode); if (response.statusCode == 200 || response.statusCode == 204) { // μ„±κ³΅μ μœΌλ‘œ μ‚­μ œλ¨ print("κ²Œμ‹œκΈ€ μ‚­μ œ 성곡"); return true; } else { // μ‹€νŒ¨ μ‹œ 였λ₯˜ λ©”μ‹œμ§€ return false; } } catch (e) { print(e); return false; } } Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text("κ²Œμ‹œκΈ€ μˆ˜μ •"), actions: [ PopupMenuButton( itemBuilder: (BuildContext context) { return _popupMenuItems; }, icon: const Icon(Icons.more_vert), onSelected: (String value) async { if (value == 'delete') { bool check = await _showDeleteConfirmDialog(); if( check ) { deleteBoard(no).then((result) { if( result ) { Navigator.pop(context); Navigator.pushReplacementNamed(context, "/board/list"); } }); } } }, ) ], ), body: Padding( padding: const EdgeInsets.all(16.0), child: Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ TextFormField( controller: _titleController, decoration: const InputDecoration(labelText: '제λͺ©'), validator: (value) { if (value == null || value.isEmpty) { return '제λͺ©μ„ μž…λ ₯ν•˜μ„Έμš”'; } return null; }, ), TextFormField( controller: _writerController, decoration: const InputDecoration(labelText: 'μž‘μ„±μž'), validator: (value) { if (value == null || value.isEmpty) { return 'μž‘μ„±μžλ₯Ό μž…λ ₯ν•˜μ„Έμš”'; } return null; }, ), TextFormField( controller: _contentController, decoration: const InputDecoration(labelText: 'λ‚΄μš©'), maxLines: 5, validator: (value) { if (value == null || value.isEmpty) { return 'λ‚΄μš©μ„ μž…λ ₯ν•˜μ„Έμš”'; } return null; }, ), ], ), ), ), bottomSheet: Container( height: 60, color: Colors.white, child: Center( child: ElevatedButton( onPressed: () { updateBoard(); }, style: ElevatedButton.styleFrom( minimumSize: const Size(double.infinity, 50), // κ°€λ‘œ 100% λ²„νŠΌ backgroundColor: Colors.blueAccent, foregroundColor: Colors.white, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.zero, // ν…Œλ‘λ¦¬λ₯Ό λ‘₯글지 μ•Šκ²Œ μ„€μ • ), ), child: const Text('μˆ˜μ •ν•˜κΈ°'), ), ), ), ); } /// μ‚­μ œ 확인 λ‹€μ΄μ–Όλ‘œκ·Έ ν‘œμ‹œ λ©”μ„œλ“œ Future<bool> _showDeleteConfirmDialog() async { bool result = false; await showDialog( context: context, builder: (BuildContext context) { return AlertDialog( title: Text('μ‚­μ œ 확인'), content: Text('μ •λ§λ‘œ 이 κ²Œμ‹œκΈ€μ„ μ‚­μ œν•˜μ‹œκ² μŠ΅λ‹ˆκΉŒ?'), actions: [ TextButton( onPressed: () { Navigator.of(context).pop(false); // μ·¨μ†Œλ₯Ό ν΄λ¦­ν•˜λ©΄ false λ°˜ν™˜ }, child: Text('μ·¨μ†Œ'), ), TextButton( onPressed: () { Navigator.of(context).pop(true); // μ‚­μ œλ₯Ό ν΄λ¦­ν•˜λ©΄ true λ°˜ν™˜ }, child: Text('μ‚­μ œ'), ), ], ); }, ).then((value) { result = value ?? false; }); return result; } }
Dart
볡사