
1. LoginPage 디자인하기
- svg: 벡터 이미지 = 글자

import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:flutter_svg/svg.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: "/login",
routes: {
"/login": (context) => LoginPage(),
"/home": (context) => HomePage()
},
);
}
}
class LoginPage extends StatelessWidget {
const LoginPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
SvgPicture.asset("assets/logo.svg"),
Text("Login",
style: TextStyle(fontSize: 40, fontWeight: FontWeight.bold)),
],
)
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Align(
alignment: Alignment.topCenter,
child: ElevatedButton(
child: Text("move login page"),
onPressed: () {
Navigator.pushNamed(context, "/login");
},
),
),
);
}
}
- 컴포넌트로 분리하기
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:flutter_svg/svg.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: "/login",
routes: {
"/login": (context) => LoginPage(),
"/home": (context) => HomePage()
},
);
}
}
class LoginPage extends StatelessWidget {
const LoginPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView(
children: [
Logo("Login"),
],
));
}
}
class Logo extends StatelessWidget {
final title;
Logo(this.title);
@override
Widget build(BuildContext context) {
return Column(
children: [
SvgPicture.asset("assets/logo.svg", height: 70, width: 70),
Text("${title}",
style: TextStyle(fontSize: 40, fontWeight: FontWeight.bold)),
],
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Align(
alignment: Alignment.topCenter,
child: ElevatedButton(
child: Text("move login page"),
onPressed: () {
Navigator.pushNamed(context, "/login");
},
),
),
);
}
}


size.dart
- gap에 일관성을 만들어서 여백 지정하기 → 아니면 다 무너짐
double smallGap = 5.0;
double mediumGap = 10.0;
double largeGap = 20.0;
double xlargeGap = 100.0;
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:flutter_svg/svg.dart';
import 'package:login_app_test/size.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: "/login",
routes: {
"/login": (context) => LoginPage(),
"/home": (context) => HomePage()
},
);
}
}
class LoginPage extends StatelessWidget {
const LoginPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView(
children: [
SizedBox(height: xlargeGap),
Logo("Login"),
],
));
}
}
class Logo extends StatelessWidget {
final title;
Logo(this.title);
@override
Widget build(BuildContext context) {
return Column(
children: [
SvgPicture.asset("assets/logo.svg", height: 70, width: 70),
Text("${title}",
style: TextStyle(fontSize: 40, fontWeight: FontWeight.bold)),
],
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Align(
alignment: Alignment.topCenter,
child: ElevatedButton(
child: Text("move login page"),
onPressed: () {
Navigator.pushNamed(context, "/login");
},
),
),
);
}
}

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:flutter_svg/svg.dart';
import 'package:login_app_test/size.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: "/login",
routes: {
"/login": (context) => LoginPage(),
"/home": (context) => HomePage()
},
);
}
}
class LoginPage extends StatelessWidget {
const LoginPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView(
children: [
SizedBox(height: xlargeGap),
Logo("Login"),
Text("Email"),
TextFormField(
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
),
),
],
));
}
}
class Logo extends StatelessWidget {
final title;
Logo(this.title);
@override
Widget build(BuildContext context) {
return Column(
children: [
SvgPicture.asset("assets/logo.svg", height: 70, width: 70),
Text("${title}",
style: TextStyle(fontSize: 40, fontWeight: FontWeight.bold)),
],
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Align(
alignment: Alignment.topCenter,
child: ElevatedButton(
child: Text("move login page"),
onPressed: () {
Navigator.pushNamed(context, "/login");
},
),
),
);
}
}


