Don't think! Just do it!

종합 IT 기술 정체성 카오스 블로그! 이... 이곳은 어디지?

Flutter/Flutter Study

[Flutter] loading 화면

방피터 2022. 10. 25. 11:26

CircularProgressIndicator라고 위젯이 하나 있는데 뭐 별건 아니고 동글동글 도는 녀석이지.

CircularProgressIndicator

보통 서버와 통신하거나 할 때 화면이 정지된 상태로 가만히 기다리면 이상하잖아? ㅋㅋ 그래서 돌돌이를 돌려놓는거지 ㅋ

단순히 이 위젯을 설명할 건 아니여~ 뭘 할거냐면 이 돌돌이를 돌려놓을 때 화면이 스크롤이 된다거나, 버튼이 또 눌린다거나 할 수도 있어서 그걸 좀 막고 싶을 때 있잖아? 배경도 좀 뿌옇게 처리해서 유저한테 컨트롤 못합니다~ 하고 알려주고 ㅋ👇

구현할 돌돌이.

이걸 구현하려면 우선 Stack에다가 children으로 Offstage로 감싸진 CircularProgressIndicator와 ModalBarrier 위젯을 사용해. 말만 들어도 쀨이 딱 오지 않아? ㅎㅎㅎ 그림을 보면 쫌 쉽지 👇

돌돌이 돌 때 배경화면 클릭못하게 + 뿌옇게!

Stack으로 원래 스크린하고 Offstage로 돌돌이랑 배경 뿌옇+컨트롤 못하게 하는 위젯을 감싸두는거지. 그리고 필요할 때 offstage를 컨트롤해서 보이게 했다가 안보이게 했다가~ 닥치고 코드나 내놓으라고? 응 ㅋ 👇

Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          StreamBuilder<User?>(
            stream: auth.authStateChanges(),
            builder: ((context, snapshot) {
              if (snapshot.hasData) {
                return const MainNavigator();
              } else {
                return const LoginNavigator();
              }
            }),
          ),
          Obx(//isLoading(obs)가 변경되면 다시 그림.
            () => Offstage(
              offstage: !IsLoadingController.to.isLoading, // isLoading이 false면 감춰~
              child: Stack(children: const <Widget>[//다시 stack
                Opacity(//뿌옇게~
                  opacity: 0.5,//0.5만큼~
                  child: ModalBarrier(dismissible: false, color: Colors.black),//클릭 못하게~
                ),
                Center(
                  child: CircularProgressIndicator(),//무지성 돌돌이~
                ),
              ]),
            ),
          ),
        ],
      ),
    );
  }

나는 Main에 main navigator들과 함께 묶어놨어.👆 스크린마다 돌돌이를 배치할 수는 없잖아? ㅋㅋ 그래서 한방에 끝내버림 ㅋㅋ 그리고 GetXController를 만들어서 offstage 값을 컨트롤해.👇

import 'package:get/get.dart';

class IsLoadingController extends GetxController {
  static IsLoadingController get to => Get.find();

  final _isLoading = false.obs;

  bool get isLoading => _isLoading.value;
  set isLoading(bool value) => _isLoading.value = value;
  void setIsLoading(bool value) => _isLoading.value = value;
}

뭐 초 간단하지 ㅋㅋ 사용하고 싶을 때는 아무 곳에서나 IsLoadingController.to.isLoading = false, true 해서 뿌연 배경과 함께 indicator(돌돌이)를 소환할 수 있게 되었어 ㅋ 아유 신나 ㅋ

onPressed: () {
  IsLoadingController.to.isLoading = true;// 돌돌이 소환!
  if (_formKey.currentState!.validate()) {
    //todo 전송
    ReportController.to
        .sendReport(_emailController.text, _textController.text)
        .then((value) {// 일이 다 끝나면
      IsLoadingController.to.isLoading = false;// 돌돌이 들어가~
    }).catchError((onError) {//에러가 있어도
      IsLoadingController.to.isLoading = false;// 돌돌이 들어가~
    });
  } else {
    IsLoadingController.to.isLoading = false;// 돌돌이 들어가~
    if (!Get.isSnackbarOpen) {
      Get.snackbar("오류", "입력에 오류가 있어요.");
    }
  }
},

그리고 돌돌이 디자인이 너무 식상하다? 하면 👇 flutter_spinkit을 써보자 ㅎㅎ

https://pub.dev/packages/flutter_spinkit

 

flutter_spinkit | Flutter Package

A collection of loading indicators animated with flutter. Heavily inspired by @tobiasahlin's SpinKit.

pub.dev

설치하고

% flutter pub add flutter_spinkit

CircularProgressIndicator() 를 spinkit 중 하나로 변경해바바 ㅋㅋ

  Obx(
    () => Offstage(
      offstage: !IsLoadingController.to.isLoading,
      child: Stack(children: <Widget>[
        const Opacity(
          opacity: 0.5,
          child: ModalBarrier(dismissible: false, color: Colors.black),
        ),
        Center(
          child: SpinKitCubeGrid(//요기요기요기
            itemBuilder: (context, index) {
              return const DecoratedBox(
                decoration: BoxDecoration(color: Colors.amber),
              );
            },
          ),
        ),
      ]),
    ),
  ),

그리고 테스트 해보면? 👇👇

Spinkit! 좋다!

너무 식상한거 아니냐고? 음... 그렇다면 itembuilder에서 리턴되는 애들을 적절하게 변경해바바 ㅋㅋ 그럼 너네도 도는 멍멍이로 loading화면을 만들 수 있어 ㅋㅋㅋㅋㅋㅋ 자! 해보자! 혼자하는 등신짓은 공짜야!! ㅋㅋㅋ

멍멍이 돌돌이 ㅋ

Center(
  child: SpinKitSpinningCircle(
    itemBuilder: (context, index) {
      return Center(
        child: Text(
          "🐶",
          style: TextStyle(fontSize: 40),
        ),
      );
    },
  ),
),
반응형