상세페이지 만들기.
네비게이터를 사용하면 덮어씌워서 보여줄 수 있음.
웹사이트랑은 다름
새로운 페이지로 이동할 때, 사라지고 그 위에 올리는 것임.
밑에서 부터 덮어지는 것임.
네비게이터를 사용하면 됨.
또 새로운 페이지 덮이는 것이
그렇게 쌓이고 쌓이고 쌓이는 식으로 동작을 함.
그러면 뒤로가기 버튼이 먹게 됨. 그러면 위에서부터 하나씩 제거를 해줌. Stack 식으로 한다고 생각하면 됨.
사용하기
actions: [IconButton(
icon: Icon(Icons.add_box_outlined),
onPressed: (){
Navigator.push(context, route)
},
iconSize: 30,
)]),
context는 부모 MaterialApp을 가리키며 됨.
onPressed: (){
Navigator.push(context,
MaterialPageRoute(builder: (c){return Text('새페이지'); })
);
},
이런식으로 만들면 세페이지 위에 Text 띄워줌. builder 안의 c 는 context를 의미함.
오 여기 Arrow function도 쓸 수 있음
// 이거
MaterialPageRoute(builder: (c){return Text('새페이지'); }));
// 이렇게 사용 가능
MaterialPageRoute(builder: (c) => Text('새페이지');));
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)
),
],
)
);
}
}
Navigator.pop(context); 이거 쓰면 Navigator 스택에서 하나 빼줌.
페이지 많으면 route 를 사용하면 됨.
만드는 법 MaterialApp안에 아래와 같이 넣으면 됨..
MaterialApp(
initialRoute: '/',
routes: {
'/': (context) => Text('첫페이지'),
'/detail': (context) => Text('둘째페이지'),
},
);
이렇게 사용하면 url을 기준으로 이동할 수 있음 그리고 복잡한 페이지들을 위와 같이 관리할 수 있다고 함.
입학상담앱은 메뉴로 메뉴에서 메뉴로 이동해야 하므로 routes를 사용해야할 것 같다.
폰에 있는 이미지 가져오기
환경설정(설치)
- image_picker 설치
# pubspec.yaml image_picker: ^0.8.4+4 - ios/Runner/Info.plist 수정
<key>NSPhotoLibraryUsageDescription</key> <string>사진첩좀 써도 됩니까</string> <key>NSCameraUsageDescription</key> <string>카메라좀 써도 됩니까</string> <key>NSMicrophoneUsageDescription</key> <string>마이크 권한좀 제발</string> - dart 파일에 import 2개 추가
import 'package:image_picker/image_picker.dart'; import 'dart:io';
이미지 가져오기
var picker = ImagePicker();
var image = await picker.pickImage(source: ImageSource.gallery);
// 비디오 가져오기??
await picker.pickVideo 등등...
// 여러개의 이미지 가져오기
await picker.pickMultiImage (배열로 반환)
userImage = File(image.path);
뭐이런식으로 만들어서 변수를 다 전달전달 사용 하면됨..
이미지 사이즈 조정등도 가능함.
- 가로세로 사이즈 조정
- 퀄리티 축소
- 필터 적용 가능 photofilter 라는 애가 있음. (플러터 패키지)
내가 올린 글, 올린 사진 수정 발행버튼 누르면 글 발행 서버 지지고 볶고하는거 말고 state만 수정해서 보여지게 만들 것.
발행까지 할 수 있는 코드임.
import 'package:flutter/gestures.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';
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 data = [];
var userImage;
var userContent;
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;
});
}
getData() async {
var result = await http.get(Uri.parse('https://codingapple1.github.io/app/data.json'));
if(result.statusCode == 200){
// 성공 코드
}else {
// 실패 코드
}
var result2 = jsonDecode(result.body);
setState(() {
data = result2;
});
}
getMore(seq) async{
var result;
if(seq == 0) result = await http.get(Uri.parse('https://codingapple1.github.io/app/more1.json'));
else if(seq == 1) result = await http.get(Uri.parse('https://codingapple1.github.io/app/more2.json'));
else return;
var result2 = jsonDecode(result.body);
setState(() {
data.add(result2);
print(data);
});
}
var scroll = ScrollController();
var isVisible = 1;
@override
void initState() {
// TODO: implement initState
super.initState();
getData();
var getFlag = 0;
scroll.addListener((){
if(scroll.position.userScrollDirection == ScrollDirection.reverse){
setState(() {
isVisible = 0;
});
}
else {
setState(() {
isVisible = 1;
});
}
if(scroll.position.maxScrollExtent == scroll.position.pixels){
getMore(getFlag);
getFlag++;
};
});
}
@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);
});
}
Image.file(userImage);
Navigator.push(context,
MaterialPageRoute(builder: (c)
=> Upload(userImage: userImage, setUserContent: setUserContent, addMyData: addMyData))
);
},
iconSize: 30,
)]),
body: [
Home(jsondata : data, scroll: scroll),
Text('샵페이지')
][tab],
bottomNavigationBar: AnimatedContainer(
duration: Duration(milliseconds: 500),
height: isVisible == 1 ? 60.0 : 0.0,
child: isVisible == 1 ?
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: '샵'),
]
) : Container(
color: Colors.white,
width: MediaQuery.of(context).size.width,
),
),
);
}
}
class Upload extends StatelessWidget {
const Upload({Key? key, this.userImage, this.setUserContent, this.addMyData}) : super(key: key);
final userImage;
final setUserContent;
final addMyData;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: [
IconButton(onPressed: (){
addMyData();
}, icon: Icon(Icons.send))
],
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Image.file(userImage),
Text('이미지업로드화면'),
TextField(onChanged: (text){
setUserContent(text);
},),
IconButton(
onPressed: (){
Navigator.pop(context);
},
icon: Icon(Icons.close)
),
],
)
);
}
}
class Home extends StatefulWidget {
const Home({Key? key, this.jsondata, this.scroll}) : super(key: key);
final jsondata;
final scroll;
@override
State<Home> createState() => _HomeState();
}
class _HomeState extends State<Home> {
@override
Widget build(BuildContext context) {
if(widget.jsondata.isNotEmpty) {
return ListView.builder(
itemCount: widget.jsondata.length, // 몇번 반복?
controller: widget.scroll,
itemBuilder: (context, index){
return
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
widget.jsondata[index]['image'].runtimeType == String
? Image.network(widget.jsondata[index]['image'].toString())
: Image.file(widget.jsondata[index]['image'])
,
Text('좋아요 : ${widget.jsondata[index]["likes"]}'),
Text(widget.jsondata[index]["date"]),
Text(widget.jsondata[index]["content"]),
],
);
});
}
else {
return CircularProgressIndicator();
}
}
}