반응형
Flutter 프로필 사진 등록/변경하기
이번에는 내정보의 프로필 사진 등록/변경에 대해 알아보겠다.
ImagePicker 위젯을 사용할 것이다. 사용법은 아래와 같다.
동작 원리
0. 화면 구성
1. Profile camera 아이콘 클릭 => 카메라로 찍기 / 갤러리에서 가져오는 모달창 생성
2. 카메라로 찍기 또는 갤러리에서 가져오기 + 변경된 내용 반영하기
0. 화면 구성
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: appBarWidget('Regist Profile'),
body: Padding(
padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 20),
child: ListView(
children: <Widget>[
imageProfile(),
SizedBox(height: 20),
nameTextField(),
SizedBox(height: 20),
],
)
)
);
}
1. Profile camera 아이콘 클릭 => 카메라로 찍기 / 갤러리에서 가져오는 모달창 생성
Widget imageProfile() {
return Center(
child: Stack(
children: <Widget>[
CircleAvatar(
radius: 80,
backgroundImage: _imageFile == null
? AssetImage('assets/profile.jfif')
: FileImage(File(_imageFile.path)),
),
Positioned(
bottom: 20,
right: 20,
child: InkWell(
onTap: () {
// 클릭시 모달 팝업을 띄워준다.
showModalBottomSheet(context: context, builder: ((builder) => bottomSheet()));
},
child: Icon(
Icons.camera_alt,
color: secondaryTextColor,
size: 40,
),
)
)
],
),
);
}
// 카메라 아이콘 클릭시 띄울 모달 팝업
Widget bottomSheet() {
return Container(
height: 100,
width: MediaQuery.of(context).size.width,
margin: EdgeInsets.symmetric(
horizontal: 20,
vertical: 20
),
child: Column(
children: <Widget>[
Text(
'Choose Profile photo',
style: TextStyle(
fontSize: 20,
),
),
SizedBox(height: 20,),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
FlatButton.icon(
icon: Icon(Icons.camera, size: 50,),
onPressed: () {
takePhoto(ImageSource.camera);
},
label: Text('Camera', style: TextStyle(fontSize: 20),),
),
FlatButton.icon(
icon: Icon(Icons.photo_library, size: 50,),
onPressed: () {
takePhoto(ImageSource.gallery);
},
label: Text('Gallery', style: TextStyle(fontSize: 20),),
)
],
)
],
)
);
}
2. 카메라로 찍기 또는 갤러리에서 가져오기 + 변경된 내용 반영하기
// 카메라로 찍거나 갤러리에서 가져온 사진 컨트롤하기 위한 변수
PickedFile _imageFile; // 카메라/갤러리에서 사진 가져올 때 사용함 (image_picker)
final ImagePicker _picker = ImagePicker(); // 카메라/갤러리에서 사진 가져올 때 사용함 (image_picker)
...
// 프로필 사진 셋팅 부분
CircleAvatar(
radius: 80,
backgroundImage: _imageFile == null
? AssetImage('assets/profile.jfif')
: FileImage(File(_imageFile.path)),
),
...
// 카메라 찍거나 갤러리에서 가져오는 메소드
takePhoto(ImageSource source) async {
final pickedFile = await _picker.getImage(source: source);
setState(() {
_imageFile = pickedFile;
});
}
전체 소스
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:my_flutter_example_app/constants/constants.dart';
import 'package:my_flutter_example_app/widgets/widgets.dart';
class RegistProfile extends StatefulWidget {
@override
_RegistProfileState createState() => _RegistProfileState();
}
class _RegistProfileState extends State<RegistProfile> {
PickedFile _imageFile; // 카메라/갤러리에서 사진 가져올 때 사용함 (image_picker)
final ImagePicker _picker = ImagePicker(); // 카메라/갤러리에서 사진 가져올 때 사용함 (image_picker)
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: appBarWidget('Regist Profile'),
body: Padding(
padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 20),
child: ListView(
children: <Widget>[
imageProfile(),
SizedBox(height: 20),
nameTextField(),
SizedBox(height: 20),
],
)
)
);
}
Widget imageProfile() {
return Center(
child: Stack(
children: <Widget>[
CircleAvatar(
radius: 80,
backgroundImage: _imageFile == null
? AssetImage('assets/profile.jfif')
: FileImage(File(_imageFile.path)),
),
Positioned(
bottom: 20,
right: 20,
child: InkWell(
onTap: () {
showModalBottomSheet(context: context, builder: ((builder) => bottomSheet()));
},
child: Icon(
Icons.camera_alt,
color: secondaryTextColor,
size: 40,
),
)
)
],
),
);
}
Widget nameTextField() {
return TextFormField(
decoration: InputDecoration(
border: OutlineInputBorder(
borderSide: BorderSide(
color: primaryTextColor,
),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: secondaryTextColor,
width: 2,
),
),
prefixIcon: Icon(
Icons.person,
color: primaryTextColor,
),
labelText: 'Name',
hintText: 'Input your name'
),
);
}
Widget bottomSheet() {
return Container(
height: 100,
width: MediaQuery.of(context).size.width,
margin: EdgeInsets.symmetric(
horizontal: 20,
vertical: 20
),
child: Column(
children: <Widget>[
Text(
'Choose Profile photo',
style: TextStyle(
fontSize: 20,
),
),
SizedBox(height: 20,),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
FlatButton.icon(
icon: Icon(Icons.camera, size: 50,),
onPressed: () {
takePhoto(ImageSource.camera);
},
label: Text('Camera', style: TextStyle(fontSize: 20),),
),
FlatButton.icon(
icon: Icon(Icons.photo_library, size: 50,),
onPressed: () {
takePhoto(ImageSource.gallery);
},
label: Text('Gallery', style: TextStyle(fontSize: 20),),
)
],
)
],
)
);
}
takePhoto(ImageSource source) async {
final pickedFile = await _picker.getImage(source: source);
setState(() {
_imageFile = pickedFile;
});
}
}
반응형
댓글