종류
- MaterialPageRoute()
- CupertinoPageRoute()
- 슬라이드 전환
- import 'package:flutter/cupertino.dart' 상단에 추가해야함
- PageRouteBuilder()
1. 전체 커스터마이징
| GestureDetector( |
| child: Text(widget.data[i]['user']), |
| onTap: () { |
| Navigator.push(context, |
| MaterialPageRoute(builder: (c) => Profile()) |
| ); |
| }, |
| ), |
| GestureDetector( |
| child: Text(widget.data[i]['user']), |
| onTap: () { |
| Navigator.push(context, |
| CupertinoPageRoute(builder: (c) => Profile()) |
| ); |
| }, |
| ), |
| Navigator.push(context, |
| PageRouteBuilder( |
| pageBuilder: (c, a1, a2) => Upload(), |
| transitionsBuilder: (c, a1, a2, child) => FadeTransition(opacity: a1, child: child), |
| transitionDuration: Duration(milliseconds : 500), |
| ), |
| ) |
- pageBuilder: 에는 보여줄 페이지를 return
- transitionsBuilder: 는 파라미터 4개를 입력하고 애니메이션을 return
- 첫째는 context (쓸데없음)
- 둘째는 0에서 1로 증가하는 애니메이션 숫자 (새로운 페이지에 씀)
- 셋째는 0에서 1로 증가하는 애니메이션 숫자 (기존에 보이던 페이지에 씀)
- 넷째는 현재 보여주는 위젯
- FadeTransition()
- opacity: 애니메이션 숫자
- child: 보여줄 위젯
- 이렇게 작성하면 특정 위젯을 서서히 opacity를 0에서 1로 보여줄 수 있음
- transitionDuration : Duration(milliseconds : 500) 이걸로 몇초간 동작할지 설정 가능
- FadeTransition 말고 SlideTransition 써도 됨
| SlideTransition( |
| position: Tween( |
| begin: Offset(-1.0, 0.0), |
| end: Offset(0.0, 0.0), |
| ).animate(a1), |
| child: child, |
| ) |
- 위젯 위치 변경하려면 PositionedTransition()
- 위젯 사이즈를 변경하려면 ScaleTransition()
- 위젯을 가렸다가 보여주려면 SizeTransition()
- 위젯을 회전시키려면 RotationTransition()
- 두 페이지 간에 똑같은 위젯이 있을 때 그걸 유지하면서 페이지 전환하고 싶은 경우 사용
| import 'package:flutter/cupertino.dart'; |
| 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'; |
| import 'package:image_picker/image_picker.dart'; |
| import 'dart:io'; |
| import 'package:shared_preferences/shared_preferences.dart'; |
| import 'dart:convert'; |
| |
| void main() { |
| runApp( |
| MaterialApp( |
| theme: style.theme, |
| home: MyApp() |
| )); |
| } |
| |
| class MyApp extends StatefulWidget { |
| const MyApp({Key? key}) : super(key: key); |
| |
| @override |
| State<MyApp> createState() => _MyAppState(); |
| } |
| |
| class _MyAppState extends State<MyApp> { |
| var tab = 0; |
| var list = [1, 2, 3]; |
| var map = {'name':'john', 'age':20}; |
| var data = []; |
| var userImage; |
| var userContent; |
| |
| saveData() async { |
| var storage = await SharedPreferences.getInstance(); |
| |
| var map = {'age' : 20}; |
| storage.setString('map', jsonEncode(map)); |
| var result = storage.getString('map') ?? '업는데요'; |
| print(jsonDecode(result)['age']); |
| } |
| |
| addMyData() { |
| var myData = { |
| 'id': data.length, |
| 'image': userImage, |
| 'likes': 5, |
| 'date': 'July 25', |
| 'content': userContent, |
| 'liked': false, |
| 'user': 'John Kim' |
| }; |
| setState(() { |
| data.insert(0, myData); |
| }); |
| } |
| setUserContent(a) { |
| setState(() { |
| userContent = a; |
| }); |
| } |
| |
| addData(a) { |
| setState(() { |
| data.add(a); |
| }); |
| } |
| |
| getData() async { |
| var result = await http.get(Uri.parse('https://codingapple1.github.io/app/data.json')); |
| |
| var result2 = jsonDecode(result.body); |
| setState(() { |
| data = result2; |
| }); |
| |
| } |
| |
| @override |
| void initState() { |
| super.initState(); |
| saveData(); |
| getData(); |
| } |
| |
| @override |
| Widget build(BuildContext context) { |
| return Scaffold( |
| appBar: AppBar( |
| title: Text('Instagram'), |
| actions: [ |
| IconButton( |
| icon: Icon(Icons.add_box_outlined), |
| onPressed: () async { |
| var picker = ImagePicker(); |
| var image = await picker.pickImage(source: ImageSource.gallery); |
| if(image != null) { |
| setState(() { |
| userImage = File(image.path); |
| }); |
| } |
| |
| Navigator.push(context, |
| MaterialPageRoute(builder: (c) => Upload( userImage : userImage, setUserContent : setUserContent, addMyData : addMyData) ) |
| ); |
| }, |
| iconSize: 30, |
| ) |
| ]), |
| body: [Home(data : data, addData : addData), Text('샵페이지')][tab], |
| bottomNavigationBar: BottomNavigationBar( |
| showSelectedLabels: false, |
| showUnselectedLabels: false, |
| onTap: (i){ |
| setState(() { |
| tab = i; |
| }); |
| }, |
| items: [ |
| BottomNavigationBarItem(icon: Icon(Icons.home_outlined), label: '홈'), |
| BottomNavigationBarItem(icon: Icon(Icons.shopping_bag_outlined), label: '샵') |
| ], |
| ), |
| ); |
| } |
| } |
| |
| class Home extends StatefulWidget { |
| const Home({Key? key, this.data, this.addData}) : super(key: key); |
| final data, addData; |
| |
| @override |
| State<Home> createState() => _HomeState(); |
| } |
| |
| class _HomeState extends State<Home> { |
| |
| var scroll = ScrollController(); |
| |
| getMore() async { |
| var result = await http.get(Uri.parse('https://codingapple1.github.io/app/more1.json')); |
| var result2 = jsonDecode(result.body); |
| |
| widget.addData(result2); |
| } |
| |
| @override |
| void initState() { |
| super.initState(); |
| scroll.addListener(() { |
| if(scroll.position.pixels == scroll.position.maxScrollExtent) { |
| getMore(); |
| } |
| }); |
| } |
| |
| @override |
| Widget build(BuildContext context) { |
| |
| if (widget.data.isNotEmpty) { |
| return ListView.builder( |
| itemCount: widget.data.length, |
| controller: scroll, |
| itemBuilder: (c, i) { |
| return Column( |
| crossAxisAlignment: CrossAxisAlignment.start, |
| children: [ |
| widget.data[i]['image'].runtimeType == String ? Image.network(widget.data[i]['image']) : Image.file(widget.data[i]['image']), |
| Container( |
| constraints: BoxConstraints(maxWidth: 600), |
| padding: EdgeInsets.all(20), |
| width: double.infinity, |
| child: Column( |
| children: [ |
| GestureDetector( |
| child: Text(widget.data[i]['user']), |
| onTap: () { |
| Navigator.push(context, |
| PageRouteBuilder(pageBuilder: (c, a1, a2) => Profile(), |
| transitionsBuilder: (c, a1, a2, child) => |
| FadeTransition(opacity: a1, child: child) |
| ) |
| ); |
| }, |
| ), |
| Text('좋아요 ${widget.data[i]['likes'].toString()}'), |
| Text(widget.data[i]['date']), |
| Text(widget.data[i]['content']) |
| ], |
| ), |
| ) |
| ], |
| ); |
| } |
| ); |
| } else { |
| return Text('로딩중임'); |
| } |
| } |
| } |
| |
| class Upload extends StatelessWidget { |
| const Upload({Key? key, this.userImage, this.setUserContent, this.addMyData}) : super(key: key); |
| final userImage, setUserContent, addMyData; |
| |
| @override |
| |
| Widget build(BuildContext context) { |
| return Scaffold( |
| appBar: AppBar(actions: [ |
| IconButton(onPressed: () { |
| addMyData(); |
| }, icon: Icon(Icons.send)) |
| ],), |
| body: Column( |
| crossAxisAlignment: CrossAxisAlignment.start, |
| children: [ |
| IconButton( |
| onPressed: (){ |
| Navigator.pop(context); |
| }, |
| icon: Icon(Icons.close) |
| ), |
| Image.file(userImage), |
| Text('이미지업로드화면'), |
| TextField(onChanged: (text) { |
| setUserContent(text); |
| },), |
| ], |
| ) |
| ); |
| } |
| } |
| |
| class Profile extends StatelessWidget { |
| const Profile({Key? key}) : super(key: key); |
| |
| @override |
| Widget build(BuildContext context) { |
| return Scaffold( |
| appBar: AppBar(), |
| body: Text('프로필페이지') |
| ); |
| } |
| } |