inblog logo
|
sxias
    Flutter

    [Flutter] 7. Login App v1 : Prototype

    문정준's avatar
    문정준
    May 29, 2025
    [Flutter] 7. Login App v1 : Prototype
    Contents
    1. Project 생성2. 경로 설정3. 코드 작성4. Result
     

    1. Project 생성

    • 이전 방법 참조

    2. 경로 설정

    • main.dart
      • 로그인 버튼을 눌렀을 때 다른 화면으로 이동하도록 주소 설정
      • routes : 어떤 경로를 받았을 때 동작할 함수(행위) 결정
    import 'package:flutter/material.dart'; import 'package:loginapp/page/home_page.dart'; import 'package:loginapp/page/login_page.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp(); @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, initialRoute: "/login", routes: {"/home": (context) => HomePage(), "/login": (context) => LoginPage()}, ); } }
     

    3. 코드 작성

    • login_page.dart
      • 로그인 화면
      • 이메일, 비밀번호를 입력하고 로그인 버튼을 누르면 메인 화면으로 넘어가도록 설정
      • ListView : 앱의 내부 키보드로 인해 화면이 줄어듬 → Column으로 지정할 경우 화면이 깨짐
    import 'package:flutter/material.dart'; import 'package:loginapp/component/m_form.dart'; import 'package:loginapp/component/m_logo.dart'; import '../size.dart'; class LoginPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( body: Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: ListView( children: [ SizedBox(height: xxlGap), MLogo("Login"), SizedBox(height: lGap), MForm(), ], ), ), ); } }
     
    • home_page.dart
      • 로그인 한 이후 메인 화면
      • Navigator.pop(context) : 이전 화면으로 돌아가기
    import 'package:flutter/material.dart'; import 'package:loginapp/component/m_button.dart'; import 'package:loginapp/component/m_logo.dart'; import '../size.dart'; class HomePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( body: Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: ListView( children: [ SizedBox(height: xxlGap), MLogo("Care Soft"), SizedBox(height: lGap), MButton("Get Started", () { Navigator.pop(context); }), ], ), ), ); } }
     
    • m_logo.dart
      • SVG 파일을 사용하여 크기가 커져도 이미지가 깨지지 않음 : 벡터 파일
     

    Widgets

    • SvgPictures.asset : asset에서 SVG 파일을 받아서 출력하는 위젯
    import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; class MLogo extends StatelessWidget { String title; MLogo(this.title); @override Widget build(BuildContext context) { return Column( children: [ SvgPicture.asset("logo.svg", width: 70, height: 70), Text( title, style: TextStyle(fontSize: 40, fontWeight: FontWeight.bold), ), ], ); } }
     
    • m_form.dart
      • 데이터를 서버에 전송하기 위한 form
      • 데이터를 전송하기 위해 필요한 컴포넌트들은 form에 묶어서 사용
      • CrossAxisAlignment.stretch : 자식들의 보조 축 길이(너비)를 화면 끝까지 늘려줌
        • minWidth : double.infinity
      • TextEditingController : text에 대한 처리가 가능한 Controller
        • .text : 입력 받은 데이터 값을 Text로 반환
     

    Widgets

    • Form : 데이터를 전달하기 위해 사용하는 위젯
    import 'package:flutter/material.dart'; import 'package:loginapp/component/m_button.dart'; import 'package:loginapp/component/m_text_box.dart'; import '../size.dart'; class MForm extends StatelessWidget { TextEditingController _email = TextEditingController(); TextEditingController _password = TextEditingController(); void submit(BuildContext context) { var requestBody = {"email": _email.text, "password": _password.text}; print("전송할 데이터 : $requestBody"); Navigator.pushNamed(context, "/home"); } @override Widget build(BuildContext context) { return Form( child: Column( // min 값을 double.infinity로 늘려줌 crossAxisAlignment: CrossAxisAlignment.stretch, children: [ MTextBox("Email", _email), SizedBox(height: sGap), MTextBox("Password", _password, isPassword: true), SizedBox(height: mGap), MButton("Login", () => submit(context)), ], ), ); } }
     
    • m_text_box.dart
      • 텍스트를 입력 받아 TextEditingController에 전달하는 컴포넌트
      • bool isPassword를 통해 비밀번호를 입력받을 경우 입력칸을 *로 표시하게 설정 가능
    import 'package:flutter/material.dart'; import 'package:loginapp/component/m_text_field.dart'; class MTextBox extends StatelessWidget { String division; bool isPassword; TextEditingController controller; MTextBox(this.division, this.controller, {this.isPassword = false}); @override Widget build(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(division), MTextField("Enter $division", controller, isPassword: isPassword), ], ); } }
     
    • m_text_field.dart
      • TextEditingController를 통해 입력값을 전달
      • 스타일 설정 가능
        • Enabled(Default), Focused, Error, FocusedError 등 4가지 경우에 대해 설정 가능
     

    Widgets

    • TextFormField : 텍스트를 입력할 수 있는 위젯
      • controller : TextEditingController를 연결
      • decoration : 해당 위젯의 스타일 지정
      • obscureText : 텍스트를 ‘*’로 표시할 지에 대한 여부
      • hintText : 텍스트가 입력되지 않았을 때 표시할 String = placeholder
      • hintStyle : hintText의 스타일 지정
    import 'package:flutter/material.dart'; class MTextField extends StatelessWidget { String placeholder; bool isPassword; TextEditingController controller; MTextField(this.placeholder, this.controller, {this.isPassword = false}); @override Widget build(BuildContext context) { return TextFormField( controller: controller, obscureText: isPassword, decoration: InputDecoration( // 1. enabledBorder : 기본 디자인 // 2. focusedBorder : 포커스가 잡혔을 때 기본 디자인 // 3. errorBorder : 기본 에러 디자인 // 4. focusedErrorBorder : 포커스가 잡혔을 때 기본 에러 디자인 border: OutlineInputBorder(borderRadius: BorderRadius.circular(15)), errorBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15)), focusedErrorBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(15)), hintText: placeholder, hintStyle: TextStyle(color: Colors.black26), ), ); } }
     
    • m_button.dart
      • 입력값을 서버 측에 전달하고, 화면을 전환하는 버튼을 생성하는 컴포넌트
      • 입력값은 submit이라는 함수로 콘솔에 출력하는 행위를 통해 전달
    import 'package:flutter/material.dart'; class MButton extends StatelessWidget { String title; var submit; MButton(this.title, this.submit); @override Widget build(BuildContext context) { return ElevatedButton( onPressed: submit, style: ElevatedButton.styleFrom(backgroundColor: Colors.black, fixedSize: Size(double.infinity, 60)), child: Text( title, style: TextStyle(color: Colors.white), ), ); } }
     
    • size.dart
      • 각 화면에서 사용할 수 있는 gap의 크기를 미리 지정하여 사용
      • 디자인의 통일성 부여
    double sGap = 5; double mGap = 10; double lGap = 20; double xxlGap = 100;
     

    4. Result

    • 로그인 화면
    notion image
     
    • 이메일, 비밀번호 입력 후 Login 버튼을 누르면 메인 화면으로 이동 및 콘솔에 정보 출력
    notion image
     
    • 메인 화면
    notion image
     
    • 콘솔
    notion image
    Share article
    Contents
    1. Project 생성2. 경로 설정3. 코드 작성4. Result

    Sxias ㆍ a32176740@gmail.com

    RSS·Powered by Inblog