Flutter: type _file is not a subtype of type widget - image

i am getting type _file is not a subtype of type widget error and this is my code.
i am trying to move my cropped image that i cropped in cropImage to editImage widget.
_getFromGallery() async {
XFile? pickedFile = await ImagePicker().pickImage(
source: ImageSource.gallery,
maxWidth: 1800,
maxHeight: 1800,
);
_cropImage(pickedFile!.path);
}
_cropImage(pickedFile) async {
File? croppedImage = await ImageCropper.cropImage(
sourcePath: pickedFile,
maxWidth: 1080,
maxHeight: 1080,
);
if (croppedImage != null) {
image = croppedImage;
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => editImage(croppedImage)));
}
}
Widget editImage(croppedImage) {
final Future<String> _croppedImage = Future<String>.delayed(
const Duration(seconds: 2),
() => 'Data Loaded',
);
return FutureBuilder<String>(
future: _croppedImage,
builder: (BuildContext context, snapshot) {
if (snapshot.hasData) {}
return Center(
child: Scaffold(
appBar: AppBar(
title: Text('Edit Image'),
),
body: Container(child: image = croppedImage),
),
);
});
}
}
can i get the right code example? im stuck in this for weeks. please help.

flutter root tree can show only classes who inherited from the widget class. change your code to this :
Widget editImage(croppedImage) {
final Future<String> _croppedImage = Future<String>.delayed(
const Duration(seconds: 2),
() => 'Data Loaded',
);
return FutureBuilder<String>(
future: _croppedImage,
builder: (BuildContext context, snapshot) {
if (snapshot.hasData) {}
return Center(
child: Scaffold(
appBar: AppBar(
title: Text('Edit Image'),
),
body:croppedImage !=null? Container(child: Image.file(croppedImage!)):null,
),
);
});
} }

Related

Flutter FutureBuilder shows data then disappears when calling Rest API (Backend Laravel)

