replacing image in file manager does not replace the image in app - image

I uploaded an image on firebase storage. and to access said image on my flutter app, I first download it to the device and then use FileImage to display the image. However, if the image is changed, it still displays the previous one... Here's my code
var error;
Future getImage() async {
try {
var image = await ImagePicker.pickImage(
source: ImageSource.gallery,
);
await FirebaseStorage.instance
.ref()
.child(userMap['uid'])
.putFile(image)
.onComplete;
await FirebaseStorage.instance
.ref()
.child(userMap['uid'])
.writeToFile(File(path))
.future;
setState(() {
profile = FileImage(File(path));
});
} catch (e) {
error = e;
}
}
The following code displays the image...
GestureDetector(
onTap: () {
getImage();
},
child: CircleAvatar(
child: Icon(
Icons.add_a_photo,
color: color2.withOpacity(0.5),
),
radius: widget.height * 0.05,
backgroundColor: color3,
backgroundImage: profile,
),
),
please help

I could recommend you another way to solve your issue.
First thing, you don't need to use FileImage because it's very difficult control you cache
with it.
Try the next code:
Future<String> uploadImage(File image) async {
var reference = FirebaseStorage.insance.ref().child(userMap['uid']);
var uploadTask = reference.putFile(image); // you can just put your file like that
var snapshot = await uploadTask.onComplete;
var location = await snapshot.ref.getDownloadURL(); // and get url with it with this code
return location.toString()
}
Future getImage() async {
try {
var image = await ImagePicker.pickImage(
source: ImageSource.gallery,
);
profile = await uploadImage(image)
setState((){});
}
catch (e) {
error = e;
}
}
after you get your url address with uploadImage, please use library: https://pub.dev/packages/cached_network_image. It's perfect for work with images.
GestureDetector(
onTap: () {
getImage();
},
child: CircleAvatar(
child: Icon(
Icons.add_a_photo,
color: color2.withOpacity(0.5),
),
radius: widget.height * 0.05,
backgroundColor: color3,
backgroundImage: CachedNetworkImageProvider(
imageUrl: profile,
placeholder: (context, url) => CircularProgressIndicator(),
errorWidget: (context, url, error) => Icon(Icons.error),
),
),
),

Related

Flutter: type _file is not a subtype of type widget

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,
),
);
});
} }

How to get original image size in Dart Image.network?

The following code gives Division by null error,
#override
Widget build(BuildContext context) {
Image image = Image.network(data['image-url']);
double widthToHeight = image.width / image.height;
if(widthToHeight <= 0.2) {
return NewsTileSmall(data: data);
} else {
return NewsTileLarge(data: data);
}
}
Best if, I could use a function to set the value of double widthToHeight.
In your build method you need to preload image.
Image image = new Image.network('image-url');
Completer<ui.Image> completer = new Completer<ui.Image>();
image.image
.resolve(new ImageConfiguration())
.addListener(ImageStreamListener(ImageInfo info, bool _) {
completer.complete(info.image));
})
Then you need to use FutureBuilder
FutureBuilder<ui.Image>(
future: completer.future,
builder: (BuildContext context, AsyncSnapshot<ui.Image> snapshot) {
if (snapshot.hasData){
return your image Widget}
else{
return placeholder widget
}
completed build method
import 'dart:ui' as ui;
Image image = Image.network('image url');
final completer = Completer<ui.Image>();
image.image
.resolve(const ImageConfiguration()).
addListener(ImageStreamListener((ImageInfo info, bool syncCall) => completer.complete(info.image)));
return Scaffold(
appBar: AppBar(
title: const Text("Image Dimensions Example"),
),
body: FutureBuilder<ui.Image>(
future: completer.future,
builder: (BuildContext context, AsyncSnapshot<ui.Image> snapshot) {
if (snapshot.hasData) {
return Text(
'${snapshot.data.width}x${snapshot.data.height}',
);
} else {
return const Text('Loading...');
}
},
)
);
});
To get the original size of a network image, you could use the image_pixels library.
Here is how to use it:
Widget buildContent(BuildContext context, String url) {
final width = MediaQuery.of(context).size.width; // This is the screen size width
final height = MediaQuery.of(context).size.height; // This is the screen size height
Image nimg = Image.network(url); // Preload the network image
return Stack(children: [
Center(
child: Image(
image: nimg.image,
fit: BoxFit.fill,
width: width,
height: height,
)
),
// Wrap the widget that need to access the original image size in ImagePixels
ImagePixels(
imageProvider: nimg.image,
builder: (context, img) {
return Positioned(
// Place a widget on top of the image, it's position related to the original image size
top: 92.0 * (height/img.height),
left: 137.0 * (width/img.width),
child: InkWell(
onTap: () {
print("On tap");
},
child:
Container(
width: 50,
height: 50,
color: Colors.red,
),
)
);
},
)
]);
}

