Flutter - 코딩마스터하기|사진 업로드,게시하기1
unique post key 만들기
firebase에 collection에 post와 uniqui한 키도 만들어 줄 것이다. 이미지는 firebase에 storage를 이용할 것이다. 우선 repo - helper 폴더에 generate_post_key.dart를 만들어 준다. 그리고 키를 가져오는 메소드를 만들어 주자. String getNewPostKey를 만들어주고 (UserModel userModel)을 받아온다. 그리고 파일이름 부분을 정해주는데 "${DateTime.now().millisecondsSinceEpoch}_${userModel.userKey}";로 만들어서 시간과 유저의 유니크 아이디로 조합해준다.
String getNewPostKey(UserModel userModel) => "${DateTime.now().millisecondsSinceEpoch}_${userModel.userKey}";
send post key to share screen
share_post_screen에서 postkey를 받아오기위해서 final String postKey;를 추가해주고 @required this.postKey를 추가해준다. 그리고 my_gallery에 가서 기존에 timeInMilli로 파일 이름을 지정해주는 부분을 지우고 final String postKey = getNewPostKey(Provider.of<UserModelState>(context, listen: false,).userModel);를 넣어준다. 그리고 try 안에 .png 앞의 $timeInMilli도 $postKey로 변경해준다. 그 하단에 SharePostScreen에 postKey: postKey,를 추가해주면 된다. 그리고 take_photo에서도 _attemptTakePhoto 메소드도 똑같이 변경해주면 된다.
my_gallery.dart
List<Widget> getImages(BuildContext context, GalleryState galleryState) {
return galleryState.images
.map((localImage) => InkWell(
onTap: () async {
Uint8List bytes = await localImage.getScaledImageBytes(
galleryState.localImageProvider, 0.3);
final String postKey =
getNewPostKey(Provider.of<UserModelState>(context, listen: false,).userModel);
// final String timeInMilli = DateTime.now()
// .microsecondsSinceEpoch
// .toString(); //1970-01-01 부터 millisecond의 시간
try {
//((await getTemporaryDirectory()).path+'$timeInMilli.png')로 만들어도 되지만 위험성이 있어서 사용x Join 추천
final path = join((await getTemporaryDirectory()).path,
'$postKey.png'); //getTemporaryDirectory는 Future사용 .path로 임시저장폴더 주소, 파일명 순서로 경로임
File imageFile = File(path)..writeAsBytesSync(bytes);
Navigator.of(context).push(MaterialPageRoute(
builder: (_) => SharePostScreen(imageFile,postKey: postKey,)));
} catch (e) {}
},
child: Image(
fit: BoxFit.cover,
image: DeviceImage(localImage ,scale: 0.2,),
),
))
.toList();
}
take_photo.dart
void _attemptTakePhoto(CameraState cameraState, BuildContext context) async {
final String postKey =
getNewPostKey(Provider.of<UserModelState>(context, listen: false,).userModel);
// final String timeInMilli = DateTime.now()
// .microsecondsSinceEpoch
// .toString(); //1970-01-01 부터 millisecond의 시간
try {
//((await getTemporaryDirectory()).path+'$timeInMilli.png')로 만들어도 되지만 위험성이 있어서 사용x Join 추천
final path = join((await getTemporaryDirectory()).path,
'$postKey.png'); //getTemporaryDirectory는 Future사용 .path로 임시저장폴더 주소, 파일명 순서로 경로임
await cameraState.controller.takePicture(path);
File imageFile = File(path);
Navigator.of(context).push(MaterialPageRoute(
builder: (_) => SharePostScreen(
imageFile,
postKey: postKey,
)));
} catch (e) {}
}
app bar layout on share post
이미지 공유하는 부분의 레이아웃을 바꿔보자. share_post_screen.dart에서 Image.file을 Scaffold로 감싸준다. 그리고 appbar:AppBar()를 넣어준다. title에는 Text로 New Post 를 넣어주고 actions 에는 FlatButton을 넣어줘서 child에 Text로 Share를 해주고 textScaleFactor은 1.4 글자색을 blue를 해주면 appBar 부분은 완성이다.
Widget build(BuildContext context) {
return Scaffold(
body: Image.file(imageFile),
appBar: AppBar(
title: Text("New Post"),
actions: [
FlatButton(
onPressed: () {},
child: Text(
"Share",
textScaleFactor: 1.4,
style: TextStyle(
color: Colors.blue,
),
),
),
],
),
);
}
caption part in share post body layout
이미지를 올릴때 글 부분과 사진을 임시적으로 보는 앱바 바로 하단의 한줄짜리 부분이다. 이를 위해서 image.file를 ListTile로 감사준다. 그리고 ListTile를 ListView로 다시한번 감싸준다. leading부분에 image부분을 넣어주고 width에 size.width/6, height도 똑같이 해준다. fit에 BoxFit.cover로 해주면 된다. title 부분은 글 내용 부분으로 TextField를 이용한다. decoration 옵션에 InputDecoration을 넣어주고 hintText에 'Write a caption'을 해준다. 그럼 밑줄이 나오는데 이를 해결하기 위해 InputDecoration에 border에 InputBorder.none을 해주면 된다.
body: ListView(
children: [
ListTile(
contentPadding: EdgeInsets.symmetric(
vertical: common_gap,
horizontal: common_gap,
),
leading: Image.file(
imageFile,
width: size.width / 6,
height: size.width / 6,
fit: BoxFit.cover,
),
title: TextField(
decoration: InputDecoration(
hintText: 'Write a caption....', border: InputBorder.none),
),
),
],
),
section button layout in share post
이미지 캡션을 달아주는 부분 아래에 태그와 위치를 추가하는 부분을 만들어 보자. 모양을 보면 ListTile로 만들어 주면 될 것으로 보인다. 우선 Divider로 칸을 나눠준다. color은 grey[300]으로 해주고 thickness 1, height 1 로해준다. 이를 get _divider =>의 메소드로 빼준다. 그리고 그 아래에 ListTile로 title에 Text에 'Tag People' 를 해주고 style에 FntWeight.w400으로 두께를 준다. traing는 Icons.navigate_next로 준다. dense는 true로 해주고 contentPadding를 symmetric으로 horizontal에 common_gap만큼 주면 된다. 이 부분은 add location 과 똑같으므로 메소드로 _sectionButton(String title)로 빼줘서 title 부분만 받아서 쓴다.
body: ListView(
children: [
_captionWithImage(),
_divider,
_sectionButton('Tag People'),
_divider,
_sectionButton('Add Location'),
],
),
Divider get _divider =>
Divider(
color: Colors.grey[300],
thickness: 1, //진짜 선의 두께를 나타내는 부분 이부분 외는 흰색임
height: 1, // 선이 나오는 부분이 아니라 패딩같이 차지하는 범위라 생각하면됨
);
ListTile _sectionButton(String title) {
return ListTile(
title: Text(
title,
style: TextStyle(fontWeight: FontWeight.w400),
),
trailing: Icon(
Icons.navigate_next,
),
dense: true,
contentPadding: EdgeInsets.symmetric(
horizontal: common_gap,
),
);
}