Unable to fill the CircleAvatar with the selected image from image_picker - flutter

I'm getting the image from the image_picker package and loading the image in CircleAvatar but image is not filling across the circle. I have used boxfit.fill in the ClipRRect and also in the ClipOval.
import 'package:image_picker/image_picker.dart';
class EditProfileScreen extends StatefulWidget {
static const String routename = "/EditProfileScreen";
const EditProfileScreen({Key? key}) : super(key: key);
#override
_EditProfileScreenState createState() => _EditProfileScreenState();
}
class _EditProfileScreenState extends BaseState<EditProfileScreen> {
final ImagePicker _picker = ImagePicker();
XFile? _imageFileSelected;
set _imageFile(XFile? value) {
_imageFileSelected = value == null ? null : value;
}
void _onImageButtonPressed(ImageSource source,
{BuildContext? context, bool isMultiImage = false}) async {
try {
final pickedFile = await _picker.pickImage(
source: source, maxHeight: 160, maxWidth: 200);
setState(() {
_imageFile = pickedFile;
});
} catch (e) {
setState(() {
_pickImageError = e;
});
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppWidgets.backgroundColor,
appBar: AppWidgets.appbar(text: "Edit Profile", actionWidgets: []),
body: SingleChildScrollView(
child: Container(
margin: EdgeInsets.fromLTRB(20, 16, 20, 20),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Center(
child: Column(
children: [
CircleAvatar(
child: ClipRRect(
borderRadius: BorderRadius.circular(48),
child: (_imageFileSelected?.path == null)
? Image.network(
profileImagePath,
)
: Image.file(
File(_imageFileSelected!.path),
),
),
radius: 50.0,
),
SizedBox(
height: 10,
),
TextButton(
onPressed: () {
_onImageButtonPressed(ImageSource.gallery,
context: context);
},
child: AppWidgets.text(
string: 'Change Photo',
weight: FontWeight.w500,
textColor: AppWidgets.buttonColor,
size: 16),
),
],
),
),
),
);
}
Note:
I have used boxfit no luck.
I tried clipoval in the child didn't work.
I tried to put images in backgroundImage and foregroundImage unable to do

Instead of using circleavatar you can use Container with background property Try this code.
Container(
height: 88.5.h,
width: 88.5.w,
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.cover,
image: CachedNetworkImageProvider(
state.details["profile_photo"]),
shape: BoxShape.circle,
border: Border.all(
color: ColorConstant.buttonColor,
width: 5.w)),
),

I use this to store the updated picture locally.
ps. this already has a picture which can be changed but you can just use background color to hold instead.
File _image;
String _imagepath;
Future _getImage() async {
var image = await ImagePicker.pickImage(source: ImageSource.gallery);
if (image != null) {
var cropped = await ImageCropper.cropImage(
sourcePath: image.path,
maxHeight: 100,
maxWidth: 100,
aspectRatio: CropAspectRatio(ratioX: 1, ratioY: 1),
cropStyle: CropStyle.circle,
compressQuality: 100,
);
this.setState(() {
_image = cropped;
});
saveImage(_image.path);
}
}
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');
});
}
#override
void initState() {
// TODO: implement initState
super.initState();
LoadImage();
}
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: _getImage,
child: Container(
//padding: EdgeInsets.all(2),
decoration: BoxDecoration(
border: Border.all(
color: Colors.white,
width: 5.0,
),
shape: BoxShape.circle,
),
child: _imagepath != null
? CircleAvatar(
backgroundImage: FileImage(File(_imagepath)),
radius: 60,
)
: CircleAvatar(
backgroundImage: _image != null
? FileImage(_image)
: AssetImage('assets/mypic1.jpg'),
backgroundColor: Colors.blue[200],
radius: 60,
),
),
);

Related

Flutter Carousel framed by taking pictures in the moment

