사용된 컴포넌트
Form : https://api.flutter.dev/flutter/widgets/Form-class.html
TextFormField : https://api.flutter.dev/flutter/material/TextFormField-class.html
Navigator : https://api.flutter.dev/flutter/dart-html/Navigator-class.html
Route : https://api.flutter.dev/flutter/widgets/Route-class.html
flutter_svg : https://pub.dev/packages/flutter_svg
Theme : https://api.flutter.dev/flutter/material/Theme-class.html
프로젝트 구조
pubspec.yaml
name: flutter_login
description: flutter login ui app
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 1.0.0+1
environment:
sdk: ">=2.15.1 <3.0.0"
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.2
#외부 라이브러리 https://pub.dev/packages/flutter_svg
flutter_svg: ^1.0.0
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^1.0.0
flutter:
uses-material-design: true
# assets 경로 지정
assets:
- assets/
main.dart
import 'package:flutter/material.dart';
import 'package:flutter_login/pages/home_page.dart';
import 'package:flutter_login/pages/login_page.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Login App',
// 테마설정
theme: ThemeData(
/// 전체 TextButton 테마를 지정하면 모든 TextButton에 테마가 적용된다.
textButtonTheme: TextButtonThemeData(
style: TextButton.styleFrom(
backgroundColor: Colors.black,
primary: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
),
minimumSize: Size(400, 60)
)
),
),
/// 화면이동을 위해 route를 사용
initialRoute: "/login", // 초기 경로 설정
routes: { // 경로 목록
"/login" : (context) => LoginPage(),
"/home" : (context) => HomePage()
},
);
}
}
size.dart : 사이즈를 위한 상수 선언 파일
const double small_gap = 5.0;
const double medium_gap = 10.0;
const double large_gap = 20.0;
const double xlarge_gap = 100.0;
components/custom_form.dart : 폼 입력 화면 구성
import 'package:flutter/material.dart';
import 'package:flutter_login/components/custom_text_form_field.dart';
import 'package:flutter_login/size.dart';
class CustomForm extends StatelessWidget {
// global key
final _formkey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return Form(
// global key를 form에 지정하여 해당 key로 form의 상태를 관리
key: _formkey,
child: Column(
children: [
CustomTextFormField("Email"),
SizedBox(height: medium_gap,),
CustomTextFormField("Password"),
SizedBox(height: large_gap,),
// 로그인 버튼
TextButton(
onPressed: (){
/// 유효성 검사
if (_formkey.currentState!.validate()) {
/// 네비게이터로 화면 이동, routes의 이름을 적어 이동한다
Navigator.pushNamed(context, "/home");
}
},
child: Text("Login"),
)
],
),
);
}
}
components/custom_text_form_field.dart : 텍스트폼필드를 커스텀하게 정의
import 'package:flutter/material.dart';
import 'package:flutter_login/size.dart';
class CustomTextFormField extends StatelessWidget {
final String text;
const CustomTextFormField(this.text);
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(text),
SizedBox(height: small_gap,),
TextFormField(
// 1. [유효성 체크]
// 공백일 경우 메시지 출력..
validator: (value) => value!.isEmpty
? "필수항목입니다"
: null,
// 2. [마킹처리]
// text가 Password일 경우 마킹 처리 true
obscureText: text == "Password" ? true : false,
// 3. [데코레이션]
// 힌트 문자나 여러가지 데코레이션 기능 추가
decoration: InputDecoration(
hintText: "Enter $text.", // 힌트문자
enabledBorder: OutlineInputBorder(
// 기본 모양
borderRadius: BorderRadius.circular(20),
),
focusedBorder: OutlineInputBorder(
// 포커스 되었을 경우 모양
borderRadius: BorderRadius.circular(20),
),
errorBorder: OutlineInputBorder(
// 에러 발생 시 모양
borderRadius: BorderRadius.circular(20)
),
focusedErrorBorder: OutlineInputBorder(
// 에러 발생 후 포커스 되었을 경우 모양
borderRadius: BorderRadius.circular(20)
)
),
)
],
);
}
}
components/logo.dart : 로고 사용, flutter_svg 외부 라이브러리 사용
import 'package:flutter/cupertino.dart';
import 'package:flutter_svg/flutter_svg.dart';
/// flutter_svg 외부 라이브러리를 이용해 svg 이미지를 가져온다.
class Logo extends StatelessWidget {
final String title;
//const Logo({Key? key}) : super(key: key);
const Logo(this.title);
@override
Widget build(BuildContext context) {
return Column(
children: [
SvgPicture.asset(
"assets/logon_logo.svg",
height: 70,
width: 70,
),
Text(title, style: TextStyle(fontSize: 40, fontWeight: FontWeight.bold),)
],
);
}
}
pages/login_page.dart : 로그인 페이지
import 'package:flutter/material.dart';
import 'package:flutter_login/components/custom_form.dart';
import 'package:flutter_login/components/logo.dart';
import 'package:flutter_login/size.dart';
// stless 단축키로 자동 생성..
class LoginPage extends StatelessWidget {
const LoginPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(16.0),
child: ListView(
children: [
SizedBox(height: xlarge_gap,),
Logo("Login"),
SizedBox(height: large_gap,),
CustomForm(),
],
),
)
);
}
}
pages/home_page.dart : 로그인 이후 화면 페이지
import 'package:flutter/material.dart';
import 'package:flutter_login/components/logo.dart';
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(16.0),
child: ListView(
children: [
SizedBox(height: 200,),
Logo("환영합니다."),
SizedBox(height: 50,),
TextButton(
onPressed: (){
Navigator.pop(context);
},
child: Text("로그인 페이지로 이동"))
],
),
),
);
}
}
참고 : https://github.com/flutter-coder/flutter-ui-book1/tree/master/flutter_login
'개발 > Flutter' 카테고리의 다른 글
[Flutter] 프로필 UI 만들기 (0) | 2021.12.30 |
---|---|
[Flutter] The flutter tool cannot access the file or directory. (0) | 2021.12.29 |
[Flutter] 플러터로 개발시 유용한 pub.dev (0) | 2021.12.12 |
[Flutter] 레시피 UI 만들기 (1) | 2021.12.12 |
[Fultter] 쇼핑몰 UI 만들기 (0) | 2021.12.03 |
댓글