스터디/Flutter+Dart

Flutter Alert Dialog, Progress, Auto Close

Dalmangyi 2019. 7. 30.

화면 개발 다음으로 중요한것이 사용자에게 상태를 알리거나 동작을 물어보는 용도로 많이 쓰는 알림 화면(Alert Dialog, Popup)입니다. 

물론 다른 방식도 많겠지만 쉽게 접근할 수 있는 Alert Dialog부터 시작해보겠습니다

 

 

 

 


 

 

Alert Dialog

출처 : developer.android.com

위쪽은 제목 영역(1), 중간에 내용 영역(2), 아래에 있는 액션 영역(3) 으로 구성되어 있습니다.

 

 

Flutter에서도 AlertDialog는 제목(Title), 내용(Body), 액션(Actions) 영역으로 구분됩니다 

AlertDialog(
	title: new Text("Alert Dialog title"),
	content: new Text("Alert Dialog body"),
	actions: <Widget>[
		new FlatButton(
			child: new Text("Close"),
		),
	],
);

이 세가지 영역 모두 필수가 아닙니다. 

제목과 내용은 무조건 텍스트, 액션도 무조건 버튼이 아닌 Widget을 받기 때문에 무엇으로든 변형할 수 있습니다

 

왼쪽 부터 - 메인화면, Full AlertDialog, Only Title, Only Body, Only Actions

 

이런 AlertDialog를 만들었으면 화면에 보여줘야 겠죠?

showDialog 라는 flutter의 기본 함수를 이용해서 출력합니다

void _showDialog() { 
    showDialog(
      context: context,
      builder: (BuildContext context) {
        // return object of type Dialog
        return AlertDialog(
          title: new Text("Alert Dialog title"),
          content: new Text("Alert Dialog body"),
          actions: <Widget>[ 
            new FlatButton(
              child: new Text("Close"),
              onPressed: () {
                Navigator.pop(context);
              },
            ),
          ],
        );
      },
    );
  }

닫을때는 onPressed 함수안에 'Navigator.pop(context)'을 구현하면 됩니다 

 

아이폰도 너무 잘됨. gif.

 

 

 

내용이 길때 Body 처리 

화면에 짤리는걸 막기 위해서 SingleChildScrollView(ScollView Widget)도 잊지마세요

  void _showDialog() { 
    showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: new Text("Alert Dialog title"),
          content: SingleChildScrollView(child:new Text("Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body Alert Dialog body ")),
          actions: <Widget>[ 
            new FlatButton(
              child: new Text("Close"),
              onPressed: () {
                Navigator.pop(context);
              },
            ),
          ],
        );
      },
    );
  }

 

긴 내용이 있는 body. gif

 

 

 

여백을 눌러도 닫히지 않게 만들기

기본적으로 Dialog는 여백을 누르면 Dialog가 Navigator.pop()함수를 실행한 것처럼 닫히도록 되어 있습니다 

아래 코드를 추가하면 여백을 눌러도 Dialog가 닫히지 않게 됩니다 

barrierDismissible: false

참 쉽죠? 혹시 모르니 풀 코드!

void _showDialog() { 
    showDialog(
      context: context,
      barrierDismissible: false,  
      builder: (BuildContext context) { 
        return AlertDialog(
          title: new Text("Alert Dialog title"),
          content: SingleChildScrollView(child:new Text("Alert Dialog body")),
          actions: <Widget>[ 
            new FlatButton(
              child: new Text("Close"),
              onPressed: () {
                Navigator.pop(context);
              },
            ),
          ],
        );
      },
    );
  }

여백을 눌러도 닫을 수 없는. gif.

 

 

모서리를 라운드 처리 하고 싶다면?

파라매터로 RoundedRectangleBorder를 추가하면 됩니다

이외에도 ShapeBorder가 모두 됩니다