How can I display a Carousel framed by taking pictures in the moment?
This carousel needs a function to remove photos if needed. And an indicator of what image I'm seeing.
I'm using packages: 'image_picker' to get the photos from gallery or camera. And the 'carousel_slider' package to display the carousel.
And so, if there isn't a photo there isn't a carousel.
The problem I get is that the second photo replaces the first... the third replaces the second and the first, I mean the next photo will replace the previous photos. Also, I can't remove the photos from the carousel, and I can't display the indicators for the image I'm looking at either.
Here are the functions I run to take the pictures:
_takePicture() async {
File auxiliarFile;
final ImagePicker _picker = ImagePicker();
XFile imageFile = await _picker.pickImage(
source: ImageSource.camera, maxWidth: 600) as XFile;
setState(() {
_storedImage = File(imageFile.path);
});
auxiliarFile = _storedImage!;
final appDir = await syspath.getApplicationDocumentsDirectory();
String fileName = path.basename(_storedImage!.path);
final savedImage = await _storedImage!.copy('${appDir.path}/$fileName');
listImages.add(auxiliarFile);
}
_chosePicture() async {
final ImagePicker _picker = ImagePicker();
XFile imageFile = await _picker.pickImage(
source: ImageSource.gallery,
) as XFile;
setState(() {
_storedImage = File(imageFile.path);
});
final appDir = await syspath.getApplicationDocumentsDirectory();
String fileName = path.basename(_storedImage!.path);
final savedImage = await _storedImage!.copy('${appDir.path}/$fileName');
listImages.add(savedImage);
}
To display the carousel I tried:
_storedImage != null
? Column(
children: [
CarouselSlider(
options: CarouselOptions(
enableInfiniteScroll: false,
enlargeCenterPage: true,
enlargeFactor: 0.25,
),
items: listImages.map((i) {
return Builder(builder:
(BuildContext context) {
return Container(
width: MediaQuery.of(context)
.size
.width *
0.75,
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(10),
border: Border.all(
color: Colors.black87),
color: Colors.grey[350],
),
child: OutlinedButton(
onPressed: _showDeleteDialog,
onLongPress: () =>
_showDeleteDialog(),
child: Image.file(
(_storedImage!),
),
),
);
});
}).toList(),
),
Padding(
padding: const EdgeInsets.all(8),
child: Row(
mainAxisAlignment:
MainAxisAlignment.center,
children: map<Widget>(listImages,
(index, url) {
return InkWell(
onTap: () {
setState(() {
_pageController
.jumpToPage(index);
currentIndex = index;
});
},
child: Container(
width: 10,
height: 10,
margin: const EdgeInsets
.symmetric(
vertical: 10,
horizontal: 5,
),
decoration:
const BoxDecoration(
shape: BoxShape.circle,
color: Colors.grey,
),
),
);
}),
),
),
],
)
: const Text(
'No image',
style: TextStyle(
fontWeight: FontWeight.bold,
),
)

Store Image in List<Xfile> from image urls