I'm running a flutter application with a laravel backend and I have some issues.
The problem is the FutureBuilder show data then it disappears; Sometimes length==4 then it turns to 0 and shows 'no data' in Scaffold🙄
The same when I refresh the code.
PS: I'm running laravel on localhost and using a real device to test.
Environment: Android Studio, Windows 10, Real device
Laravel project: https://github.com/brakenseddik/blog_api_laravel
Flutter project: https://github.com/brakenseddik/blog_api_flutter
import 'package:http/http.dart' as http;
class Repository {
String _baseUrl = 'http://192.168.1.2:8000/api';
httpGet(String api) async {
return await http.get(_baseUrl + '/' + api);
}
}
here the homepage source code
import 'dart:convert';
import 'package:blog_api/models/post_model.dart';
import 'package:blog_api/services/post_service.dart';
import 'package:flutter/material.dart';
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
PostService _postService = PostService();
List<PostModel> _list = List<PostModel>();
Future<List<PostModel>> _getPosts() async {
var result = await _postService.getAllPosts();
_list = [];
if (result != null) {
var blogPosts = json.decode(result.body);
blogPosts.forEach((post) {
PostModel model = PostModel();
setState(() {
model.title = post['title'];
model.details = post['details'];
model.imageUrl = post['featured_image_url'];
_list.add(model);
});
});
}
return _list;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Blog App'),
),
body: FutureBuilder(
future: _getPosts(),
builder:
(BuildContext context, AsyncSnapshot<List<PostModel>> snapshot) {
print('length of list ${_list.length}');
_list = snapshot.data;
if (_list.length == 0) {
return Center(
child: Text('No data'),
);
} else if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
} else {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Card(
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Image.network(
snapshot.data[index].imageUrl,
height: 150,
// width: double.maxFinite,
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
snapshot.data[index].title,
style: TextStyle(
fontSize: 18, fontWeight: FontWeight.w700),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
snapshot.data[index].details.substring(0, 25),
style: TextStyle(
fontSize: 16,
),
),
),
],
),
),
);
});
}
},
));
}
}
And the PostService
import 'package:blog_api/repository/repository.dart';
class PostService {
Repository _repository;
PostService() {
_repository = Repository();
}
getAllPosts() async {
return await _repository.httpGet('get-posts');
}
}
I think the issue is that you're calling setState in _getPosts(). This will rebuild everything and never give the response to the FutureBuilder. Just run the code without setState:
blogPosts.forEach((post) {
PostModel model = PostModel();
model.title = post['title'];
model.details = post['details'];
model.imageUrl = post['featured_image_url'];
_list.add(model);
FutureBuilder will initially call its builder with a snapshot that doesn't have any data yet. Once it receives the data, it will call its builder again. Because of this, if (_list.length == 0) will result in a NPE, since _list is null.
I would try changing the order of the if statements:
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
} else if (snapshot.data.length == 0) {
return Center(
child: Text('No data'),
);
} else {
return ListView.builder(
//...
}
future: _getPosts(),
Don't do that. This means every time build is called, you are querying your API again.
Create a variable of type Future<List<PostModel>>, assign _getPosts() to it once and then use that variable with your FutureBuilder.

setState() or markNeedsBuild() error when trying to pick image from gallery and take image with camera flutter

I'm trying to take an image from my gallery or capture with camera immediately the upload page is built. I created a dialog to show the two options but I'm getting the error
setState() or markNeedsBuild() called during build.
when I run on my emulator.
Any help will be appreciated. Thank you
This is my code
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
class UploadPage extends StatefulWidget {
#override
_UploadPageState createState() => _UploadPageState();
}
class _UploadPageState extends State<UploadPage> {
PickedFile image;
final picker=ImagePicker();
takeImage(mContext){
return showDialog(
context: mContext,
builder: (context){
return SimpleDialog(
title: Text("New post"),
children: [
SimpleDialogOption(
child: Text("Upload from from gallery"),
onPressed: ()async{
Navigator.pop(context);
final file=await picker.getImage(
source: ImageSource.gallery,
// maxHeight: 600,
// maxWidth: 970,
);
setState(() {
this.image=file;
});
},
),
SimpleDialogOption(
child: Text("Capture with camera"),
onPressed: ()async{
Navigator.pop(context);
final file=await picker.getImage(
source: ImageSource.camera,
maxHeight: 600,
maxWidth: 970,
);
setState(() {
this.image=file;
});
},
),
SimpleDialogOption(
child: Text("Cancel",style: TextStyle(color: Colors.red),),
onPressed: (){
Navigator.pop(context);
},
),
],
);
}
);
}
#override
Widget build(BuildContext context) {
return takeImage(context);
}
}
showDialog displays a dialog above the current contents of the app and it returns the future.
You can call showDialog after build
class UploadPage extends StatefulWidget {
#override
_UploadPageState createState() => _UploadPageState();
}
class _UploadPageState extends State<UploadPage> {
PickedFile image;
final picker = ImagePicker();
takeImage(mContext) {
return showDialog(
context: mContext,
builder: (context) {
return SimpleDialog(
title: Text("New post"),
children: [
SimpleDialogOption(
child: Text("Upload from from gallery"),
onPressed: () async {
Navigator.pop(context);
final file = await picker.getImage(
source: ImageSource.gallery,
// maxHeight: 600,
// maxWidth: 970,
);
setState(() {
this.image = file;
});
},
),
SimpleDialogOption(
child: Text("Capture with camera"),
onPressed: () async {
Navigator.pop(context);
final file = await picker.getImage(
source: ImageSource.camera,
maxHeight: 600,
maxWidth: 970,
);
setState(() {
this.image = file;
});
},
),
SimpleDialogOption(
child: Text(
"Cancel",
style: TextStyle(color: Colors.red),
),
onPressed: () {
Navigator.pop(context);
},
),
],
);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
'Take Picture',
),
),
body: Center(
child: FlatButton(
color: Colors.blue,
onPressed: () {
takeImage(context);
},
child: Text(
'Select Image',
style: TextStyle(color: Colors.white),
),
),
),
);
}
}

Flutter Save & Load Image - Image Picker/Image crop

I'm trying to make a profile picture screen in flutter. I have used this 2 plugin (image crop and image picker) for select and edit the image.
class ProfilePage extends StatefulWidget {
#override
__ProfilePageState createState() => __ProfilePageState();
}
class __ProfilePageState extends State<ProfilePage> {
File _pickedImage;
String _imagepath;
#override
void initState() {
super.initState();
LoadImage();
}
#override
Widget build(BuildContext context) {
return Scaffold(
// appBar: AppBar(
// title: Text('Profile'),
// ),
body: ListView(
children: <Widget>[
Center(
child: CircleAvatar(
radius: 80,
child: _imagepath == null ? Text('Profile image') : null,
backgroundImage:
_imagepath != null ? FileImage(File(_imagepath)) : null,
),
),
SizedBox(height: 10),
RaisedButton(
child: Text('Select image'),
onPressed: () {
_showPickOptionDialog(context);
},
)
],
),
);
}
_loadPicker(ImageSource source) async {
File picked = await ImagePicker.pickImage(source: source);
if (picked != null) {
_cropImage(picked);
SaveImage(picked.path);
}
LoadImage();
Navigator.pop(context);
}
_cropImage(File picked) async {
File cropped = await ImageCropper.cropImage(
androidUiSettings: AndroidUiSettings(
toolbarTitle: "Modifica immagine",
statusBarColor: Colors.green,
toolbarColor: Colors.green,
toolbarWidgetColor: Colors.white,
),
sourcePath: picked.path,
// aspectRatioPresets: [
// CropAspectRatioPreset.original,
// CropAspectRatioPreset.ratio16x9,
// CropAspectRatioPreset.ratio4x3,
// ],
maxWidth: 800,
);
if (cropped != null) {
setState(() {
_pickedImage = cropped;
});
}
}
void _showPickOptionDialog(BuildContext context) {
showDialog(
context: context,
builder: (context) => AlertDialog(
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ListTile(
title: Text('select image from gallery'),
onTap: () {
_loadPicker(ImageSource.gallery);
}),
ListTile(
title: Text('Scatta una foto'),
onTap: () {
_loadPicker(ImageSource.camera);
},
),
],
),
));
}
void SaveImage(path) async {
SharedPreferences saveimage = await SharedPreferences.getInstance();
saveimage.setString("imagepath", path);
}
void LoadImage() async {
SharedPreferences saveimage = await SharedPreferences.getInstance();
setState(() {
_imagepath = saveimage.getString("imagepath");
});
}
}
Code works but it only save the picked image instead of the cropped one.
I've tried many times but I can't see the error, sorry about that..
could you help me?
Thanks!
when you use Future you should return value and use this value with .then()
try this:
class ProfilePage extends StatefulWidget {
#override
__ProfilePageState createState() => __ProfilePageState();
}
class __ProfilePageState extends State<ProfilePage> {
File _pickedImage;
String _imagepath;
#override
void initState() {
super.initState();
LoadImage();
}
#override
Widget build(BuildContext context) {
return Scaffold(
// appBar: AppBar(
// title: Text('Profile'),
// ),
body: ListView(
children: <Widget>[
Center(
child: CircleAvatar(
radius: 80,
child: _imagepath == null ? Text('Profile image') : null,
backgroundImage:
_imagepath != null ? FileImage(File(_imagepath)) : null,
),
),
SizedBox(height: 10),
RaisedButton(
child: Text('Select image'),
onPressed: () {
_showPickOptionDialog(context);
},
)
],
),
);
}
_loadPicker(ImageSource source) async {
File picked = await ImagePicker.pickImage(source: source);
if (picked != null) {
_cropImage(picked).then(File cropped){
SaveImage(cropped.path);
}
}
LoadImage();
Navigator.pop(context);
}
Future<File> _cropImage(File picked) async {
File cropped = await ImageCropper.cropImage(
androidUiSettings: AndroidUiSettings(
toolbarTitle: "Modifica immagine",
statusBarColor: Colors.green,
toolbarColor: Colors.green,
toolbarWidgetColor: Colors.white,
),
sourcePath: picked.path,
// aspectRatioPresets: [
// CropAspectRatioPreset.original,
// CropAspectRatioPreset.ratio16x9,
// CropAspectRatioPreset.ratio4x3,
// ],
maxWidth: 800,
);
if (cropped != null) {
setState(() {
_pickedImage = cropped;
});
}
return cropped;
}
void _showPickOptionDialog(BuildContext context) {
showDialog(
context: context,
builder: (context) => AlertDialog(
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ListTile(
title: Text('select image from gallery'),
onTap: () {
_loadPicker(ImageSource.gallery);
}),
ListTile(
title: Text('Scatta una foto'),
onTap: () {
_loadPicker(ImageSource.camera);
},
),
],
),
));
}
void SaveImage(path) async {
SharedPreferences saveimage = await SharedPreferences.getInstance();
saveimage.setString("imagepath", path);
}
void LoadImage() async {
SharedPreferences saveimage = await SharedPreferences.getInstance();
setState(() {
_imagepath = saveimage.getString("imagepath");
});
}
}
Found the solution by editing this part:
if (cropped != null) {
_pickedImage = cropped;
SaveImage(_pickedImage.path);
LoadImage();
setState(() {});
}
}

