Vintage appMaker의 Tech Blog

[Flutter] custom Dialog에서 Dialog 호출시 주의점. - ShowModalBottomSheet 본문

Source code or Tip/Flutter & Dart

[Flutter] custom Dialog에서 Dialog 호출시 주의점. - ShowModalBottomSheet

VintageappMaker 2022. 10. 2. 18:54

Custom Dialog나 Modal Dialog에서 버튼을 선택하고 다시 Dialog를 호출하려고 하다보면 반응하지 않을 때가 있다. 이 때는  호출하기 전에, Navigator.of(context).pop()을 먼저 해주고 나서 실행해야 재대로 된 결과를 얻을 수 있다. 

 

 

 

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  final String title;

  const MyHomePage({
    Key? key,
    required this.title,
  }) : super(key: key);

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Text(
              'Custom Dialog 테스트',
            )
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          showBottomSelect2(
              context: context,
              titles: <String>["내용수정", "삭제"],
              onSelect: (s) {
                if (s == "내용수정") {
                } else {
                  showDeleteAskDialog(
                      context: context,
                      title: "테스트",
                      desc: "테스트",
                      onCancel: () {},
                      onDelete: () {});
                }
              });
        },
        child: const Icon(Icons.add),
      ),
    );
  }
}

// 삭제 다이알로그
void showDeleteAskDialog(
    {required BuildContext context,
    required String title,
    required String desc,
    required Function onCancel,
    required Function onDelete}) {
  showDialog(
      context: context,
      builder: (context) {
        return Dialog(
          elevation: 0,
          backgroundColor: Color(0xffd6d5d6),
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(14.0),
          ),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              SizedBox(height: 20),
              Text(
                "${title}",
                style: TextStyle(
                  fontSize: 17.0,
                  fontWeight: FontWeight.bold,
                ),
              ),
              SizedBox(height: 9),
              Text(
                "${desc}",
                style: TextStyle(fontSize: 13, color: Color(0xff696969)),
                textAlign: TextAlign.center,
              ),
              SizedBox(height: 11),
              Divider(
                color: Color(0xFFbbbbbc),
                height: 1,
              ),
              Container(
                padding: EdgeInsets.only(top: 13, bottom: 10),
                width: MediaQuery.of(context).size.width,
                height: 45,
                child: InkWell(
                  highlightColor: Colors.grey[200],
                  onTap: () {
                    onDelete();
                    Navigator.of(context).pop();
                  },
                  child: Center(
                    child: Text(
                      "삭제",
                      style: TextStyle(
                        fontSize: 18.0,
                        color: Colors.red,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                  ),
                ),
              ),
              Divider(
                color: Color(0xFFbbbbbc),
                height: 1,
              ),
              Container(
                width: MediaQuery.of(context).size.width,
                padding: EdgeInsets.only(top: 13, bottom: 10),
                height: 45,
                child: InkWell(
                  borderRadius: BorderRadius.only(
                    bottomLeft: Radius.circular(15.0),
                    bottomRight: Radius.circular(15.0),
                  ),
                  onTap: () {
                    onCancel();
                    Navigator.of(context).pop();
                  },
                  child: Center(
                    child: Text(
                      "취소",
                      style: TextStyle(
                        fontSize: 18.0,
                        fontWeight: FontWeight.normal,
                      ),
                    ),
                  ),
                ),
              ),
            ],
          ),
        );
      });
}

// 하단메뉴 2 - 타이틀, 설명 X
void showBottomSelect2(
    {required BuildContext context,
    required List<String> titles,
    required Function onSelect}) {
  Widget buildBar(String title) {
    return GestureDetector(
      onTap: () {
        // 매우중요: 논리적으로 반대일 것 같은데, pop부터 하지않으면
        // context를 가지고 하는 작업은 아무 반응이 없게된다.

        Navigator.of(context).pop();
        onSelect(title);
      },
      child: Container(
          width: double.infinity,
          height: 58,
          child: Column(
            children: [
              Container(
                padding: EdgeInsets.only(top: 15, bottom: 13),
                child: Text(
                  title,
                  style: TextStyle(fontSize: 20, color: Color(0xff007AFF)),
                  textAlign: TextAlign.center,
                ),
              ),
            ],
          )),
    );
  }

  Widget buildCancelBar() {
    return GestureDetector(
      onTap: () {
        Navigator.of(context).pop();
      },
      child: Container(
          color: Colors.white,
          width: double.infinity,
          height: 56,
          child: Column(
            children: [
              Container(
                padding: EdgeInsets.only(top: 15, bottom: 13),
                child: Text(
                  "Cancel",
                  style: TextStyle(fontSize: 20, color: Color(0xff007AFF)),
                  textAlign: TextAlign.center,
                ),
              ),
            ],
          )),
    );
  }

  var lst = <Widget>[];
  for (var i = 0; i < titles.length; i++) {
    if (i != 0) {
      lst.add(Divider(
        color: Color(0xFFbbbbbc),
        height: 1,
      ));
    }
    lst.add(buildBar(titles[i]));
  }
  lst.add(buildCancelBar());

  showModalBottomSheet(
    context: context,
    backgroundColor: Colors.transparent,
    builder: (context) {
      return Container(
        padding: EdgeInsets.only(left: 8, right: 8),
        child: Container(
          decoration: BoxDecoration(
            color: Color(0xffd6d5d6),
            borderRadius: BorderRadius.all(Radius.circular(14)),
          ),
          child: SingleChildScrollView(
            child: Expanded(
              flex: 1,
              child: Container(
                child: Wrap(
                  children: lst,
                ),
              ),
            ),
          ),
        ),
      );
    },
  );
}

 

Comments