[Flutter] Login 구현

비나·2022년 11월 14일
4

Flutter

목록 보기
15/16
post-thumbnail

📌 Login 구현하기

이번 포스팅은 코딩셰프 Flutter 조금 매운맛 강좌 중 로그인 구현 하는 부분 정리이다.
간단한 로그인 화면을 만들고,
입력한 이메일과 비밀번호가 특정 값과 일치하면
다음 화면으로 이동하도록 조건문을 사용해 구현하는 간단한 로그인 구현을 해본다.

비밀번호 부분의 경우 입력할때 화면에 보이지 않아야 하기 때문에,
obscureText: true 로 입력한 글자가 보이지 않도록 구현한다.


✅ Login 틀

일단 TextField를 사용해서 로그인 입력하는 부분을 만든다.

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Login',
      home: LogIn(),
    );
  }
}

class LogIn extends StatefulWidget {
  @override
  State<LogIn> createState() => _LogInState();
}

class _LogInState extends State<LogIn> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Log in'),
        elevation: 0.0,
        backgroundColor: Colors.redAccent,
        centerTitle: true,
        leading: IconButton(icon: Icon(Icons.menu), onPressed: () {}),
        actions: <Widget>[
          IconButton(icon: Icon(Icons.search), onPressed: () {})
        ],
      ),
      body: Column(
        children: [
          Padding(padding: EdgeInsets.only(top: 50)),
          Center(
            child: Image(
              image: AssetImage('image/munji.png'),
              width: 170.0,
            ),
          ),
          Form(
              child: Theme(
            data: ThemeData(
                primaryColor: Colors.grey,
                inputDecorationTheme: InputDecorationTheme(
                    labelStyle: TextStyle(color: Colors.teal, fontSize: 15.0))),
            child: Container(
                padding: EdgeInsets.all(40.0),
                // 키보드가 올라와서 만약 스크린 영역을 차지하는 경우 스크롤이 되도록
                // SingleChildScrollView으로 감싸 줌
                child: SingleChildScrollView(
                  child: Column(
                    children: [
                      TextField(
                        decoration: InputDecoration(labelText: 'Enter email'),
                        keyboardType: TextInputType.emailAddress,
                      ),
                      TextField(
                        decoration:
                            InputDecoration(labelText: 'Enter password'),
                        keyboardType: TextInputType.text,
                        obscureText: true, // 비밀번호 안보이도록 하는 것
                      ),
                      SizedBox(height: 40.0,),
                      ButtonTheme(
                        minWidth: 100.0,
                        height: 50.0,
                        child: ElevatedButton( 
                            onPressed: (){
                              
                            },
                            child: Icon(
                              Icons.arrow_forward,
                              color: Colors.white,
                              size: 35.0,
                            ),
                            style: ElevatedButton.styleFrom(
                              backgroundColor: Colors.orangeAccent
                            ),
                        )
                      )
                    ],
                  ),
                )),
          ))
        ],
      ),
    );
  }
}

✅ 예제 코드

🌟 email과 password 체크

TextField에 있는 값을 읽어야하는 경우,
TextEditingController 사용해서 TextField와 연결한다.

TextEditingController 변수형으로 controller, controller2 변수를 선언하고,
이 변수에 각각 이메일과 비밀번호의 값을 입력받는다.

그리고 조건문을 사용하여 이메일이 mei@hello.com 이고,
비밀번호가 1234 인 경우에만 다음 화면으로 이동하도록 한다.
이메일이나 비밀번호가 틀린 경우에는
showSnackBar()함수를 통해 snack bar를 띄워 잘못 된 것을 알려주도록 한다.

이 부분의 코드를 보면 아래와 같다.

if (controller.text == 'mei@hello.com' &&
    controller2.text == '1234') {
  Navigator.push(
    context,
    MaterialPageRoute(
      builder: (BuildContext context) =>
    NextPage()));
}
else if (controller.text == 'mei@hello.com' && controller2.text != '1234') {
  showSnackBar(context, Text('Wrong password'));
}
else if (controller.text != 'mei@hello.com' && controller2.text == '1234') {
  showSnackBar(context, Text('Wrong email'));
}
else {
  showSnackBar(context, Text('Check your info again'));
}
}

🌟 snack bar 구현

위의 조건문에서는 이메일이나 비밀번호가 틀린 경우,
showSnackBar()함수를 통해 snack bar를 보여주도록 했다.
snack bar에서는 이메일이 틀렸는지 비밀번호가 틀렸는지 아니면 둘다 틀렸는지에 따라
적절한 문구를 띄워줘야 하므로, showSnackBar에는 context와 Text('')를 전달받도록 했다.

showSnackBar()함수의 구현은 아래와 같이 해준다.

void showSnackBar(BuildContext context, Text text) {
  final snackBar = SnackBar(
    content: text,
    backgroundColor: Color.fromARGB(255, 112, 48, 48),
  );

// Find the ScaffoldMessenger in the widget tree
// and use it to show a SnackBar.
  ScaffoldMessenger.of(context).showSnackBar(snackBar);
}

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

  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

🌟 overflow 방지

이메일과 비밀번호 텍스트필드를 클릭하면,
키보드가 열리게 되는데 이 경우에 화면의 가려지는 부분이 overflow가 된다.
그래서 노란 오류 같은게 보인다.
따라서 이걸 방지하기 위해 SingleChildScrollView 위젯을 사용한다.
강의에서는 텍스트필드 부분을 이 위젯으로 감싸주었는데,
난 그림 부분에서도 overflow 문제가 발생해서 그림 부분부터 아예 감싸줬다.

