728x90
반응형
Login App 만들기 01- 구조
1. form 태그 안에서 각각의 객체들은
앱의 진입점
라우터 명령어를 사용해 전환하여 사용
import 'package:flutter/material.dart';
import 'package:flutter_login_app/components/custom_form.dart';
import 'package:flutter_login_app/components/logo.dart';
import 'package:flutter_login_app/pages/home_page.dart';
import 'package:flutter_login_app/pages/login_page.dart';
import 'package:flutter_login_app/size.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
textButtonTheme: TextButtonThemeData(
style: TextButton.styleFrom(
backgroundColor: Colors.black,
foregroundColor: Colors.white,
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(30.0)),
minimumSize: Size(400, 60),
)),
),
//앱에서 사용할 화면(경로)를 미리 사용할 수 있다.
routes: {
'/login': (context) => LoginPage(),
'/home': (context) => HomePage(),
},
initialRoute: '/login',
);
}
}
// class LoginPage extends StatelessWidget {
// const LoginPage({super.key});
//
// @override
// Widget build(BuildContext context) {
// return ListView(
// children: [
// Logo('Login'),
// SizedBox(height: largeGap),
// CustomForm(),
// ],
// );
// }
// }
페이지들 구성
//로그인 페이지
import 'package:flutter/material.dart';
import 'package:flutter_login_app/components/custom_form.dart';
import 'package:flutter_login_app/components/logo.dart';
import 'package:flutter_login_app/size.dart';
class LoginPage extends StatelessWidget {
const LoginPage({super.key});
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: Padding(
padding: const EdgeInsets.all(16.0),
child: ListView(
children: [
SizedBox(
height: xlargeGap,
),
Logo('Login'),
SizedBox(
height: largeGap,
),
CustomForm(),
],
),
),
),
);
}
}
//홈 페이지
import 'package:flutter/material.dart';
import 'package:flutter_login_app/components/logo.dart';
import 'package:flutter_login_app/size.dart';
import 'package:flutter_svg/flutter_svg.dart';
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
const SizedBox(height: xlargeGap),
Logo('home Page'),
const SizedBox(height: largeGap),
TextButton(
onPressed: () {
//화면 스택 제거
Navigator.pop(context);
},
child: Text('Get Start'))
],
),
),
),
);
}
}
Navigator를 통해 화면 pop(제거), push(보여지기 ) 설정함
폼의 구성 및 유효성 검사
import 'package:flutter/material.dart';
import 'package:flutter_login_app/components/custom_text_form_field.dart';
import 'package:flutter_login_app/size.dart';
class CustomForm extends StatelessWidget {
String _email = '';
String _password = '';
CustomForm({super.key});
// 1. 글로벌 키 선언 - 폼 상태를 관리하기 위한 key 이다.
final _fromKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return Form(
key: _fromKey,
child: Column(
children: [
CustomTextFormField('E-mail', (value) {
_email = value ?? ''; // null 병합 연산자
}),
const SizedBox(height: largeGap),
CustomTextFormField('Password', (value) {
_password = value ?? '';
}),
const SizedBox(height: largeGap),
TextButton(
onPressed: () {
if (_fromKey.currentState!.validate()) {
//유효성 검사가 통과한다면, 아래 로직 호출
//save() 메서드를 호출해야되고
// 통신요청
//로깅 확인
print('validation 통과! eamil : $_email ');
print('validation 통과! password : $_password ');
Navigator.pushNamed(context, '/home');
}
},
child: Text('Login'))
],
),
);
}
}
커스텀 입력 필드
import 'package:flutter/material.dart';
class CustomTextFormField extends StatelessWidget {
final String label;
final FormFieldSetter<String>? onSaved;
const CustomTextFormField(this.label, this.onSaved, {super.key});
@override
Widget build(BuildContext context) {
return TextFormField(
obscureText: label == 'Password',
keyboardType: label == 'E-mail' ? TextInputType.emailAddress : null,
decoration: InputDecoration(
labelText: label,
border: OutlineInputBorder(),
),
validator: (value) {
if (value == null || value.isEmpty) {
return '$label 을 입력하세요.';
}
return null;
},
onSaved: onSaved,
);
}
}
로고 컴포넌트
https://pub.dev/packages/flutter_svg
flutter_svg | Flutter package
An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files.
pub.dev
의존성 주입한 후,
$ flutter pub add flutter_svg
dependencies:
flutter_svg: ^2.0.17
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
class Logo extends StatelessWidget {
final String title;
const Logo(this.title, {super.key});
@override
Widget build(BuildContext context) {
return Column(
children: [
SvgPicture.asset(
'assets/logo.svg',
height: 70,
width: 70,
semanticsLabel: 'Login Logo',
),
Text(
title,
style: TextStyle(
fontSize: 40,
fontWeight: FontWeight.bold,
),
),
],
);
}
}
3. 주요 기능 설명
- 유효성 검사
- 입력 값이 비어 있을 경우 에러 메시지를 출력합니다.
- 이메일 필드와 비밀번호 필드 각각에 적합한 검사를 수행합니다.
- 폼 상태 관리
- _formKey를 사용하여 폼의 상태를 관리합니다.
- onSaved를 활용해 입력 데이터를 저장합니다.
- 로고 표시
- 로고와 제목을 함께 표시하여 사용자 경험을 높입니다.
4. 결과 화면
로그인 화면은 아래와 같이 구성됩니다:
- 로고와 제목
- 이메일 및 비밀번호 입력 필드
- 로그인 버튼
728x90
반응형
'Frontend > Flutter' 카테고리의 다른 글
[flutter 20] shopping_cart_app 만들기 (0) | 2025.01.13 |
---|---|
[Flutter00] Flutter 기초다지기3 _ List (0) | 2025.01.08 |
[Flutter00]플러터 기본기 다지기2 (1) | 2025.01.08 |
댓글