Please help on file uploading using Flutter and Laravel

I'm trying to upload images and other different types of files using Flutter mobile sdk and Laravel api. Here is my Flutter code :
class _MyHomePageState extends State<MyHomePage> {
File _image;
Future getImageGallery() async {
var imageFile = await ImagePicker.pickImage(source: ImageSource.gallery);
setState(() {
_image = imageFile;
});
}
Future getImageCamera() async {
var imageFile = await ImagePicker.pickImage(source: ImageSource.camera);
setState(() {
_image = imageFile;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Center(
child: _image == null
? Text('No image selected')
: Image.file(_image),
),
RaisedButton(
child: Icon(Icons.image),
onPressed: getImageGallery,
),
RaisedButton(
child: Icon(Icons.camera_alt),
onPressed: getImageCamera,
),
RaisedButton(
child: Icon(Icons.file_upload),
onPressed: () {
upload(_image);
},
),
],
),
),
);
}
Future upload(File imageFile) async {
print(imageFile.path);
var stream = http.ByteStream(DelegatingStream.typed(imageFile.openRead()));
var length = await imageFile.length();
var uri = Uri.parse('https://api.tredlr.com/api/upload');
var request = http.MultipartRequest('POST', uri);
var multipartFile = http.MultipartFile('image', stream, length,
filename: basename(imageFile.path));
request.files.add(multipartFile);
var response = await request.send();
print(response);
print(response.stream);
print(response.statusCode);
if (response.statusCode == 200) {
print('uploaded');
} else {
print('not uploaded');
}
}
}
and here is my Laravel code :
$photo = $request->file("image");
$ext = $photo->getClientOriginalExtension();
$fileName = rand(10000, 50000) . '.' .$ext;
$thumbSm = 'thumb_sm' . rand(10000, 50000) . '.' .$ext;
$image = Image::make($request->file('image'));
$image->save(base_path().'/public/'. $fileName);
$image->resize(120, 120);
$image->save(base_path().'/public/'. $thumbSm);
Future _test(File file) async {
Dio dio = new Dio();
file.existsSync();
String fileName = file.path.split('/').last;
FormData formData = new FormData.fromMap({
"image": await MultipartFile.fromFile(file.path,filename: fileName)
});
response = await dio.post("http://you ip address/api/route", data: formData);
}

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

Check image is loaded in Image.network widget in flutter

