상세페이지 만들기 (Navigator)
- 버튼 클릭 시 사진을 업로드 할 수 있는 페이지 만들기
- 현재는 Tab을 활용해서 보여지는 페이지를 다르게 했는데
- 이번에는 Navigator를 사용해서 보여주는 방법을 배우기!
- Naviagor는 기존 페이지에 새로운 페이지를 덮어씌워서 페이지를 보여주게 한다.
- 웹과 다르게 모바일에서는 새로운 페이지를 열 때 기존 페이지에 새로운 페이지를 덮어씌우게 된다.
- 예시로 카카오톡에서 새로운 링크를 클릭 시 새로운 페이지가 기존 페이지를 덮어씌우는 것과 같다.
- 그래서 기존 Tab과의 차이점으로는 Stack으로 관리하기에 뒤로가기 버튼이 잘 작동하게 된다.
- 현재 AppBar에 만들어 뒀던 add_box_outlined 아이콘을 클릭 시 작동하기 위해 onPressed 메서드 안에 코드를 작성하기
- Navigator.push(context, route)를 작성하는데
- 이때 주의점으로 context에는 MaterialApp이 들어있는 context를 넣어줘야하기에 확인을 꼭 잘 해줘야 한다.
- 그리고 route에는 MaterialPageRoute() 위젯을 넣고
- 해당 위젯의 값으로는 builder: ( ){ } 을 추가하며 인자 값을 하나 넣어줘야한다. 이때 builder로 context를 만들어주기에 필요하면 context를 기입하고 아니면 그냥 c를 넣어주면 된다.
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Instagram'),
actions: [
IconButton(
onPressed: (){
Navigator.push(context,
MaterialPageRoute(builder: (c){
return Text('새로운 페이지');
})
);
},
icon: Icon(Icons.add_box_outlined)
)
],
),
- 여기서 Arrow Function을 사용하는 방법을 짚고 넘어가자면
- return 문이 하나만 있을 경우에 사용하는 것으로 아래와 같이 변경할 수 있다.
// 변경전
onPressed: (){Navigator.push(context,
MaterialPageRoute(builder: (c){
return Text('새로운 페이지');
})
);
},
// 변경후
onPressed: (){Navigator.push(context,
MaterialPageRoute(builder: (c) => Text('새로운 페이지')
)
);
},
- 이제 버튼을 클릭 시 다른 페이지로 이동하고 해당 페이지에서 닫기 버튼을 클릭 시 창을 닫도록 하는 코드 작성하기
- 한번 더 정리하자면 페이지 열게 하는 건
- 페이지 닫게 하는 건
import 'dart:js_interop';
import 'package:flutter/material.dart';
import './style.dart' as style;
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:flutter/rendering.dart';
void main() {
runApp(
MaterialApp(
theme: style.theme,
home: MyApp()
)
);
}
class MyApp extends StatefulWidget {
MyApp({super.key});
@override
State createState() => _MyAppState();
}
class _MyAppState extends State {
var homeData = [];
appendData(value){
setState(() {
homeData.add(value);
});
}
getData() async{
var result = await http.get(Uri.parse('<https://codingapple1.github.io/app/data.json>'));
if (result.statusCode == 200) {
setState(() {
homeData = jsonDecode(result.body);
});
} else {
print('실패');
}
}
@override
void initState() {
super.initState();
getData();
}
// 0: home, 1: shop
var tab = 0;
changeTab(tabNumber){
setState(() {
tab = tabNumber;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Instagram'),
actions: [
IconButton(
onPressed: (){
Navigator.push(context,
MaterialPageRoute(builder: (c) => Upload()
)
);
},
icon: Icon(Icons.add_box_outlined)
)
],
),
);
}
}
// Upload
class Upload extends StatelessWidget {
const Upload({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('이미지업로드화면'),
IconButton(
onPressed: (){
Navigator.pop(context);
},
icon: Icon(Icons.close)
),
],
)
);
}
}
- 그리고 현재는 Tap으로 페이지를 보여주고 했는데 페이지가 너무 많다면 routes를 사용하면 된다.
- 이렇게 작성하게 되면 React에서 했던 Routing 기능을 적용할 수 있다.
- 기본 경로를 initialRoute로 기본 경로를 설정 하고 routes로 경로 별 return 할 요소를 전달하기
void main() {
runApp(
MaterialApp(
theme: style.theme,
initialRoute: '/',
routes: {
'/': (c) => MyApp(),
'/mypage': (c) => Text('마이 페이지')
},
)
);
}