I want to show a picture inside a CircleAvatar, if the user never inserted a picture before then the default picture "empty_profile.png" will appear, otherwise if the user already inserted a picture from gallery or camera then the last one will be shown.
This is the code :
File _file = null;
File variable declared at the beginning.
Future<void> changeImage() async { //This will change the picture
File tmp = await imgFromGallery();
setState(() {
_file = tmp;
});
return;
}
The function above will change _file value to the file picked from gallery.
Widget myAvatar() {
return GestureDetector(
onTap: null,
child: CircleAvatar(
radius: 55,
backgroundColor: Color(0xffFDCF09),
child: CircleAvatar(
radius: 50,
child: Container(
child: _file == null
? AssetImage("empty_profile.png")
: FileImage(_file),
),
),
),
);
}
Finally if file is still null then the asset image is loaded, otherwise if a new picture is choosen then FileImage(_file) will show the picked image.
I have a lots of error because I don't know very well how to handle files, their paths and show images...Can you explain me how I should do?
To include static images in your Flutter project, place them inside the "assets/images" folder. Then, make sure to add this folder to your pubspec.yml:
flutter:
assets:
- assets/images/
Next, you may have errors related to trying to render an AssetImage inside a CircleAvatar. To render the file as an Image widget instead, use Image.asset(<path>). Your example could be written as:
Widget myAvatar() {
return GestureDetector(
onTap: null,
child: CircleAvatar(
radius: 55,
backgroundColor: Color(0xffFDCF09),
child: _file == null
? Image.asset("assets/images/empty_profile.png")
: _file
),
);
}
Finally, a great resource for user-selected images is the image_picker library: https://pub.dev/packages/image_picker. For example, a "Select from Gallery" button could invoke the following code, which allows the user to crop the image and saves it as an Image widget:
PickedFile image = await picker.getImage(
source: ImageSource.gallery, // to select from camera, use ImageSource.camera
maxHeight: 1024,
maxWidth: 1024,
imageQuality: 50
);
try {
File croppedImage = await ImageCropper.cropImage( // use platform-native image cropping
sourcePath: image.path,
cropStyle: CropStyle.circle,
maxWidth: 512,
maxHeight: 512
);
setState(() { // refresh state to render new profile image
_file = Image.file(croppedImage)
})
} catch (err) {
print(err)
}
You can use CachedNetworkImage PlugIn - Update other details as per your need. This code show Network Images, if not available will show Assets Image.
new Container(
width: 140.0,
height: 140.0,
child: ClipOval(
child: CachedNetworkImage(
imageUrl: _profile == null ? "" : Api.baseURL + _profile,
placeholder: (context, url) =>
Center(child: CircularProgressIndicator()),
errorWidget: (context, url, error) => Image.asset(
"img/user.png",
fit: BoxFit.cover,
height: 140.0,
width: 140.0,
),
fit: BoxFit.cover,
height: 140.0,
width: 140.0,
),
),
),
Related
Trying to export a frame from my video file, save it to an image file list, and then display it back when building my list of containers.
setState(() async{
if (result!.files.isNotEmpty) {
for (PlatformFile item in result.files) {
videos.add(File(item.path!));
var duration = Duration(seconds: 1);
File image = await ExportVideoFrame.exportImageBySeconds(File(item.path!), duration, 0);
videoThumbs.add(image);
//tickets[widget.indexEvent].videos[i]
}
} else {}
});
Then later in my page class I am trying to display it back for the user in a child of my container:
Container(
width: 220,
height: 220,
color: colorPrimary,
child: Image.file(
videoThumbs[i],
width: 100,
height: 100,
fit: BoxFit.fill,
),
),
The code doesn't hard fail, and will build the apk, but when in the app, my thumbnail just says:
As you can see from my thumbnail, my list of photos and videos are building, but when it tries to loop through the videos and show a thumb, the array index is empty, I think? I believe I'm reading that error right.
I have seriously been at this for 2 weeks, and I could really use some help.
in this list, Your data is not complete, on 2 last of your data is null.
use this:
child:
videoThumbs[I] == null? const SizedBox():
Image.file(
videoThumbs[i],
width: 100,
height: 100,
fit: BoxFit.fill,
),
I am using this function to get images from the gallery
_getFromGallery() async {
XFile? pickedFileGal = await ImagePicker().pickImage(
source: ImageSource.gallery,
maxWidth: 1800,
maxHeight: 1800,
);
if (pickedFileGal != null) {
XFile imageFileGal = XFile(pickedFileGal.path);
setState(() {
_imageFile = imageFileGal;
});
}
}
late XFile _imageFile;
I need to set the image to the container background, the container has a child column. So I need to set it in BoxDecoration, but I have the image in XFile the container BoxDecoration image does not take Image.file(). So how can I achieve that? Please guide me
Container(
decoration: BoxDecoration(
image: Image.file(_imageFile), //Error
),
padding: const EdgeInsets.only(top: 20),
color: Colors.white,
margin: const EdgeInsets.only(
bottom: 15,
),
child: Column(
children: []))
First the image here needs to be a DecorationImage which then takes ImageProvider<Object>.
Knowing this , the correct way to use this is as follows
Container(decoration: BoxDecoration(
image: DecorationImage(image: Image.file('file').image)
),),
Xfile to file
Xfile pickedFile;
Image.file(File(pickedFile.path))
I have a list combined of video and image,
I want to show video thumbnail in list if it's video.
Right now i have shown only icon of video player if it's video
can we show thumbnail ..?
[![The list view][1]][1]
Below is the code
children: [
if (post.photo != null)
AspectRatio(
aspectRatio: 156 / 110,
child: ClipRRect(
borderRadius: const BorderRadius.all(
AppTheme.mediumBorderRadius,
),
child: CustomExtendedImage(
url: post.photo!,
),
),
),
if (post.video != null)
// Get Video Thumbnail somehow
const AspectRatio(
aspectRatio: 156 / 110,
child: Center(
child: Icon(
FlatIcons.video_camera,
size: 100,
),
),
),
],
You can use package video_thumbnail like this
Future<File> _generateThumbnail() async {
final String _path = await VideoThumbnail.thumbnailFile(
video: 'video_url',
thumbnailPath: (await getTemporaryDirectory()).path, /// path_provider
imageFormat: ImageFormat.PNG,
maxHeight: 50,
quality: 50,
);
return File(_path);
}
I'm trying to upload, and update a picture from firebase storage. But for some reason this is not working properly.
This would be the scenario; A user take a picture from his camera, so this picture is uploaded to my storage, so after that I get the url picture, so I can use this like NetworkImage(url) to update the picture.
This is what's happening currently:
Let's say I don't have any picture.
I update my profile with a new picture. (This works perfectly).
Now let's say I want to update my profile picture, so I take another picture, let's call it A so I upload this one.
Nothing happens, picture doesn't change.
But If I try again with a B picture, for some reason the picture is updated with the A picture.
This would be my code and how I'm facing this feature.
I have the next method which is invoked when a user click over his picture. I wait for the result (value) so when I got the result I upload the picture. Then, when the picture is uploaded, I just call to setState and save the url into the _imageUrl variable.
After that, I change the "profilePic" attribute from my data base to true.
String _imageUrl = 'assets/profileDefault.jpg';
bool profilePicture = false;
io.File profilePic;
Future getFromCamara() async {
await ImagePicker().getImage(source: ImageSource.camera).then((value) {
profilePic = io.File(value.path);
FirebaseStorage.instance.ref().child('picture').putFile(profilePic);
}).then((result) {
var ref = FirebaseStorage.instance.ref().child('picture');
ref.getDownloadURL().then((loc) => setState(() => _imageUrl = loc));
});
try {
FirebaseFirestore.instance
.collection('Usuarios')
.doc(uid)
.update({'profilePic': true});
} catch (e) {
print(e.toString());
}
So now, using a StreamBuilder, I get the result of profilePic from my DataBase, if is True, I download the URL, and if don't, I just use the Asset default's pic.
body: StreamBuilder(
stream: FirebaseFirestore.instance.collection('Usuarios').snapshots(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot1) {
if (!snapshot1.hasData) {
return Center(
child: CircularProgressIndicator(),
);
}
List<DocumentSnapshot> users = snapshot1.data.docs;
for (DocumentSnapshot user in users) {
if (user.id == userID) {
profilePicture = user['profilePic'];
}
}
if (profilePicture) {
FirebaseStorage.instance
.ref()
.child('picture')
.getDownloadURL()
.then((loc) => _imageUrl = loc);
} else {
_imageUrl = 'assets/profileDefault.jpg';
}
return Stack(
alignment: Alignment.center,
children: <Widget>[
Positioned(
top: 0,
child: Container(
color: Color.fromRGBO(255, 0, 0, 70),
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height * .55,
),
),
Positioned(
top: MediaQuery.of(context).size.height * .015,
left: 15,
right: 15,
child: Container(
width: MediaQuery.of(context).size.height * .90,
height: 300,
padding: EdgeInsets.only(bottom: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
GestureDetector(
onTap: () => _setPic(context),
child: CircleAvatar(
radius: 79,
backgroundColor: Color(0xFFFFFFFFF),
child: CircleAvatar(
radius: 75,
backgroundImage: profilePicture
? NetworkImage(_imageUrl)
: AssetImage(_imageUrl),
),
),
),
// More code...
What I'm doing wrong? Why my picture isn't getting updated?
Updated:
I tried this, so I can save in pictureTemp the picture's bytes, calling to setState to rebuild the widget and put the picture with Image.memory(pictureTemp). But it doesn't seem to work.
Uint8List pictureTemp;
io.File profilePic;
Future getFromCamara() async {
var pickedFile = await ImagePicker().getImage(source: ImageSource.camera);
var image = await pickedFile.readAsBytes();
FirebaseStorage.instance
.ref()
.child('picture')
.putFile(io.File(pickedFile.path));
setState(() {
pictureTemp = image;
});
child: CircleAvatar(
radius: 75,
backgroundImage: profilePicture
? pictureTemp == null
? AssetImage(_imageUrl)
: Image.memory(pictureTemp)
: AssetImage(_imageUrl),
),
Here when the image is picked you should directly set it or you can set it after the firebase upload is finished successfully.
But rather than loading an image from Firebase URL after the upload, you can directly load from the picked file as follows;
image = Image.memory(await pickedFile.readAsBytes())
This will instantly set the image and will save you a read call to Firebase. You should always try to minimize the Firebase Reads whenever possible.
After selecting image using image_picker: ^0.6.0+15 package, we received a file in Android and iOS, but the issue is with the display/render of the image in the UI.
//Display Image to user
Expanded(
child: Padding(
padding: EdgeInsets.only(top: 20, bottom: 20),
child: _selectedImage == null
? Center(
child: Container(
child: Text('No Image selected'),
),
)
: Image.memory(
_selectedImage.readAsBytesSync(),
fit: BoxFit.contain,
),
),
)
setState(() {}); is required in Android but on iOS image display with out calling setState(() {}); glitches the UI on iOS if we call setState().
We have an option:
Future getImage(int sourceType) async {
_selectedImage = await ImagePicker.pickImage(
source: sourceType == 1 ? ImageSource.gallery : ImageSource.camera,
maxHeight: 500,
maxWidth: 500,
);
// to show Images in Images View
if (Platform.isAndroid) {
setState(() {});
}
}
But is there any explanation on setState() is not needed on iOS?
Any interface should be ready for multiple build() calls per second. You should be free to call setState() with no reservations anytime. When this is a problem, you are doing something wrong.
I think this is what's wrong in your case: you call _selectedImage.readAsBytesSync() in build(). You should do that elsewhere and keep info about it in fields of your class, which the build() function uses to simply convert that information to UI.