🌟 Focus

email, password 입력하는 텍스트필드 부분을 제외한 화면을 탭하면,
키보드 사라지게 GestureDetector 사용하여 unfocus 하도록 구현한다.

Focus는 말 그대로 초점을 맞추는 것인데,
텍스트 필드가 선택되면 그 필드에 focus가 된 상태이다.
Focus 관련 된 것들을 간단하게 보면,
FocusNode는 포커스를 받는 특정 위젯을 식별하는 것이고,
FocusScope는 어떤 위젯들까지 포커스를 받을 수 있는지 그 범위를 나타내는 것이다.
여기서는 FocusScope를 사용해서 텍스트 필드가 아닌 부분을 클릭 시에는 unfocus 되도록
아래와 같이 코드를 작성하고 이 위젯 안에 Scaffold의 body를 넣어준다.

GestureDetector(
  onTap: () {
  FocusScope.of(context).unfocus();
}

✅ 예제 전체 코드

이렇게 구현한 전체 코드는 다음과 같다.

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Login',
      home: LogIn(),
    );
  }
}

class LogIn extends StatefulWidget {
  @override
  State<LogIn> createState() => _LogInState();
}

class _LogInState extends State<LogIn> {
  TextEditingController controller = TextEditingController();
  TextEditingController controller2 = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Log in'),
        elevation: 0.0,
        backgroundColor: Colors.redAccent,
        centerTitle: true,
        leading: IconButton(icon: Icon(Icons.menu), onPressed: () {}),
        actions: <Widget>[
          IconButton(icon: Icon(Icons.search), onPressed: () {})
        ],
      ),
      // email, password 입력하는 부분을 제외한 화면을 탭하면, 키보드 사라지게 GestureDetector 사용 
      body: GestureDetector(
        onTap: () {
          FocusScope.of(context).unfocus();
        },
        child: SingleChildScrollView(
          child: Column(
            children: [
              Padding(padding: EdgeInsets.only(top: 50)),
              Center(
                child: Image(
                  image: AssetImage('image/munji.png'),
                  width: 170.0,
                ),
              ),
              Form(
                child: Theme(
                data: ThemeData(
                    primaryColor: Colors.grey,
                    inputDecorationTheme: InputDecorationTheme(
                        labelStyle: TextStyle(color: Colors.teal, fontSize: 15.0))),
                child: Container(
                    padding: EdgeInsets.all(40.0),
                    child: Builder(builder: (context) {
                      return Column(
                        children: [
                          TextField(
                            controller: controller,
                            autofocus: true,
                            decoration: InputDecoration(labelText: 'Enter email'),
                            keyboardType: TextInputType.emailAddress,
                          ),
                          TextField(
                            controller: controller2,
                            decoration:
                                InputDecoration(labelText: 'Enter password'),
                            keyboardType: TextInputType.text,
                            obscureText: true, // 비밀번호 안보이도록 하는 것
                          ),
                          SizedBox(
                            height: 40.0,
                          ),
                          ButtonTheme(
                              minWidth: 100.0,
                              height: 50.0,
                              child: ElevatedButton(
                                onPressed: () {
                                  if (controller.text == 'mei@hello.com' &&
                                      controller2.text == '1234') {
                                    Navigator.push(
                                        context,
                                        MaterialPageRoute(
                                            builder: (BuildContext context) =>
                                                NextPage()));
                                  }
                                  else if (controller.text == 'mei@hello.com' && controller2.text != '1234') {
                                      showSnackBar(context, Text('Wrong password'));
                                  }
                                  else if (controller.text != 'mei@hello.com' && controller2.text == '1234') {
                                      showSnackBar(context, Text('Wrong email'));
                                  }
                                  else {
                                    showSnackBar(context, Text('Check your info again'));
                                  }
                                },
                                child: Icon(
                                  Icons.arrow_forward,
                                  color: Colors.white,
                                  size: 35.0,
                                ),
                                style: ElevatedButton.styleFrom(
                                    backgroundColor: Colors.orangeAccent),
                              ))
                        ],
                      );
                    })),
              ))
            ],
          ),
        ),
      ),
    );
  }
}

void showSnackBar(BuildContext context, Text text) {
  final snackBar = SnackBar(
    content: text,
    backgroundColor: Color.fromARGB(255, 112, 48, 48),
  );

// Find the ScaffoldMessenger in the widget tree
// and use it to show a SnackBar.
  ScaffoldMessenger.of(context).showSnackBar(snackBar);
}

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

  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

✅ 화면 결과




📌 마무리

이렇게 오늘의 포스팅을 마친다.
주말에 들은 강의를 이제야 겨우 정리 ㅎ
근데 진짜 이거 강의가 잘되어있다,,
기초 정리하기 너무 좋다.
근데 이게 올라온게 아마 Flutter 2.0 이전 버전이라 버튼 위젯은 신경써서 바뀐걸로 써줘야 한다.
아무튼 오늘 정리 끝 🫠💥




참고
- Flutter
- Dart packages
- 코딩셰프 Flutter 조금 매운맛
profile
아자아자 코딩라이푸 ٩(๑❛ʚ❛๑)۶

0개의 댓글