이번 글에서는 로그인 UI를 구성하고, 이를 위한 위젯들을 정리해보겠습니다.
디자인 시안을 확인한 후, 필요한 위젯을 만들고 LoginPage와 LoginBody를 구성하겠습니다.
UI에 사용될 파일
디자인 시안
1. 프로젝트에 assets 폴더 및 이미지 추가
로그인 화면에서 로고 및 기타 이미지 파일을 사용하기 위해 assets/ 폴더를 추가하고, 이미지 파일을 프로젝트에 포함해야 합니다.
Flutter에서는 pubspec.yaml 파일에서 assets 폴더 및 이미지 파일을 등록해야 이를 사용할 수 있습니다.
# To add assets to your application, add an assets section, like this:
assets:
- assets/
# - images/a_dot_ham.jpeg
📌설명
- - assets/ → assets 폴더 자체를 등록하여 내부 파일 사용 가능.
- - assets/logo.svg → 로고 파일 개별 등록 (SVG 이미지 사용 가능).
- - images/a_dot_ham.jpeg → 다른 이미지 파일 추가 예시.
👉 이렇게 설정하면 프로젝트에서 assets/ 폴더 내의 로고 및 기타 이미지 파일을 불러와 사용할 수 있습니다.
이제 assets/logo.svg를 활용하여 로그인 화면에 로고를 표시할 수 있습니다.
2. 로그인 UI를 위한 공통 위젯 만들기
로그인 화면에서는 여러 번 재사용되는 요소(예: 입력 필드, 버튼, 로고 등)가 많기 때문에 이를 위젯으로 분리하면 유지보수가 쉽습니다.
우선 로그인 UI에서 사용될 공통 위젯을 먼저 만들어보겠습니다.
- 앱 로고 (CustomLogo)
로그인 화면의 로고 및 앱 이름을 표시하는 위젯입니다.
SVG 형식의 로고 이미지를 불러오고, 앱 이름을 텍스트 스타일링하여 보여줍니다.
📌 파일 위치: ui/widgets/custom_logo.dart
import 'package:class_f_story/_core/constants/size.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
class CustomLogo extends StatelessWidget {
final String title;
const CustomLogo(this.title, {super.key});
@override
Widget build(BuildContext context) {
return Column(
children: [
const SizedBox(height: xlargeGap),
SvgPicture.asset(
'assets/logo.svg', // assets 폴더에 로고 이미지 필요
width: 70,
height: 70,
),
Text(
title,
style: TextStyle(fontSize: 40, fontWeight: FontWeight.bold),
),
const SizedBox(height: largeGap),
],
);
}
}
📌 설명
- SvgPicture.asset('assets/logo.svg'): assets/ 폴더에서 로고를 불러옴.
- Text(title): 앱 이름을 표시.
- SizedBox(height: xlargeGap): 로고와 텍스트 사이에 적절한 간격을 추가
- 로그인 입력 필드 (CustomAuthTextFormField)
사용자명 및 비밀번호 입력을 위한 커스텀 TextFormField 위젯입니다.
각 필드에는 라벨, 입력 필드, 테두리 스타일을 적용했습니다.
📌 파일 위치: ui/widgets/custom_auth_text_form_field.dart
import 'package:class_f_story/_core/constants/size.dart';
import 'package:flutter/material.dart';
class CustomAuthTextFormField extends StatelessWidget {
final String text;
final bool obscureText;
final TextEditingController controller;
const CustomAuthTextFormField({
required this.text,
this.obscureText = false,
required this.controller,
super.key,
});
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(text),
const SizedBox(height: smallGap),
TextFormField(
controller: controller,
obscureText: obscureText,
decoration: InputDecoration(
hintText: 'Enter $text',
enabledBorder: OutlineInputBorder(
// 기본 TextFormField 설정한다.
borderRadius: BorderRadius.circular(20.0),
),
focusedBorder: OutlineInputBorder(
// 손가락 터치시 활성화 된 디자인 설정
borderRadius: BorderRadius.circular(20.0),
),
errorBorder: OutlineInputBorder(
// 유효설 검사 실패시 사용되는 디자인 설정
borderRadius: BorderRadius.circular(20.0),
),
focusedErrorBorder: OutlineInputBorder(
// 에러가 발생 후 손가락을 터치 했을 때 디자인 설정
borderRadius: BorderRadius.circular(20.0),
),
),
),
],
);
}
}
📌 설명
- Text(text): 입력 필드 위에 라벨을 표시.
- TextFormField: 실제로 입력할 수 있는 필드.
- obscureText: 비밀번호 입력 시 true로 설정하면 입력 내용이 숨겨짐.
- 로그인 버튼 (CustomElevatedButton)
로그인 버튼을 위한 ElevatedButton 위젯입니다.
📌 파일 위치: ui/widgets/custom_elevated_button.dart
import 'package:flutter/material.dart';
class CustomElevatedButton extends StatelessWidget {
final String text;
// final Function(String) click;
final click;
const CustomElevatedButton({
required this.text,
required this.click,
super.key,
});
@override
Widget build(BuildContext context) {
return ElevatedButton(
style: ElevatedButton.styleFrom(
minimumSize: Size(double.infinity, 50),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
backgroundColor: Colors.white12),
onPressed: click,
child: Text('$text'),
);
}
}
📌 설명
- onPressed: click: 버튼 클릭 시 실행할 함수를 받음.
- backgroundColor: Colors.white12: 버튼의 기본 색상을 지정.
- 회원가입으로 이동 버튼 (CustomTextButton)
회원가입 페이지로 이동할 때 사용하는 텍스트 버튼입니다.
📌 파일 위치: ui/widgets/custom_text_button.dart
import 'package:flutter/material.dart';
class CustomTextButton extends StatelessWidget {
final String text;
// 내장 되어 있어 있는 데이터 타입
final VoidCallback click;
CustomTextButton({
required this.text,
required this.click,
super.key,
});
@override
Widget build(BuildContext context) {
return TextButton(
onPressed: click,
child: Text(
text,
style: TextStyle(
color: Colors.black87,
decoration: TextDecoration.underline,
),
),
);
}
}
📌 설명
- TextButton: 일반 버튼이 아닌 텍스트 버튼을 사용하여 회원가입 링크처럼 보이게 함.
- decoration: TextDecoration.underline: 밑줄 효과를 추가.
3. 로그인 화면 구성
이제 위에서 만든 공통 위젯을 활용해 로그인 화면을 구성하겠습니다.
- 로그인 페이지 (LoginPage)
📌 파일 위치: ui/pages/auth/login_page.dart
import 'package:class_f_story/ui/pages/auth/login_page/widgets/login_body.dart';
import 'package:flutter/material.dart';
class LoginPage extends StatelessWidget {
const LoginPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: LoginBody(),
);
}
}
📌 설명
- Scaffold의 body에 LoginBody()를 배치.
- 로그인 화면 본문 (LoginBody)
📌 파일 위치: ui/pages/auth/login_page/widgets/login_body.dart
import 'package:class_f_story/_core/constants/size.dart';
import 'package:class_f_story/ui/widgets/custom_auth_text_form_field.dart';
import 'package:class_f_story/ui/widgets/custom_elevated_button.dart';
import 'package:class_f_story/ui/widgets/custom_logo.dart';
import 'package:class_f_story/ui/widgets/custom_text_button.dart';
import 'package:flutter/material.dart';
class LoginBody extends StatelessWidget {
final _usernameController = TextEditingController();
final _passwordController = TextEditingController();
LoginBody({super.key});
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(16.0),
child: ListView(
children: [
CustomLogo('f-story'),
CustomAuthTextFormField(
text: 'Username',
controller: _usernameController,
),
const SizedBox(height: largeGap),
CustomAuthTextFormField(
text: 'Password',
controller: _passwordController,
),
const SizedBox(height: largeGap),
CustomElevatedButton(
text: '로그인',
click: () {
String temp1 = _usernameController.text.trim();
String temp2 = _passwordController.text.trim();
// TODO - 로그인 처리
// 뷰 모델에 있는 기능인 로그인 행위를 만들어 줄 예정
},
),
CustomTextButton(
text: '회원가입 페이지로 이동',
click: () {
Navigator.pushNamed(context, '/join');
},
),
],
),
);
}
}
- 사용자 세션 관리 (SessionUser)
로그인된 사용자의 정보를 저장할 모델을 생성합니다.
📌 파일 위치: data/model/session_user.dart
class SessionUser {
int? id;
String? username;
String? accessToken;
bool? isLogin;
SessionUser({
required this.id,
required this.username,
required this.accessToken,
required this.isLogin,
});
}
5. 마무리
✅ 정리
- assets/ 폴더 설정 및 로고 추가
- 공통 위젯 (CustomLogo, CustomAuthTextFormField, CustomElevatedButton, CustomTextButton) 구현
- 로그인 화면 (LoginPage, LoginBody) 구성
- 사용자 세션 (SessionUser) 모델 정의
다음 글에서는 Dio 클래스 선언 및 UserRepository 구현 해보겠습니다! 🚀
프로젝트 기본 설정이 궁금하다면??
[Flutter] 블로그 만들기 (기본 프로젝트 설정)
Flutter로 블로그 앱을 만들기 위한 기본 프로젝트 설정을 정리한 글입니다. 필요한 라이브러리, 테마 설정, 네비게이션 및 기본 페이지 구조까지 포함되어 있습니다.1. 프로젝트에 필요한 라이브
seohong.tistory.com
'Flutter > App' 카테고리의 다른 글
[Flutter] 블로그 만들기 - 로그인 기능 구현 (상태관리 및 예외처리) (0) | 2025.02.09 |
---|---|
"[Flutter] 블로그 만들기 - 서버 통신의 모든 것 (Dio 활용) (0) | 2025.02.09 |
[Flutter] 블로그 만들기 - 기본 프로젝트 설정 (1) | 2025.02.08 |
[Flutter] 상태 관리 앱 만들기 (라이브러리 사용) (0) | 2025.02.05 |
[Flutter]상태 관리 앱 만들기 (nheritedWidget 사용) (0) | 2025.02.03 |