Untuk menyimpan image ke filesystem, kita perlu 2 package untuk mengatur path, yaitu:
path_provider : https://pub.dev/packages/path_provider
path : https://pub.dev/packages/path
Untuk instalasi package, tambahkan dependencies pada pubsec.yaml. Pada saat tutorial dibuat versi yang digunakan adalah seperti code dibawah. SIlakan lihat link pub.dev diatas untuk instalasi versi terbaru.
path_provider: ^1.6.27 path: ^1.7.0
Buka file widgets/add_image.dart, import library yang diperlukan
import 'package:path/path.dart' as path;
import 'package:path_provider/path_provider.dart' as syspaths;
Lalu tambahkan code berikut pada fungsi _takePic(). Code dibawah adalah untuk mengambil path dari aplikasi cool spot.
final appDir = await syspaths.getApplicationDocumentsDirectory();
final fileName = path.basename(pickedFile.path);
final savedImage = await _img.copy('${appDir.path}/$fileName');
widget.onSelectImg(savedImage);
Berikut isi lengkap dari widgets/add_image.dart
import 'dart:io'; import 'package:flutter/material.dart'; import 'package:image_picker/image_picker.dart'; import 'package:path/path.dart' as path; import 'package:path_provider/path_provider.dart' as syspaths; class AddImage extends StatefulWidget { final Function onSelectImg; AddImage(this.onSelectImg); @override _AddImageState createState() => _AddImageState(); } class _AddImageState extends State<AddImage> { File _img; final picker = ImagePicker(); Future<void> _takePic() async { final pickedFile = await picker.getImage(source: ImageSource.camera, maxWidth: 600); if (pickedFile == null) { return; } setState(() { _img = File(pickedFile.path); }); final appDir = await syspaths.getApplicationDocumentsDirectory(); final fileName = path.basename(pickedFile.path); final savedImage = await _img.copy('${appDir.path}/$fileName'); widget.onSelectImg(savedImage); } @override Widget build(BuildContext context) { return Row( children: [ Container( width: 100, height: 100, decoration: BoxDecoration( border: Border.all(width: 1, color: Colors.grey), ), child: _img != null ? Image.file( _img, fit: BoxFit.cover, width: double.infinity, ) : Text( 'No Image', textAlign: TextAlign.center, ), alignment: Alignment.center, ), SizedBox( width: 10, ), Expanded( child: FlatButton.icon( icon: Icon(Icons.camera), label: Text('Take Pic'), textColor: Theme.of(context).primaryColor, onPressed: _takePic, ), ), ], ); } }
Untuk file lainya juga terdapat perubahan, namun lebih ke proses menambahkan data ke models, menampilkan cool spot di list.
Karena tujuan dari tutorial adalah membahas akses ke native device, perubahan di file lainnya tidak akan dibahas, namun kami sediakan dibawah. SIlakan dicopy.
File providers/cool_spot.dart
import 'dart:io'; import 'package:flutter/foundation.dart'; //import 'package:image_picker/image_picker.dart'; import '../models/spot.dart'; class CoolSpot with ChangeNotifier { List<Spot> _items = []; List<Spot> get items { return [..._items]; } void addSpot(String pickedTitle, File pickedImg) { final newSPot = Spot( id: DateTime.now().toString(), img: pickedImg, title: pickedTitle, loc: null); _items.add(newSPot); notifyListeners(); } }
File screens/spot_list_scr.dart
import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import './add_spot_scr.dart'; import '../providers/cool_spot.dart'; class SpotListScr extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('My Cool Spot'), actions: <Widget>[ IconButton( icon: Icon(Icons.add), onPressed: () { Navigator.of(context).pushNamed(AddSpotScr.routeNm); }, ), ], ), body: Consumer<CoolSpot>( child: Center( child: Text('Belum ada cool spot nih..'), ), builder: (ctx, coolSpot, ch) => coolSpot.items.length <= 0 ? ch : ListView.builder( itemCount: coolSpot.items.length, itemBuilder: (ctx, i) => ListTile( leading: CircleAvatar( backgroundImage: FileImage(coolSpot.items[i].img), ), title: Text(coolSpot.items[i].title), onTap: () {}, //ke detail page ), ), ), ); } }
File screens/add_spot_scr.dart
import 'dart:io'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../widgets/add_image.dart'; import '../providers/cool_spot.dart'; class AddSpotScr extends StatefulWidget { static const routeNm = '/add-spot'; @override _AddSpotScrState createState() => _AddSpotScrState(); } class _AddSpotScrState extends State<AddSpotScr> { final _titleCtrl = TextEditingController(); File _pickedImg; void _selectImg(File pickedImg) { _pickedImg = pickedImg; } void _saveSpot() { if (_titleCtrl.text.isEmpty || _pickedImg == null) { return; } Provider.of<CoolSpot>(context, listen: false) .addSpot(_titleCtrl.text, _pickedImg); Navigator.of(context).pop(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Add New Spot"), ), body: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: <Widget>[ Expanded( child: SingleChildScrollView( child: Padding( padding: const EdgeInsets.all(8.0), child: Column( children: <Widget>[ TextField( decoration: InputDecoration(labelText: "Title"), controller: _titleCtrl, ), SizedBox( height: 10, ), AddImage(_selectImg), ], ), ), ), ), RaisedButton.icon( icon: Icon(Icons.add), label: Text('Add Spot'), elevation: 0, materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, color: Theme.of(context).accentColor, onPressed: _saveSpot, ) ], ), ); } }