I have created a variable
List<Xfile> imageList;
using this variable I have showed the selected images in GridView.Builder and uploaded them.
But I want to store those uploaded images in this List to show them again in GridView.Builder.
Means How to store images from imageUrls in List
How can I achieve this?
Follow as follows:
Variables
final picker = ImagePicker();
File? file;
XFile? pickedImage;
bool isLoading = false;
List<File?> fileList = [];
Method to select image from gallery
Future pickImageFromGallery() async {
pickedImage = await picker.pickImage(source: ImageSource.gallery);
setState(() {
file = File(pickedImage!.path);
fileList.add(file);
});
}
And place in gridview as follows:
GridView.builder(
itemCount: fileList.length,
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
itemBuilder: (BuildContext context, int i) {
return Container(
padding: const EdgeInsets.all(10),
child: Stack(
children: <Widget>[
SizedBox(
height: 100,
width: 100,
child: Image.file(File(fileList[i]!.path),fit: BoxFit.cover,),
),
Positioned(
right: 1,
child: GestureDetector(
onTap: () {
setState(() {
dltImages(fileList[i]);
});
},
child: const Icon(Icons.cancel, color: Colors.red),
))
],
),
);
},
),
Find full code at:
https://github.com/nbnD/image_picker_flutter/blob/master/lib/homepage.dart
I do like this if there is multi images upload
class PickImagesPage extends StatefulWidget {
const PickImagesPage({super.key, required this.initialUrls});
final List<String> initialUrls;
#override
State<PickImagesPage> createState() => _PickImagesPageState();
}
class _PickImagesPageState extends State<PickImagesPage> {
#override
void initState() {
urls = widget.initialUrls;
super.initState();
}
List<String> urls = [];
List<File> files = [];
List<String> removedUrls = [];
final Repo repo = Repo();
#override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final style = theme.textTheme;
final scheme = theme.colorScheme;
return LoadingLayer(
child: Scaffold(
bottomNavigationBar: Padding(
padding: const EdgeInsets.fromLTRB(24, 0, 24, 24),
child: ElevatedButton(
onPressed:
files.isNotEmpty || widget.initialUrls.length != urls.length
? () async {
try {
await repo.uploadImages(
files: files,
urls: urls,
removedUrls: removedUrls,
);
Navigator.pop(context);
} catch (e) {
AppSnackbar(context).error(e);
if (kDebugMode) {
print(e);
}
}
}
: null,
child: const Text(Labels.save),
),
),
appBar: AppBar(
title: const Text(
Labels.ambienceImages,
),
),
floatingActionButton: FloatingActionButton(
onPressed: () async {
final List<XFile> pickedFiles = await pickImages();
if (pickedFiles.isNotEmpty) {
setState(() {
files.addAll(pickedFiles.map((e) => File(e.path)));
});
}
},
child: const Icon(Icons.add),
),
body: GridView.count(
padding: const EdgeInsets.all(12),
crossAxisCount: 2,
mainAxisSpacing: 12,
crossAxisSpacing: 12,
children: [
...urls
.map(
(e) => GestureDetector(
onTap: () {
setState(() {
urls.remove(e);
removedUrls.add(e);
});
},
child: Container(
clipBehavior: Clip.antiAlias,
decoration: BoxDecoration(
color: scheme.surfaceVariant.withOpacity(0.5),
borderRadius: BorderRadius.circular(20),
image: DecorationImage(
image: NetworkImage(e),
),
),
),
),
)
.toList(),
...files
.map(
(e) => Container(
clipBehavior: Clip.antiAlias,
alignment: Alignment.topRight,
decoration: BoxDecoration(
color: scheme.surfaceVariant.withOpacity(0.5),
borderRadius: BorderRadius.circular(20),
image: DecorationImage(
image: FileImage(e),
),
),
child: SizedBox(
height: 40,
width: 40,
child: RawMaterialButton(
elevation: 0,
focusElevation: 0,
hoverElevation: 0,
shape: const CircleBorder(),
fillColor: theme.cardColor.withOpacity(0.5),
onPressed: () {
setState(() {
files.remove(e);
});
},
child: const Icon(Icons.remove),
),
),
),
)
.toList(),
GestureDetector(
onTap: () async {
final List<XFile> pickedFiles = await pickImages();
if (pickedFiles.isNotEmpty) {
setState(() {
files.addAll(pickedFiles.map((e) => File(e.path)));
});
}
},
child: Container(
clipBehavior: Clip.antiAlias,
decoration: BoxDecoration(
color: scheme.surfaceVariant.withOpacity(0.5),
borderRadius: BorderRadius.circular(20),
),
child: Stack(
children: const [
Center(
child: Icon(Icons.add),
),
PickImageLabel(),
],
),
),
),
],
),
),
);
}
}
class Repo {
Future<void> uploadImages(
{required List<String> urls,
required List<File> files,
required List<String> removedUrls}) async {
List<String> newUrls = [];
for (var file in files) {
final url = await upload(file);
newUrls.add(url);
}
for (var url in removedUrls) {
await deleteImage(url);
}
await saveImages(urls + newUrls);
}
}

How do I keep a variable value after UI state change?

