본문 바로가기
Flutter

[flutter] 블로그 만들기 02 - 로그인 페이지 구성하기

by JINJINC 2025. 2. 3.
728x90
반응형

기본 파일 (이미지)

로그인 ui 환경 구현하기

디자인 시안

1. assets 허용하기

assets:
  - assets/

2. 폴더 구조

3. Login page

import 'package:flutter/material.dart';

import 'widgets/login_body.dart';

class LoginPage extends StatelessWidget {
  const LoginPage({super.key});

  @override
  Widget build(BuildContext context) {
    return LoginBody();
  }
}

4. login body

import 'package:class_f_story/_core/constants/size.dart';
import 'package:class_f_story/ui/pages/custom_logo.dart';
import 'package:class_f_story/ui/widgets/custom_auth_text_form_field.dart';
import 'package:class_f_story/ui/widgets/custom_text_button.dart';
import 'package:flutter/material.dart';

import '../../../../widgets/custom_elevated_button.dart';

class LoginBody extends StatelessWidget {
  final TextEditingController _usernameController = TextEditingController();
  final TextEditingController _passwordController = TextEditingController();
  LoginBody({super.key});

  @override
  Widget build(BuildContext context) {
    return SafeArea(
        child: Scaffold(
      body: ListView(
        padding: EdgeInsets.all(16),
        children: [
          CustomLogo(title: 'f-story'),
          CustomAuthTextFormField(
              text: 'Username', textEditingController: _usernameController),
          const SizedBox(height: mediumGap),
          CustomAuthTextFormField(
            text: 'Password',
            textEditingController: _passwordController,
            obscureText: true,
          ),
          const SizedBox(height: largeGap),
          CustomElevatedButton(
            text: '로그인',
            click: () {
              String _uid = _usernameController.text.trim();
              String _pass = _passwordController.text.trim();
              //TODO : 뷰모델에 있는 기능인 login 행위를 만들어 줄 예정  reapostiroy로 넘겨주기
            },
          ),
          CustomTextButton(
              text: '회원가입 페이지로 이동',
              click: () {
                Navigator.pushNamed(context, '/join');
              })
        ],
      ),
    ));
  }
}

5. custom_logo

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({required this.title, super.key});

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        const SizedBox(
          height: xLargeGap,
        ),
        SvgPicture.asset(
          'assets/logo.svg',
          width: 70,
          height: 70,
        ),
        Text(
          '$title',
          style: TextStyle(fontSize: 40, fontWeight: FontWeight.bold),
        ),
        const SizedBox(
          height: largeGap,
        ),
      ],
    );
  }
}

6. custom_auth_text_form_field

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 textEditingController;

  const CustomAuthTextFormField(
      {required this.text,
      required this.textEditingController,
      this.obscureText = false,
      super.key});

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(text),
        const SizedBox(height: smallGap),
        TextFormField(
          controller: textEditingController,
          obscureText: obscureText,
          decoration: InputDecoration(
            hintText: 'Enter $text',
            enabledBorder: OutlineInputBorder(
              borderRadius: BorderRadius.circular(20),
              borderSide: BorderSide(color: Colors.grey),
            ),
            focusedBorder: OutlineInputBorder(
              //손가락 터치시 활성화된 디자인 설정
              borderRadius: BorderRadius.circular(20),
            ),
            errorBorder: OutlineInputBorder(
              // 유효성 검사실패시 사용되는 디자인 설정
              borderRadius: BorderRadius.circular(20),
              borderSide: BorderSide(color: Colors.red),
            ),
            focusedErrorBorder: OutlineInputBorder(
              //에러가 발생 후 손가락 터치했을때 디자인 설정
              borderRadius: BorderRadius.circular(20),
              borderSide: BorderSide(color: Colors.red),
            ),
          ),
        ),
      ],
    );
  }
}

7. custom_elevated_button

import 'package:class_f_story/_core/constants/size.dart';
import 'package:flutter/material.dart';

class CustomElevatedButton extends StatelessWidget {
  final String text;
  //final Function(String) click;  동적 으로 받기 위해 생략
  final click;
  CustomElevatedButton({required this.text, required this.click, super.key});

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
        style: ElevatedButton.styleFrom(
            backgroundColor: Colors.white12,
            minimumSize: Size(double.infinity, 50),
            foregroundColor: Colors.black,
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(20.0),
            )),
        onPressed: click,
        child: Text('$text'));
  }
}

8. custom_text_button

import 'package:flutter/material.dart';

class CustomTextButton extends StatelessWidget {
  final String text;
  //내장되어있는 빌트인 타입
  final VoidCallback click;
  const 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),
        ));
  }
}
728x90
반응형

댓글