1. 페이지 이동
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(),
},
);
}
}
- MaterialApp 설정
- initialRoute : 앱 실행 시 제일 먼저 보이는 화면 설정
- routes: 페이지 이동 경로 설정
// stle 입력 후 자동 완성
class LoginPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("LoginPage")),
body: Align(
alignment: Alignment(0, 0),
// double 가능 -> 소숫점으로 위치 설정 가능
child: ElevatedButton(
onPressed: () {
Navigator.pushNamed(context, "/home");
},
child: Text("로그인"),
),
),
);
}
}
- Align
- 위젯의 위치를 자유롭게 설정 가능
- alignment
- Alignment(-1, -1): 화면 제일 왼쪽 위
- Alignment(0, 0): 중앙
- Alignment(1, 1): 제일 오른쪽 아래
- double로 설정 가능
- Navigator.pushNamed(context, "/home")
- 경로 /home 으로 이동
- 이동할 경우 왼쪽 위에 뒤로 가기 버튼 자동 생성
// stle 입력 후 자동 완성
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("HomePage")),
body: Align(
alignment: Alignment(0, 0), // (-1, -1) ~ (1, 1)
child: ElevatedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text("돌아가기"),
),
),
);
}
}
- Navigator.pop(context)
- 현재 화면을 닫고 이전 화면으로 되돌아 갑니다.
- Flutter의 네비게이션 시스템에서 화면을 스택(stack)으로 관리합니다.
- pop 메서드는 현재 스택의 맨 위에 있는 화면을 제거하고, 그 아래에 있는 화면을 표시하게 됩니다.
2. 문자 입력 시 올라오는 키보드가 버튼 가리지 않게 설정
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: LoginPage(),
);
}
}
class LoginPage extends StatelessWidget {
const LoginPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: true,
body: Column(
children: [
Flexible(
child: ListView(
shrinkWrap: true,
children: [
Container(
height: 400,
color: Colors.redAccent,
),
TextFormField(),
TextFormField(),
TextFormField(),
],
),
),
ElevatedButton(onPressed: () {}, child: Text("로그인"))
],
),
);
}
}
- resizeToAvoidBottomInset
- 키보드가 나타날 때 화면의 레이아웃이 어떻게 조정될지를 제어합니다.
- true로 설정할 경우 키보드가 나타날 때 Scaffold의 body가 자동으로 크기를 조정하여 키보드에 의해 가려지지 않도록 합니다.
- shrinkWrap: true
- ListView의 세로 길이 설정
- 스크롤 가능한 위젯이 자식 위젯의 크기에 따라 축소됩니다.
- 스크롤 가능한 부모 위젯 안에서 자식 위젯이 공간을 낭비하지 않도록 도와줍니다.
- Flexible 위젯
- Row, Column, 또는 Flex 컨테이너의 자식 위젯으로, 자식이 main axis에 따라 유연하게 확장되도록 합니다.
- TextFormField
- 사용자 입력을 위한 필드입니다.
- ElevatedButton을 ListView 아래에 위치시킬 경우 키보드가 올라와도 버튼이 가려지지 않습니다.


- 키보드가 나타나면 로그인 버튼이 위로 올라간 것을 볼 수 있습니다.
3. 사용자가 입력한 값을 전송
class LoginPage extends StatelessWidget {
LoginPage({super.key});
String? username;
final password = TextEditingController();
final email = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: true,
body: ListView(
children: [
Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
onChanged: (value) {
username = value;
},
decoration: InputDecoration(
filled: true,
fillColor: Colors.yellow, // 배경색 설정
border: OutlineInputBorder( // 외곽선 설정 (옵션)
borderRadius: BorderRadius.circular(12.0),
),
),
),
),
CustomInput(password, "패스워드를 입력하세요", obsecure: true),
CustomInput(email, "이메일을 입력하세요"),
ElevatedButton(
onPressed: () {
fetch(username!.trim(), password.text.trim());
},
child: Text("로그인"),
),
],
),
],
),
);
}
}
- TextFormField
- onChanged: 입력값에 변화가 있을 경우 실행됩니다.
- value: 입력값
- fillColor: 배경색 설정
- filled: true → 배경색을 채워줍니다.
- border: OutlineInputBorder: 외곽선 설정
- borderRadius → 외곽선을 둥글게 합니다.
- username!.trim()
!
연산자는 null이 아님을 보장합니다. → Dart는 해당 변수가 null이 아님을 인식하고, null safety 경고를 무시하게 됩니다.
- trim()
- 문자열의 앞뒤 공백을 제거합니다.
class CustomInput extends StatelessWidget {
CustomInput(this.controller, this.hint, {this.obsecure = false});
final controller;
final hint;
final obsecure;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
controller: controller,
obscureText: obsecure,
decoration: InputDecoration(
hintText: "${hint}",
suffixIcon: Icon(Icons.password),
focusedBorder: OutlineInputBorder(),
enabledBorder: OutlineInputBorder(),
),
),
);
}
}
void fetch(String username, String password) {
print("$username과 $password를 전송하였습니다");
}
- controller → TextEditingController에 담긴 값에 접근할 수 있습니다.
- obscureText: true
- 비밀번호를 알아 볼 수 없는 문자로 바꿔줍니다.
- hintText
- TextFormField에 힌트 텍스트를 설정할 수 있습니다.
- suffixIcon: Icon(Icons.password)
- TextFormField 제일 끝에 패스워드 아이콘을 넣습니다.
- prefixIcon: 앞에 아이콘을 넣습니다.
- focusedBorder
- 입력 필드가 포커스를 받았을 때의 테두리 스타일을 정의합니다.
- 사용자가 입력 필드에 터치하거나 클릭하여 텍스트를 입력할 때 활성화됩니다.
- enabledBorder
- 입력 필드가 활성화되었지만 포커스를 받지 않았을 때의 테두리 스타일을 정의합니다.
- 입력 필드가 사용 가능한 상태일 때 기본적으로 표시되는 테두리 스타일입니다.
Share article