So basically, I have an ImagePicker widget that empties every time my view changes in a browser(flutter web):
But once I change the size of the browser window, the image dissappears:
So I was wondering if there's a way to keep value of the variable that contains the string image.
This is the function that gets the image:
static Future<Uint8List?> webPickImage() async {
final picker = ImagePicker();
var file = await picker.pickImage(source: ImageSource.gallery);
if (file != null) {
return await file.readAsBytes();
} else {
return null;
}
}
As you can see, this returns an Uint8List which then is emited in a BLoC/cubit state management class variable
void userWebImageChanged() async {
final newWebImage = await CommonFunction.webPickImage();
emit(
state.copyWith(
webUserImage: newWebImage,
),
);
}
State management class:
So it appears that webUserImage loses it's value when the browser window changes size:
part of 'sign_up_cubit.dart';
class SignUpState extends Equatable {
const SignUpState(
{
this.webUserImage
});
final Uint8List? webUserImage;
#override
List<Object?> get props => [
webUserImage
];
SignUpState copyWith(
{
Uint8List? webUserImage
}) {
return SignUpState(
webUserImage: webUserImage ?? this.webUserImage);
}
}
Widget(read comments):
class SignUpForm extends StatelessWidget {
const SignUpForm({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => SignUpCubit(),
child: BlocConsumer<SignUpCubit, SignUpState>(
builder: (context, state) => ResponsiveRowColumn(
rowMainAxisAlignment: MainAxisAlignment.spaceEvenly,
rowPadding: const EdgeInsets.all(10),
columnPadding: const EdgeInsets.all(10),
layout: ResponsiveWrapper.of(context).isSmallerThan(DESKTOP)
? ResponsiveRowColumnType.COLUMN
: ResponsiveRowColumnType.ROW,
children: [
ResponsiveRowColumnItem(
rowFlex: 1,
child: SizedBox(
width: 350,
child: Column(
children: [
Wrap(
runSpacing: 10,
alignment: WrapAlignment.center,
children: [
ResponsiveVisibility(
hiddenWhen: const [
Condition.smallerThan(name: TABLET)
],
//BLoC
child: BlocBuilder<SignUpCubit, SignUpState>(
buildWhen: (previous, current) =>
previous.webUserImage !=
current.webUserImage,
builder: (cubitContext, state) {
return GestureDetector(
onTap: () async {
cubitContext
.read<SignUpCubit>()
.userWebImageChanged();
},
child: Container(
margin: const EdgeInsets.all(10),
width: 135,
height: 135,
decoration: BoxDecoration(
borderRadius:
const BorderRadius.all(
Radius.circular(10)),
border: Border.all(
color: Theme.of(context)
.primaryColorDark,
width: 1,
),
color: Colors.white),
child: state.webUserImage == null
? Center(
child: Icon(
Icons.add,
color: Theme.of(context)
.primaryColorDark,
size: 50,
),
)
: ClipRRect(
child: Image.memory(
// This is the state variable that sets and holds the image:
state.webUserImage!),
borderRadius:
const BorderRadius.all(
Radius.circular(11)),
),
),
);
},
),
//...

how to convert an Xfile to file?

I want to get picutres with the emulator's camera and when i take one it' doesn't save the picture and give me an error that says pickImage method reurns a Future of type XFile and I want a return of type File and when i use (as File) it give me another Error that says Xfile is not a subtype of type File
class ImageInput extends StatefulWidget {
final Function? onSelect;
const ImageInput({Key? key, this.onSelect}) : super(key: key);
#override
_ImageInputState createState() => _ImageInputState();
}
class _ImageInputState extends State<ImageInput> {
File? _imagePicker;
Future<void> _takeAPicture() async {
final picker = ImagePicker();
final imageFile = await picker.pickImage(
source: ImageSource.gallery,
maxWidth: 600,
);
}
Future<void> _chooseAPicture() async {
final picker = ImagePicker();
final imageFile = await picker.pickImage(
source: ImageSource.camera,
maxWidth: 600,
) as File;
setState(() {
_imagePicker = File(imageFile.path);
});
final appdir = await syspath.getApplicationDocumentsDirectory();
final fileName = path.basename(imageFile.path);
final savedImage = await imageFile.copy('${appdir.path}/${fileName}');
widget.onSelect!(savedImage);
}
#override
Widget build(BuildContext context) {
return Row(children: [
Container(
child: _imagePicker != null
? Image.file(
_imagePicker as File,
fit: BoxFit.cover,
width: double.infinity,
)
: Text(
'No Image Taken',
textAlign: TextAlign.center,
),
alignment: Alignment.center,
height: 100,
width: 100,
decoration: BoxDecoration(
border: Border.all(color: Colors.grey, width: 1),
),
),
SizedBox(
height: 10,
),
Expanded(
child: Column(
children: [
TextButton.icon(
onPressed: () => _takeAPicture(),
label: Text('choose an Image'),
style: ButtonStyle(
textStyle: MaterialStateProperty.all(
TextStyle(color: Theme.of(context).primaryColor),
),
),
icon: Icon(Icons.camera),
),
TextButton.icon(
onPressed: () => _chooseAPicture(),
label: Text('Take an Image'),
style: ButtonStyle(
textStyle: MaterialStateProperty.all(
TextStyle(color: Theme.of(context).primaryColor),
),
),
icon: Icon(Icons.camera_enhance_sharp),
),
],
),
),
]);
}
}
Try out below code for XFile
final ImagePicker _picker = ImagePicker();
Future getForFrontImage(ImageSource source) async {
final XFile? pickedFile = await _picker.pickImage(source: source);
if (pickedFile != null) {
setState(() {
selectedChequeImg = File(pickedFile.path);
});
}
}

Error while trying to load an asset: FormatException: Illegal scheme character - error while using image picker

I am trying to enable to the app user to change his/her profile picture and upload it via camera or gallery, I used
the image picker package for this purpose,
this is my code snippet:
`
class ProfilePic extends StatefulWidget {
const ProfilePic({
Key key,
}) : super(key: key);
#override
_ProfilePicState createState() => _ProfilePicState();
}
class _ProfilePicState extends State<ProfilePic> {
File image = new File("");
final _picker = ImagePicker();
#override
Widget build(BuildContext context) {
return SizedBox(
height: 115,
width: 115,
child: Stack(
fit: StackFit.expand,
overflow: Overflow.visible,
children: [
CircleAvatar(
backgroundImage: AssetImage(image.uri.toFilePath()),
// child: ClipRRect(
// borderRadius: BorderRadius.circular(50),
// child: image != null
// ? Image.file(
// image,
// width: 115,
// height: 115,
// fit: BoxFit.fitHeight,
// )
// : Container(
// decoration: BoxDecoration(
// color: Colors.grey[100],
// borderRadius: BorderRadius.circular(50)),
// width: 100,
// height: 100,
// child: Icon(
// Icons.camera_alt,
// color: Colors.grey[800],
// ),
// ),
// ),
),
Positioned(
right: -16,
bottom: 0,
child: SizedBox(
height: 46,
width: 46,
child: FlatButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50),
side: BorderSide(color: Colors.white),
),
color: Color(0xFFF5F6F9),
onPressed: () {
_showPicker(context);
},
child: SvgPicture.asset("icons/cameraIcon.svg"),
),
),
)
],
),
);
}
_imgFromCamera() async {
PickedFile pickedFile =
await _picker.getImage(source: ImageSource.camera, imageQuality: 50);
setState(() {
image = File(pickedFile.path);
});
}
_imgFromGallery() async {
PickedFile pickedFile =
await _picker.getImage(source: ImageSource.gallery, imageQuality: 50);
setState(() {
image = File(pickedFile.path);
});
}
void _showPicker(context) {
showModalBottomSheet(
context: context,
builder: (BuildContext bc) {
return SafeArea(
child: Container(
child: new Wrap(
children: <Widget>[
new ListTile(
leading: new Icon(Icons.photo_library),
title: new Text('Gallerie'),
onTap: () {
_imgFromGallery();
Navigator.of(context).pop();
}),
new ListTile(
leading: new Icon(Icons.photo_camera),
title: new Text('Caméra'),
onTap: () {
_imgFromCamera();
Navigator.of(context).pop();
},
),
],
),
),
);
});
}
}
`
PS: I am using Chrome for debugging.
Its select the image from the device but doesn't change the state to upload the image, am asking if it is a flutter web related problem so in a real device or emulator can work smoothly?
Any suggestion please.
AssetImage takes asset files that you have referenced in your pubspec.yaml. you should use FileImage instead if you are trying to display images from the camera or gallery.
example: FileImage(image)
You can read more here