I am new to Flutter. I try to load network images using image.network widget. it's working fine but sometimes it takes time to load. I added tap listener to image.network during tap I need to check image is fully loaded or not based on the result I need to redirect the page. how to check image is loaded or not?
Code:
new Image.network('http://via.placeholder.com/350x150')
Any help will be appreciated, thank you in advance
You may use the loadingBuilder which is inbuilt feature from flutter for Image.Network
I did it as below:
Image.network(imageURL,fit: BoxFit.cover,
loadingBuilder:(BuildContext context, Widget child,ImageChunkEvent loadingProgress) {
if (loadingProgress == null) return child;
return Center(
child: CircularProgressIndicator(
value: loadingProgress.expectedTotalBytes != null ?
loadingProgress.cumulativeBytesLoaded / loadingProgress.expectedTotalBytes!
: null,
),
);
},
),
for this kind of issues it's good to use the cached_network_image
so you can provide a placeholder when the image is loading and an error widget in case a resource fails to load
String url = "http://via.placeholder.com/350x150";
CachedNetworkImage(
imageUrl: url,
placeholder: (context,url) => CircularProgressIndicator(),
errorWidget: (context,url,error) => new Icon(Icons.error),
),
for ones who do not need to cache the image can use meet_network_image package,
The package basic usage :
MeetNetworkImage(
imageUrl:
"https://random.dog/3f62f2c1-e0cb-4077-8cd9-1ca76bfe98d5.jpg",
loadingBuilder: (context) => Center(
child: CircularProgressIndicator(),
),
errorBuilder: (context, e) => Center(
child: Text('Error appear!'),
),
)
In addition, you can do that by yourself with using a FutureBuilder,
We need to get data with http call that way, we need to import http before import you also need to add pubspec.yaml and run the command flutter packages get
import 'package:http/http.dart' as http;
FutureBuilder(
// Paste your image URL inside the htt.get method as a parameter
future: http.get(
"https://random.dog/3f62f2c1-e0cb-4077-8cd9-1ca76bfe98d5.jpg"),
builder: (BuildContext context, AsyncSnapshot<http.Response> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
return Text('Press button to start.');
case ConnectionState.active:
case ConnectionState.waiting:
return CircularProgressIndicator();
case ConnectionState.done:
if (snapshot.hasError)
return Text('Error: ${snapshot.error}');
// when we get the data from the http call, we give the bodyBytes to Image.memory for showing the image
return Image.memory(snapshot.data.bodyBytes);
}
return null; // unreachable
},
);
This way it will start loading, then it will show the loading of the image loading and then the image. Best option if you don't want to use external libs.
Image.network(
imgUrl,
height: 300,
fit: BoxFit.contain,
frameBuilder: (_, image, loadingBuilder, __) {
if (loadingBuilder == null) {
return const SizedBox(
height: 300,
child: Center(child: CircularProgressIndicator()),
);
}
return image;
},
loadingBuilder: (BuildContext context, Widget image, ImageChunkEvent? loadingProgress) {
if (loadingProgress == null) return image;
return SizedBox(
height: 300,
child: Center(
child: CircularProgressIndicator(
value: loadingProgress.expectedTotalBytes != null
? loadingProgress.cumulativeBytesLoaded / loadingProgress.expectedTotalBytes!
: null,
),
),
);
},
errorBuilder: (_, __, ___) => Image.asset(
AppImages.withoutPicture,
height: 300,
fit: BoxFit.fitHeight,
),
)
thank you for your comment thats help to resolve the situation that how to know if the image is loaded or not hope that help
I use a StatefulWidget
need a editing depend on your AffichScreen
situation :
-i have an url that i enter
-if url is correct affich the image if not affich an icon
-if empty affich a Text()
-precacheImage check if the url is correct if not give an error and change _loadingimage(bool) to false to affich the icon eror
-i use a NetworkImage to check with precacheImage and before affich use a Image.network
bool _loadingimage;
ImageProvider _image;
Image _imagescreen;
#override
void initState() {
_loadingimage = true;
_imageUrlfocusNode.addListener(_updateImageUrl);
super.initState();
}
#override
void dispose() {
_imageUrlfocusNode.removeListener(_updateImageUrl);
_quantityfocusNode.dispose();
_imageUrlConroller.dispose();
_imageUrlfocusNode.dispose();
super.dispose();
}
void _updateImageUrl() {
setState(() {
_image = NetworkImage(_imageUrlConroller.text);
});
if (!_imageUrlfocusNode.hasFocus) {
if (_imageUrlConroller.text.isNotEmpty) {
setState(() {
loadimage();
});
}
}
}
void loadimage() {
_loadingimage = true;
precacheImage(_image, context, onError: (e, stackTrace) {
// log.fine('Image ${widget.url} failed to load with error $e.');
print('error $e');
setState(() {
_loadingimage = false;
print(_loadingimage);
});
});
if (_loadingimage == true) {
_imagescreen = Image.network(
_imageUrlConroller.text,
fit: BoxFit.fill,
);
}
}
Container(
width: 100,
height: 100,
margin: EdgeInsets.only(top: 13, right: 11),
decoration: BoxDecoration(
border: Border.all(
width: 1,
color: Colors.grey,
),
),
child:_imageUrlConroller.text.isEmpty
? Text('enter an url')
: !_loadingimage
? Container(
child: Icon(Icons.add_a_photo),
)
: Container(
child: _imagescreen,
),
),

Resources