iT邦幫忙

2021 iThome 鐵人賽

DAY 26
0
Mobile Development

30天 - Flutter 日常系列 第 26

[Day26] Flutter - Presentation Login & Splash Screen (part10)

前言

Hi, 我是魚板伯爵今天就是把之前寫的一堆功能放到Screen裡面,由於是UI的部分所以程式碼會很長,有些地方我只會擷取片段,建議大家看完整程式碼。

完整程式碼

需要具備知識

Splash Screen

把首頁的MultiBlocProvider加上AuthenticationBloc,並觸發事件AppStarted()來檢查是否有登入過。

// main.dart

BlocProvider(
  create: (context) => AuthenticationBloc(
    authRepository: authRepository,
  )..add(AppStarted()),
),

把這個畫面設置成初始畫面,然後當事件觸發後BlocListener會監聽AuthenticationBloc現在的狀態進行頁面切換。

class SplashScreen extends StatelessWidget {
  const SplashScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BlocListener<AuthenticationBloc, AuthenticationState>(
      listener: (context, state) {
        if (state is Unauthenticated) {
          context.replaceRoute(LoginScreen());
        }
        if (state is Authenticated) {
          context.replaceRoute(HomeScreen());
        }
      },
      child: Scaffold(
        backgroundColor: Theme.of(context).backgroundColor,
      ),
    );
  }
}

Login Screen

LoginScreen這邊一樣加一個AuthenticationBloc監聽器,檢查是否登入成功取得驗證。

class LoginScreen extends StatelessWidget {
  const LoginScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BlocListener<AuthenticationBloc, AuthenticationState>(
      listener: (context, state) {
        if (state is Authenticated) {
          context.replaceRoute(HomeScreen());
        }
      },
      child: Scaffold(
        backgroundColor: Theme.of(context).backgroundColor,
        body: Container(
          width: MediaQuery.of(context).size.width,
          height: MediaQuery.of(context).size.height,
          child: Stack(
            alignment: Alignment.center,
            children: [
              Positioned(
                top: 200,
                child: Text(
                  "Hello",
                  style: Theme.of(context).textTheme.bodyText1,
                ),
              ),
              Positioned(
                top: 370,
                child: BlocProvider(
                  create: (context) =>
                      SignInBloc(authRepository: AuthRepository()),
                  child: LoginFrom(),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Login From

創建SignInBloc然後在LoginForm裡面寫一個SignInBloc的監聽器來檢查登入成功或失敗,如果登入成功的話就觸法LoggedIn的事件。

Positioned(
    top: 370,
    child: BlocProvider(
      create: (context) =>
          SignInBloc(authRepository: AuthRepository()),
      child: LoginFrom(),
    ),
),
class LoginFrom extends StatelessWidget {
  const LoginFrom({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BlocListener<SignInBloc, SignInState>(
      listener: (context, state) {
        if (state is SignInStateSuccess) {
          BlocProvider.of<AuthenticationBloc>(context).add(LoggedIn());
        }
        if (state is SignInStateFailure) {
          // TODO: Display a snackbar
        }
      },
      child: Column(
        children: [
          GoogleSignInButton(),
        ],
      ),
    );
  }
}

Home Screen

在首頁檢查驗證登入狀態,然後在登出按鈕(左上角的小啤酒)新增LoggedOut事件。

return BlocListener<AuthenticationBloc, AuthenticationState>(
  listener: (context, state) {
    if (state is Unauthenticated) {
      context.replaceRoute(LoginScreen());
    }
  },
class SignOutButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return IconButton(
      onPressed: () {
        BlocProvider.of<AuthenticationBloc>(context).add(LoggedOut());
      },
      icon: Icon(
        Icons.sports_bar_rounded,
        color: Theme.of(context).shadowColor,
        size: 30,
      ),
    );
  }
}


上一篇
[Day25] Flutter - Application Authentication (part9)
下一篇
[Day27] Flutter - Infrastructure Click Game (part11)
系列文
30天 - Flutter 日常30

尚未有邦友留言

立即登入留言