shape: RoundedRectangleBorder(
	borderRadius: BorderRadius.circular(8.0)
)
  void _showDialog() { 
    showDialog(
      context: context,
      barrierDismissible: false, 
      builder: (BuildContext context) { 
        return AlertDialog(
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(8.0)
          ),
          title: new Text("Alert Dialog title"),
          content: SingleChildScrollView(child:new Text("Alert Dialog body")),
          actions: <Widget>[ 
            new FlatButton(
              child: new Text("Close"),
              onPressed: () {
                Navigator.pop(context);
              },
            ),
          ],
        );
      },
    );
  }

RoundedRectangleBorder 사용한 모습. gif.

 

 

 

로딩 다이얼로그 (Progress Dialog)

언제 끝날지 모르는 로딩이 있을때는 안드로이드에서는 주로 Progress Dialog 를 사용합니다

flutter에서는 찾아보니 기본적으로 제공하진 않고 있습니다 

왜냐하면 flutter는 Widget으로 모든것을 더하고 뺄 수 있으니까요!

물론 안드로이드도 아이폰도 커스텀으로 만들면 됩니다 하지만 플러터에서 개발하는건.. 정말이지 생각대로 금방됩니다

 

계속해서 동글 동글 도는 효과를 주기 위해선 CircularProgressIndicator가 필요합니다

new CircularProgressIndicator(
	valueColor: new AlwaysStoppedAnimation(Colors.blue),
	strokeWidth: 5.0
),

title과 action을 없애고 body에만 넣어봅니다

 

뭔가 원하던 모습이 아닌... gif

정사각형으로 이쁘게 나와주길 바랬지만 Indicator는 실망을 주고 맙니다ㅠㅠ..

크기를 다듬기 위해 SizedBox로 한번 감싸봅니다. SizedBox는 정렬이 되어야만 반영 되기 때문에 

Center Widget을 같이 사용하도록 합니다. 

 

Center, SizedBox를 이용한 모습. gif

그래도... 높이가 지멋대로 차지해버리네요 .. 

다시 높이를 위해 SizedBox로 감싸봅니다 

  void _showDialog() { 
    showDialog(
      context: context,
      builder: (BuildContext context) { 
        return AlertDialog(
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(8.0)
          ),
          content: SizedBox(
            height: 200,
            child: Center(
              child:SizedBox(
                child: 
                    new CircularProgressIndicator(
                      valueColor: new AlwaysStoppedAnimation(Colors.blue),
                      strokeWidth: 5.0
                    ),
                height: 50.0,
                width: 50.0,
              )
            ),
          ), 
        );
      },
    );
  }

정사각형으로 잘 보이는 gif.

드디여 Progress Dialog 완성!

참 쉽죠?..

 

 

 

자동 종료

팝업을 켰지만, 최대 몇초까지만 살아 있게 하고 싶고, 그 뒤엔 자동으로 닫겼으면 하는 로직을 만들고 싶을땐

showDialog에 사용했던 Builder에서 Future를 이용해서 구현하시면 됩니다

Future.delayed(Duration(seconds: 3), () {
	Navigator.pop(context);
});

3초 딜레이를 줘서 Navigator.pop을 실행하게 합니다. 

Navigator에 주어진 context는 BuildContext의 context이기 때문에, 화면 전체가 꺼지지 않고 AlertDialog만 꺼질 수 있는 것입니다

 

전체코드

void _showDialog() { 
    showDialog(
      context: context,
      builder: (BuildContext context) { 

        Future.delayed(Duration(seconds: 3), () {
          Navigator.pop(context);
        });

        return AlertDialog(
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(8.0)
          ),
          content: SizedBox(
            height: 200,
            child: Center(
              child:SizedBox(
                child: 
                    new CircularProgressIndicator(
                      valueColor: new AlwaysStoppedAnimation(Colors.blue),
                      strokeWidth: 5.0
                    ),
                height: 50.0,
                width: 50.0,
              )
            ),
          ), 
        );
      },
    );
  }

 

auto close. gif

 

댓글