코딩하는 제리

[Flutter/MiniProject] AuthenticationPage 본문

Flutter/MiniProject

[Flutter/MiniProject] AuthenticationPage

JerryCho 2021. 3. 12. 17:56


처음 실행시 화면. 우측 상단의 아이콘 클릭시 로그인 페이지 이동


소스코드 및 pubspec.yaml

provider 추가
assets 폴더 추가

// main.dart

import 'package:authentication_template_jerry/pages/auth_page.dart';
import 'package:authentication_template_jerry/provider/page_notifier.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'pages/my_home.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (_) => PageNotifier()),
      ],
      child: MaterialApp(
          title: 'Main Page',
          home: Consumer<PageNotifier>(
            builder: (context, pageNotifier, child) {
              return Navigator(
                pages: [
                  // 뒤에 쓰인 페이지 일수록 화면상 위에 존재.
                  MaterialPage(
                    key: ValueKey(MyHomePage.pageName),
                    child: MyHomePage(title: 'MyHomePage'),
                  ),
                  if (pageNotifier.currentPage == AuthPage.pageName) AuthPage(),
                ],
                onPopPage: (route, result) {
                  if (!route.didPop(result)) {
                    return false;
                  }
                  return true;
                },
              );
            },
          )),
    );
  }
}
// pages/my_home.dart

import 'package:authentication_template_jerry/pages/auth_page.dart';
import 'package:authentication_template_jerry/provider/page_notifier.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

class MyHomePage extends StatefulWidget {
  static final String pageName = 'MyHomePage';

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

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
        actions: [
          IconButton(
              icon: Icon(Icons.logout),
              onPressed: () {
                Provider.of<PageNotifier>(context, listen: false)
                    .goToOtherPage(AuthPage.pageName);
              }),
        ],
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}
// provider/page_notifier.dart

import 'package:flutter/material.dart';
import 'package:authentication_template_jerry/pages/my_home.dart';

class PageNotifier extends ChangeNotifier {
  String _currentPage = MyHomePage.pageName;

  String get currentPage => _currentPage;

  void goToMain() {
    _currentPage = MyHomePage.pageName;
    notifyListeners();
  }

  void goToOtherPage(String name) {
    _currentPage = name;
    notifyListeners();
  }
}
// pages/auth_page.dart

import 'package:authentication_template_jerry/provider/page_notifier.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

class AuthPage extends Page {
  static final pageName = 'AuthPage';

  @override
  Route createRoute(BuildContext context) {
    return MaterialPageRoute(
        // 기본 설정은 this,
        settings: this,
        builder: (context) => AuthWidget());
  }
}

class AuthWidget extends StatefulWidget {
  @override
  _AuthWidgetState createState() => _AuthWidgetState();
}

class _AuthWidgetState extends State<AuthWidget> {
  GlobalKey<FormState> _formKey = GlobalKey<FormState>();

  TextEditingController _emailController = TextEditingController();
  TextEditingController _passwordController = TextEditingController();
  TextEditingController _cPasswordController = TextEditingController();

  bool isRegister = true;

  Size size;

  Duration _duration = Duration(milliseconds: 200);
  Curve _curve = Curves.fastOutSlowIn;

  static final double _cornerRadius = 8.0;
  OutlineInputBorder _border = OutlineInputBorder(
    borderRadius: BorderRadius.circular(_cornerRadius),
    borderSide: BorderSide(color: Colors.transparent, width: 0),
  );

