2023. 3. 11. 15:38ㆍ모바일어플개발/Flutter
안녕하세요~ totally 개발자입니다.
Form, validator, TextFormField, Navigator.pushNamed의 매개변수 전달해서 다른 클래스에서 받기
Form, validator, TextFormField를 사용해서 잘 제출되었을 때 다른 페이지로 넘어갈 수 있는 예제를 살펴 보도록 하겠습니다.
플러터에서는 Form 위젯을 제공하여 양식을 만들 수 있습니다. 그리고 TextFormField를 사용하여 autoFocus, validator, onSaved 등 여러가지 속성을 같이 활용할 수 있습니다.
Step 1: MaterialApp 부분에 home 부분을 주석 처리해주시고 initialRoute와 routes를 다음처럼 정의해주도록 합니다. 이 routes 정의를 통해 pushNamed로 페이지 라우팅을 해줄 수 있습니다. (리액트랑 원리가 같습니다) 그리고 initialRoute로 최초 라우팅 위치를 지정해줍니다. 그리고 / 일 때는 메인 MyHomePage() 클래스를 렌더링해줍니다.

Step 2: 다음처럼 지정해줍니다. GlobalKey<FormState>()를 사용하여 앱에서 유일한 key를 만들어서 Form 안에서 FormState를 사용할 수 있도록 합니다. FormState는 save, reset, validate 등의 속성을 사용할 수 있게 도와줍니다. 그리고 사용자 이름과 이메일 주소를 받을 수 있게 변수를 만들어줍니다.

Step 3: user.dart 파일을 새로 생성해서 아래처럼 만들어줍니다. 매개변수를 전달하기 위한 목적의 모델링입니다.

Step 4: 별도의 usernameInput() 위젯을 만들어서 분리합니다. 69번째 autofocus: true,는 이 페이지가 열렸을 때 바로 초점을 주어 입력할 수 있도록 만들어주는 것이고 validator에서 입력값을 검증할 수 있습니다. 77번째 onSaved는 추후 save 메소드가 발생되었을 때 변수에 값을 할당해줍니다. 78-86번째 줄을 통해 스타일을 적용해줍니다.

Step 5: emailInput() 위젯도 위와 비슷하게 작성해줍니다.

Step 6: 제출 버튼을 위한 submitButton() 위젯도 생성해줍니다. 여기에서 115~121번째 줄에 있는 내용을 보면 116번째에서 validate가 성공적으로 된 경우 117번쨰에서 save를 하여 변수를 할당해주고, 118번째 pushNamed를 통해 success 페이지로 옮겨주고 매개변수로 사용자 이름, 이메일을 제공해주도록 했습니다. import 'user.dart'; 해주셔야 합니다.


Step 7: 다음처럼 build 부분을 입력해줍니다. 50번째에 key를 넣어주시고 Column 안에 위에서 생성한 위젯들을 차례로 넣어주시면 됩니다. const SizedBox(height: 15)를 사용한 것은 사이 공간을 주기 위함입니다.

Step 8: successPage.dart 파일을 생성하여 다음처럼 입력해줍니다.

Step 9: 14번째 줄을 통해서 위에서 전달한 매개변수들을 전달 받을 수 있도록 합니다. 17~22번째 줄을 통해 뒤로 가기 버튼을 구현하여 원래 페이지로 되돌아갈 수 있습니다. 그리고 30-31번째 줄을 통해 전달 받은 매개변수들인 username과 email를 화면에 표시할 수 있습니다.

Step 10: 결과를 확인해본 모습입니다.