import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:flutter_svg/svg.dart';
import 'package:login_app_test/size.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: "/login",
routes: {
"/login": (context) => LoginPage(),
"/home": (context) => HomePage()
},
);
}
}
class LoginPage extends StatelessWidget {
const LoginPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView(
children: [
SizedBox(height: xlargeGap),
Logo("Login"),
Text("Email"),
TextFormField(
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
),
),
],
));
}
}
class Logo extends StatelessWidget {
final title;
Logo(this.title);
@override
Widget build(BuildContext context) {
return Column(
children: [
SvgPicture.asset("assets/logo.svg", height: 70, width: 70),
Text("${title}",
style: TextStyle(fontSize: 40, fontWeight: FontWeight.bold)),
],
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Align(
alignment: Alignment.topCenter,
child: ElevatedButton(
child: Text("move login page"),
onPressed: () {
Navigator.pushNamed(context, "/login");
},
),
),
);
}
}

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:flutter_svg/svg.dart';
import 'package:login_app_test/size.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: "/login",
routes: {
"/login": (context) => LoginPage(),
"/home": (context) => HomePage()
},
);
}
}
class LoginPage extends StatelessWidget {
const LoginPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView(
children: [
SizedBox(height: xlargeGap),
Logo("Login"),
Text("Email"),
TextFormField(
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
),
),
],
));
}
}
class Logo extends StatelessWidget {
final title;
Logo(this.title);
@override
Widget build(BuildContext context) {
return Column(
children: [
SvgPicture.asset("assets/logo.svg", height: 70, width: 70),
Text("${title}",
style: TextStyle(fontSize: 40, fontWeight: FontWeight.bold)),
],
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Align(
alignment: Alignment.topCenter,
child: ElevatedButton(
child: Text("move login page"),
onPressed: () {
Navigator.pushNamed(context, "/login");
},
),
),
);
}
}
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:flutter_svg/svg.dart';
import 'package:login_app_test/size.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: "/login",
routes: {
"/login": (context) => LoginPage(),
"/home": (context) => HomePage()
},
);
}
}
class LoginPage extends StatelessWidget {
const LoginPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView(
children: [
SizedBox(height: xlargeGap),
Logo("Login"),
Text("Email"),
TextFormField(
decoration: InputDecoration(
hintText: "Enter Email",
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
),
),
],
));
}
}
class Logo extends StatelessWidget {
final title;
Logo(this.title);
@override
Widget build(BuildContext context) {
return Column(
children: [
SvgPicture.asset("assets/logo.svg", height: 70, width: 70),
Text("${title}",
style: TextStyle(fontSize: 40, fontWeight: FontWeight.bold)),
],
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Align(
alignment: Alignment.topCenter,
child: ElevatedButton(
child: Text("move login page"),
onPressed: () {
Navigator.pushNamed(context, "/login");
},
),
),
);
}
}

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:flutter_svg/svg.dart';
import 'package:login_app_test/size.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: "/login",
routes: {
"/login": (context) => LoginPage(),
"/home": (context) => HomePage()
},
);
}
}
class LoginPage extends StatelessWidget {
const LoginPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView(
children: [
SizedBox(height: xlargeGap),
Logo("Login"),
Text("Email"),
Form(
child: Column(
children: [
TextFormField(
decoration: InputDecoration(
hintText: "Enter Email",
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
),
)
],
)),
],
));
}
}
class Logo extends StatelessWidget {
final title;
Logo(this.title);
@override
Widget build(BuildContext context) {
return Column(
children: [
SvgPicture.asset("assets/logo.svg", height: 70, width: 70),
Text("${title}",
style: TextStyle(fontSize: 40, fontWeight: FontWeight.bold)),
],
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Align(
alignment: Alignment.topCenter,
child: ElevatedButton(
child: Text("move login page"),
onPressed: () {
Navigator.pushNamed(context, "/login");
},
),
),
);
}
}
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:flutter_svg/svg.dart';
import 'package:login_app_test/size.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: "/login",
routes: {
"/login": (context) => LoginPage(),
"/home": (context) => HomePage()
},
);
}
}
class LoginPage extends StatelessWidget {
const LoginPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView(
children: [
SizedBox(height: xlargeGap),
Logo("Login"),
Text("Email"),
Form(
child: Column(
children: [
TextFormField(
decoration: InputDecoration(
hintText: "Enter Email",
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
),
),
TextButton(
onPressed: () {},
child: Text("login"),
),
],
)),
],
));
}
}
class Logo extends StatelessWidget {
final title;
Logo(this.title);
@override
Widget build(BuildContext context) {
return Column(
children: [
SvgPicture.asset("assets/logo.svg", height: 70, width: 70),
Text("${title}",
style: TextStyle(fontSize: 40, fontWeight: FontWeight.bold)),
],
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Align(
alignment: Alignment.topCenter,
child: ElevatedButton(
child: Text("move login page"),
onPressed: () {
Navigator.pushNamed(context, "/login");
},
),
),
);
}
}

- 컴포넌트로 뺴기
import 'package:flutter/material.dart';
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Align(
alignment: Alignment.topCenter,
child: ElevatedButton(
child: Text("move login page"),
onPressed: () {
Navigator.pushNamed(context, "/login");
},
),
),
);
}
}
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import '../components/custom_form.dart';
import '../components/logo.dart';
import '../size.dart';
class LoginPage extends StatelessWidget {
const LoginPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView(
children: [
SizedBox(height: xlargeGap),
Logo("Login"),
CustomForm(),
],
));
}
}
import 'dart:ui';
import 'package:flutter/cupertino.dart';
import 'package:flutter_svg/svg.dart';
class Logo extends StatelessWidget {
final title;
Logo(this.title);
@override
Widget build(BuildContext context) {
return Column(
children: [
SvgPicture.asset("assets/logo.svg", height: 70, width: 70),
Text("${title}",
style: TextStyle(fontSize: 40, fontWeight: FontWeight.bold)),
],
);
}
}
import 'package:flutter/material.dart';
class CustomForm extends StatelessWidget {
const CustomForm({
super.key,
});
@override
Widget build(BuildContext context) {
return Form(
child: Column(
children: [
Text("Email"),
TextFormField(
decoration: InputDecoration(
hintText: "Enter Email",
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
),
),
TextButton(
onPressed: () {},
child: Text("login"),
),
],
));
}
import 'package:flutter/material.dart';
import 'package:login_app_test/pages/home_page.dart';
import 'package:login_app_test/pages/login_page.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: "/login",
routes: {
"/login": (context) => LoginPage(),
"/home": (context) => HomePage(),
},
);
}
}

import 'package:flutter/material.dart';
class CustomForm extends StatelessWidget {
TextEditingController? emailController;
@override
Widget build(BuildContext context) {
return Form(
child: Column(
children: [
Text("Email"),
TextFormField(
controller: emailController,
decoration: InputDecoration(
hintText: "Enter Email",
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
),
),
TextButton(
onPressed: () {},
child: Text("login"),
),
],
));
}
}
import 'package:flutter/material.dart';
class CustomForm extends StatelessWidget {
TextEditingController emailController = TextEditingController();
@override
Widget build(BuildContext context) {
return Form(
child: Column(
children: [
Text("Email"),
TextFormField(
controller: emailController,
decoration: InputDecoration(
hintText: "Enter Email",
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
),
),
TextButton(
onPressed: () {},
child: Text("login"),
),
],
));
}
}
import 'package:flutter/material.dart';
class CustomForm extends StatelessWidget {
TextEditingController email = TextEditingController();
@override
Widget build(BuildContext context) {
return Form(
child: Column(
children: [
Text("Email"),
TextFormField(
controller: email,
decoration: InputDecoration(
hintText: "Enter Email",
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
),
),
TextButton(
onPressed: () {},
child: Text("login"),
),
],
));
}
}
Share article