  @override
  Widget build(BuildContext context) {
    if (size == null) size = MediaQuery.of(context).size;
    return Material(
      child: Container(
        decoration: BoxDecoration(
          image: DecorationImage(
            fit: BoxFit.cover,
            image: AssetImage('assets/image.gif'),
          ),
        ),
        child: Scaffold(
          // Container 배경을 보여줌
          backgroundColor: Colors.transparent,
          body: SafeArea(
            child: Form(
              key: _formKey,
              child: Padding(
                padding: const EdgeInsets.all(6.0),
                child: ListView(
                  reverse: true /* 리스트의 순서를 뒤집음(하단부터 시작) */,
                  children: [
                    CircleAvatar(
                      backgroundColor: Colors.white54,
                      radius: 36,
                      child: Image.asset('assets/logo.png'),
                    ),
                    SizedBox(
                      height: size.height / 8,
                    ),
                    ButtonBar(
                      children: [
                        TextButton(
                            onPressed: () {
                              setState(() {
                                isRegister = false;
                              });
                            },
                            child: Text(
                              'Login',
                              style: TextStyle(
                                fontSize: 18,
                                fontWeight: isRegister
                                    ? FontWeight.w400
                                    : FontWeight.w600,
                                color:
                                    isRegister ? Colors.white60 : Colors.white,
                              ),
                            )),
                        TextButton(
                            onPressed: () {
                              setState(() {
                                isRegister = true;
                              });
                            },
                            child: Text(
                              'Register',
                              style: TextStyle(
                                fontSize: 18,
                                fontWeight: isRegister
                                    ? FontWeight.w600
                                    : FontWeight.w400,
                                color:
                                    isRegister ? Colors.white : Colors.white60,
                              ),
                            )),
                      ],
                    ),
                    SizedBox(
                      height: 16,
                    ),
                    _buildTextFormField("Email Address", _emailController),
                    SizedBox(
                      height: 8,
                    ),
                    _buildTextFormField("Password", _passwordController),
                    AnimatedContainer(
                      duration: _duration,
                      height: isRegister ? 8 : 0,
                      curve: _curve,
                    ),
                    AnimatedContainer(
                      duration: _duration,
                      height: isRegister ? 80 : 0,
                      curve: _curve,
                      child: _buildTextFormField(
                          "Confirm Password", _cPasswordController),
                    ),
                    SizedBox(
                      height: 16,
                    ),
                    TextButton(
                        onPressed: () {
                          if (_formKey.currentState.validate()) {
                            print('success');
                            Provider.of<PageNotifier>(context, listen: false)
                                .goToMain();
                          }
                        },
                        style: TextButton.styleFrom(
                            padding: EdgeInsets.all(16),
                            primary: Colors.white,
                            backgroundColor: Colors.white38),
                        child: Text(isRegister ? 'Register' : 'Login')),
                    SizedBox(
                      height: 16,
                    ),
                    Divider(
                      height: 33,
                      thickness: 1,
                      color: Colors.white38,
                      indent: 16,
                      endIndent: 16,
                    ),
                    ButtonBar(
                      alignment: MainAxisAlignment.center,
                      children: [
                        _buildSocialButton('assets/google.png', () {}),
                        _buildSocialButton('assets/facebook.png', () {}),
                        _buildSocialButton('assets/apple.png', () {}),
                      ],
                    )
                  ].reversed.toList(),
                  /* 리스트의 순서를 뒤집음.
                  뒤집으면 Iterable 타입으로 변환되기 때분에 toList로 다시 변환 */
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }

  Container _buildSocialButton(String imagePath, Function onPressed) {
    return Container(
      width: 50,
      height: 50,
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(25),
        color: Colors.white38,
      ),
      child: IconButton(
          color: Colors.white,
          icon: ImageIcon(AssetImage(imagePath)),
          onPressed: onPressed),
    );
  }

  TextFormField _buildTextFormField(
      String labelText, TextEditingController controller) {
    return TextFormField(
      cursorColor: Colors.white,
      controller: controller,
      obscureText: controller == _emailController ? false : true,
      validator: (text) {
        if (controller == _emailController &&
            ((text == null || text.isEmpty) || text.contains('@') == false)) {
          return "이메일 형식이 올바르지 않습니다.";
        }
        if (controller == _passwordController &&
            (text.length < 5 || (text == null || text.isEmpty))) {
          return "5자리 이상 입력하세요.";
        }
        if (controller == _cPasswordController &&
            isRegister &&
            (_passwordController.text != text ||
                (text == null || text.isEmpty))) {
          if (_cPasswordController.text.length < 5) {
            return "5자리 이상 입력하세요.";
          }
          return "비밀번호가 다릅니다.";
        }

        return null;
      },
      style: TextStyle(color: Colors.white),
      decoration: InputDecoration(
        labelText: labelText,
        filled: true,
        fillColor: Colors.black38,
        border: _border,
        enabledBorder: _border,
        focusedBorder: _border,
        labelStyle: TextStyle(color: Colors.white),
      ),
    );
  }
}
Comments