[전체 소스 코드]
main.dart
import 'package:flutter/material.dart'; | |
import 'package:project/successPage.dart'; | |
import 'user.dart'; | |
void main() { | |
runApp(const MyApp()); | |
} | |
class MyApp extends StatelessWidget { | |
const MyApp({super.key}); | |
// This widget is the root of your application. | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
title: 'Flutter Demo', | |
theme: ThemeData( | |
primarySwatch: Colors.blue, | |
), | |
// home: const MyHomePage(), | |
initialRoute: '/', | |
routes: { | |
'/': (context) => const MyHomePage(), | |
'/success': (context) => const SuccessPage(), | |
}); | |
} | |
} | |
class MyHomePage extends StatefulWidget { | |
const MyHomePage({super.key}); | |
@override | |
State<MyHomePage> createState() => _MyHomePageState(); | |
} | |
class _MyHomePageState extends State<MyHomePage> { | |
final _key = GlobalKey<FormState>(); | |
late String _username, _email; | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar( | |
title: const Text("Test App"), | |
), | |
body: Container( | |
padding: const EdgeInsets.all(15), | |
child: Form( | |
key: _key, | |
child: Column( | |
children: [ | |
usernameInput(), | |
const SizedBox( | |
height: 15, | |
), | |
emailInput(), | |
const SizedBox(height: 10), | |
submitButton(), | |
], | |
), | |
), | |
), | |
); | |
} | |
Widget usernameInput() { | |
return TextFormField( | |
autofocus: true, | |
validator: (val) { | |
if (val!.isEmpty) { | |
return 'The input is empty.'; | |
} else { | |
return null; | |
} | |
}, | |
onSaved: (username) => _username = username as String, | |
decoration: const InputDecoration( | |
border: OutlineInputBorder(), | |
hintText: 'Input your username.', | |
labelText: 'Username', | |
labelStyle: TextStyle( | |
fontSize: 18, | |
fontWeight: FontWeight.bold, | |
), | |
), | |
); | |
} | |
Widget emailInput() { | |
return TextFormField( | |
autofocus: true, | |
validator: (val) { | |
if (val!.isEmpty) { | |
return 'The input is empty.'; | |
} else { | |
return null; | |
} | |
}, | |
onSaved: (email) => _email = email as String, | |
decoration: const InputDecoration( | |
border: OutlineInputBorder(), | |
hintText: 'Input your email address.', | |
labelText: 'Email Address', | |
labelStyle: TextStyle( | |
fontSize: 18, | |
fontWeight: FontWeight.bold, | |
), | |
), | |
); | |
} | |
Widget submitButton() { | |
return ElevatedButton( | |
onPressed: () { | |
if (_key.currentState!.validate()) { | |
_key.currentState!.save(); | |
Navigator.pushNamed(context, '/success', | |
arguments: User(_username, _email)); | |
} | |
}, | |
child: Container( | |
padding: const EdgeInsets.all(15), | |
child: const Text( | |
"SUBMIT", | |
style: TextStyle( | |
fontSize: 18, | |
), | |
), | |
), | |
); | |
} | |
} |
user.dart
class User { | |
final String username; | |
final String email; | |
User(this.username, this.email); | |
} |
successPage.dart
import 'package:flutter/material.dart'; | |
import 'package:project/user.dart'; | |
class SuccessPage extends StatefulWidget { | |
const SuccessPage({super.key}); | |
@override | |
State<SuccessPage> createState() => _SuccessPageState(); | |
} | |
class _SuccessPageState extends State<SuccessPage> { | |
@override | |
Widget build(BuildContext context) { | |
final User args = ModalRoute.of(context)!.settings.arguments as User; | |
return Scaffold( | |
appBar: AppBar( | |
leading: IconButton( | |
onPressed: () => Navigator.of(context).pop(), | |
icon: const Icon( | |
Icons.arrow_back_ios, | |
), | |
), | |
title: const Text("Test App"), | |
), | |
body: Center( | |
child: Column( | |
mainAxisSize: MainAxisSize.min, | |
children: [ | |
const Text("Successfully submitted!"), | |
Text("Username: ${args.username}"), | |
Text("Email: ${args.email}"), | |
], | |
), | |
), | |
); | |
} | |
} |
[유튜브 강좌 영상]
'모바일어플개발 > Flutter' 카테고리의 다른 글
[041] 플러터 (Flutter) 배우기 - Firebase Auth 연동1 (이메일/비밀번호 사용) (0) | 2023.03.13 |
---|---|
[040] 플러터 (Flutter) 배우기 - Firebase(파이어베이스) 연동 (7) | 2023.03.13 |
[038] 플러터 (Flutter) 배우기 - WebView (웹뷰) 구현하기 (0) | 2023.03.04 |
[037] 플러터 (Flutter) 배우기 - 푸시 알림 보내기(local notification) (4) | 2023.02.21 |
[036] 플러터 (Flutter) 배우기 - 상태 관리6 (GetX 사용 - Reactive State Manager & RxList 사용) (0) | 2023.02.20 |