How can I select and upload Multiple images in Flutter

I tried to find how to select and upload multiple images in flutter but most of the plugins are not working or I did not understand them well. I found little application but it selects and upload only one picture. How to change this code that user can select and upload multiple pictures or is there any other alternatives. Please write in details, i am freshman in coding. Thanks in advance.
import 'package:flutter/material.dart';
import 'dart:io';
import 'package:http/http.dart' as http;
import 'package:image_picker/image_picker.dart';
import 'package:mime/mime.dart';
import 'dart:convert';
import 'package:http_parser/http_parser.dart';
import 'package:toast/toast.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Image Upload Demo',
theme: ThemeData(primarySwatch: Colors.pink),
home: ImageInput());
}
}
class ImageInput extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _ImageInput();
}
}
class _ImageInput extends State<ImageInput> {
// To store the file provided by the image_picker
File _imageFile;
// To track the file uploading state
bool _isUploading = false;
String baseUrl = 'http://YOUR_IPV4_ADDRESS/flutterdemoapi/api.php';
void _getImage(BuildContext context, ImageSource source) async {
File image = await ImagePicker.pickImage(source: source);
setState(() {
_imageFile = image;
});
// Closes the bottom sheet
Navigator.pop(context);
}
Future<Map<String, dynamic>> _uploadImage(File image) async {
setState(() {
_isUploading = true;
});
// Find the mime type of the selected file by looking at the header bytes of the file
final mimeTypeData =
lookupMimeType(image.path, headerBytes: [0xFF, 0xD8]).split('/');
// Intilize the multipart request
final imageUploadRequest =
http.MultipartRequest('POST', Uri.parse(baseUrl));
// Attach the file in the request
final file = await http.MultipartFile.fromPath('image', image.path,
contentType: MediaType(mimeTypeData[0], mimeTypeData[1]));
// Explicitly pass the extension of the image with request body
// Since image_picker has some bugs due which it mixes up
// image extension with file name like this filenamejpge
// Which creates some problem at the server side to manage
// or verify the file extension
imageUploadRequest.fields['ext'] = mimeTypeData[1];
imageUploadRequest.files.add(file);
try {
final streamedResponse = await imageUploadRequest.send();
final response = await http.Response.fromStream(streamedResponse);
if (response.statusCode != 200) {
return null;
}
final Map<String, dynamic> responseData = json.decode(response.body);
_resetState();
return responseData;
} catch (e) {
print(e);
return null;
}
}
void _startUploading() async {
final Map<String, dynamic> response = await _uploadImage(_imageFile);
print(response);
// Check if any error occured
if (response == null || response.containsKey("error")) {
Toast.show("Image Upload Failed!!!", context,
duration: Toast.LENGTH_LONG, gravity: Toast.BOTTOM);
} else {
Toast.show("Image Uploaded Successfully!!!", context,
duration: Toast.LENGTH_LONG, gravity: Toast.BOTTOM);
}
}
void _resetState() {
setState(() {
_isUploading = false;
_imageFile = null;
});
}
void _openImagePickerModal(BuildContext context) {
final flatButtonColor = Theme.of(context).primaryColor;
print('Image Picker Modal Called');
showModalBottomSheet(
context: context,
builder: (BuildContext context) {
return Container(
height: 150.0,
padding: EdgeInsets.all(10.0),
child: Column(
children: <Widget>[
Text(
'Pick an image',
style: TextStyle(fontWeight: FontWeight.bold),
),
SizedBox(
height: 10.0,
),
FlatButton(
textColor: flatButtonColor,
child: Text('Use Camera'),
onPressed: () {
_getImage(context, ImageSource.camera);
},
),
FlatButton(
textColor: flatButtonColor,
child: Text('Use Gallery'),
onPressed: () {
_getImage(context, ImageSource.gallery);
},
),
],
),
);
});
}
Widget _buildUploadBtn() {
Widget btnWidget = Container();
if (_isUploading) {
// File is being uploaded then show a progress indicator
btnWidget = Container(
margin: EdgeInsets.only(top: 10.0),
child: CircularProgressIndicator());
} else if (!_isUploading && _imageFile != null) {
// If image is picked by the user then show a upload btn
btnWidget = Container(
margin: EdgeInsets.only(top: 10.0),
child: RaisedButton(
child: Text('Upload'),
onPressed: () {
_startUploading();
},
color: Colors.pinkAccent,
textColor: Colors.white,
),
);
}
return btnWidget;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Image Upload Demo'),
),
body: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 40.0, left: 10.0, right: 10.0),
child: OutlineButton(
onPressed: () => _openImagePickerModal(context),
borderSide:
BorderSide(color: Theme.of(context).accentColor, width: 1.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.camera_alt),
SizedBox(
width: 5.0,
),
Text('Add Image'),
],
),
),
),
_imageFile == null
? Text('Please pick an image')
: Image.file(
_imageFile,
fit: BoxFit.cover,
height: 300.0,
alignment: Alignment.topCenter,
width: MediaQuery.of(context).size.width,
),
_buildUploadBtn(),
],
),
);
}
}
I used that package:
dependencies:
multi_image_picker: ^4.6.7
Ex:
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:multi_image_picker/multi_image_picker.dart';
void main() => runApp(new MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
List<Asset> images = List<Asset>();
String _error;
#override
void initState() {
super.initState();
}
Widget buildGridView() {
if (images != null)
return GridView.count(
crossAxisCount: 3,
children: List.generate(images.length, (index) {
Asset asset = images[index];
return AssetThumb(
asset: asset,
width: 300,
height: 300,
);
}),
);
else
return Container(color: Colors.white);
}
Future<void> loadAssets() async {
setState(() {
images = List<Asset>();
});
List<Asset> resultList;
String error;
try {
resultList = await MultiImagePicker.pickImages(
maxImages: 300,
);
} on Exception catch (e) {
error = e.toString();
}
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) return;
setState(() {
images = resultList;
if (error == null) _error = 'No Error Dectected';
});
}
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(
title: const Text('Plugin example app'),
),
body: Column(
children: <Widget>[
Center(child: Text('Error: $_error')),
RaisedButton(
child: Text("Pick images"),
onPressed: loadAssets,
),
Expanded(
child: buildGridView(),
)
],
),
),
);
}
}
Add dependecy of image_picker:
image_picker: ^0.8.4+3
Then make a method for selectImages():
final ImagePicker imagePicker = ImagePicker();
List<XFile>? imageFileList = [];
void selectImages() async {
final List<XFile>? selectedImages = await
imagePicker.pickMultiImage();
if (selectedImages!.isNotEmpty) {
imageFileList!.addAll(selectedImages);
}
print("Image List Length:" + imageFileList!.length.toString());
setState((){});
}
Create a builder for showing selected Images:
return Scaffold(
appBar: AppBar(
title: Text('Multiple Images'),
),
body: SafeArea(
child: Column(
children: [
ElevatedButton(
onPressed: () {
selectImages();
},
child: Text('Select Images'),
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: GridView.builder(
itemCount: imageFileList!.length,
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3),
itemBuilder: (BuildContext context, int index) {
return Image.file(File(imageFileList![index].path),
fit: BoxFit.cover,);
}),
),
),
],
),
));
Complete Source code available in github link...
https://github.com/NishaJain24/multi_image_picker

flutter why can't I show my image from camera?

I don't know why my code don't show the image from the camera..
I tried this code and the var isn't empty, but doesn't show the image in the container..
I don't get any error neither..
thanks for your help.
class _MyAppState extends State {
File _imagen;
Future getImagen() async {
var imagen = await ImagePicker.pickImage(source: ImageSource.camera);
setState(() {
_imagen = imagen;
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('picker'),
),
body: Container(
child: Center(
child: _imagen == null
? new Text('no hay imagen')
: new Image.file(_imagen),
),
),
floatingActionButton: new FloatingActionButton(
onPressed: getImagen,
child: Icon(Icons.camera),
),
),
);
}
}
this issue is related to the image size. Adding this solved the issue for me.
await ImagePicker.pickImage(source: ImageSource.camera, maxWidth: 480, maxHeight: 600);
For further clarification, check out this github issue
change the image picker to latest
image_picker: ^0.6.0+10

Resources