Related
When i click on camera icon in stack widget and also it is unable to update image it show this error.It also not upload image to database nor it chaange the url** [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Null check operator used on a null value E/flutter (28471): #0 _profileState.geturl (package:ecommerce/Auth/profile.dart:25:59) E/flutter (28471): **
I want to update image but facing error please solve it..
Code For Imagepicker
Future image(BuildContext context) async{
showModalBottomSheet(
elevation: 5,
enableDrag: true,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20),
),
),
context: context,
builder: (BuildContext context) {
return Container(
height: 200,
child: Column(
children: [
///Gallery
ListTile(
leading: Icon(Icons.browse_gallery),
title: Text("Pick image from gallery"),
onTap: () async{
final gallery=await ImagePicker().pickImage(source: ImageSource.gallery);
if (gallery!=null) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text("Image Picked successfull",style: TextStyle(color: Colors.redAccent),
),duration: Duration(seconds: 5),
));
} else {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text("Please pick image for further proccess",style: TextStyle(color: Colors.redAccent),
),duration: Duration(seconds: 5),
));
}
Code For updating Url
Future geturl(context)async{
final id=DateTime.now().toString();
final reference=FirebaseFirestore.instance.collection("user3");
await image(context);
final storage.Reference ref =
storage.FirebaseStorage.instance.ref('/images'+id);
final storage.UploadTask uploadTask = ref.putFile(_image!.absolute);
await Future.value(uploadTask);
final downurl=await ref.getDownloadURL();
print(FirebaseAuth.instance.currentUser!.uid);
reference.doc(FirebaseAuth.instance.currentUser!.uid).update(
{
"imageurl":downurl.toString(),
}
).then((value) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text("Updated successfully",style: TextStyle(color: Colors.redAccent),
),duration: Duration(seconds: 5),
));
}).catchError((e){
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text("${e.message}",style: TextStyle(color: Colors.redAccent),
),duration: Duration(seconds: 5),
));
});
}
For displaying image in flutter app
Stack(
alignment: Alignment.bottomRight,
children: [
CircleAvatar(
radius: 70,
backgroundImage:_image!=null?FileImage(_image!.absolute) : NetworkImage(snapshot.data!.docs[index]["imageurl"]) as ImageProvider,
),
InkWell(
onTap: (){
geturl(context);
},
child: Icon(Icons.add_a_photo,size: 30,)),
],
),
Please solve I am facing this error for Last couple of days
You need to declare the image variable null by adding "?".
Example: DataType image?
Then display like this
image!=null ? CircleAvatar(
radius: 70,
backgroundImage: FileImage(_image!.absolute) ,
): CircleAvatar(
radius: 70,
backgroundImage: NetworkImage(snapshot.data!.docs[index]["imageurl"])
I think that this line is causing the problem:
final storage.UploadTask uploadTask = ref.putFile(_image!.absolute);
Because _image is probably null. Where do you assign a value to the variable _image?
EDIT:
how I would fix this:
you have one method pickImage that shows the bottom modal sheet and allows the user to pick an image. if the user picks an image, you call a method that saves the picked image to firebase, in this case the method is called: saveImage
void pickImage(BuildContext context) {
showModalBottomSheet(
elevation: 5,
enableDrag: true,
isDismissible: false,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20),
),
),
context: context,
builder: (BuildContext context) {
return Container(
height: 200,
child: Column(
children: [
ListTile(
leading: Icon(Icons.browse_gallery),
title: Text("Pick image from gallery"),
onTap: () async {
XFile? pickedImage = await ImagePicker().pickImage(source: ImageSource.gallery);
if (pickedImage != null) {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text(
"Image Picked successfull",
style: TextStyle(color: Colors.redAccent),
),
duration: Duration(seconds: 5),
));
var image = Image.memory(await pickedImage.readAsBytes());
// save image to firebase
saveImage(context, image);
} else {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text(
"Please pick image for further proccess",
style: TextStyle(color: Colors.redAccent),
),
duration: Duration(seconds: 5),
));
}
},
),
],
),
);
},
);
}
method that saves the image to firebase:
Future saveImage(context, _image) async {
final id = DateTime.now().toString();
final reference=FirebaseFirestore.instance.collection("user3");
final storage.Reference ref =
storage.FirebaseStorage.instance.ref('/images'+id);
final storage.UploadTask uploadTask = ref.putFile(_image!.absolute);
await Future.value(uploadTask);
final downurl=await ref.getDownloadURL();
print(FirebaseAuth.instance.currentUser!.uid);
reference.doc(FirebaseAuth.instance.currentUser!.uid).update(
{
"imageurl":downurl.toString(),
}
).then((value) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text("Updated successfully",style: TextStyle(color: Colors.redAccent),
),duration: Duration(seconds: 5),
));
}).catchError((e){
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text("${e.message}",style: TextStyle(color: Colors.redAccent),
),duration: Duration(seconds: 5),
));
});
}
I wanted to show a tooltip when I tap my gesture detector and do different things when the GestureDetector is long pressed, How can I achieve this? I have written some code about it but on long press still shows a tooltip rather than accessing my selectDate() function
this is my current code:
GestureDetector(
onTap: () {
final dynamic tooltip = _toolTipKey.currentState;
tooltip.ensureTooltipVisible();
},
onLongPress: () {
if (widget.ticketData['status'] == 'active') {
showDialog(
context: context,
builder: (context) {
return ReusableConfirmationDialog(
titleText: 'changeDueDateTitle'.tr(),
contentText: 'changeDueDateDesc'.tr(),
declineButtonText: 'cancel'.tr(),
confirmButtonText: 'change'.tr(),
onDecline: () {
Navigator.pop(context);
},
onConfirm: () {
DevMode.log('start changing the due date');
_selectDate(context);
},
);
},
);
}
},
child: Tooltip(
key: _toolTipKey,
message: "Hello",
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 11, vertical: 5),
decoration: BoxDecoration(
color: formBackgroundColor,
borderRadius: BorderRadius.circular(15),
),
child: Row(
children: [
Image.asset(
'assets/logo/calendar.png',
width: 20,
height: 20,
),
const SizedBox(width: 5),
],
),
),
),
),
Use triggerMode: TooltipTriggerMode.manual and key to show tooltip
final GlobalKey<TooltipState> tooltipkey = GlobalKey<TooltipState>();
Tooltip(
message: "long press to open dialog",
key: tooltipkey,
triggerMode: TooltipTriggerMode.manual,
child: GestureDetector(
onTap: () {
tooltipkey.currentState?.ensureTooltipVisible();
},
onLongPress: () {
log("show dialog");
},
child: Text("dialog"),
)),
);
More about Tooltip
create this function in your code
This line triggerMode: TooltipTriggerMode.tap, will allow you to show tooltip on single tap.
Widget customToolTip({String? text}) {
return Tooltip(
message: text ?? "",
triggerMode: TooltipTriggerMode.tap,
showDuration: const Duration(seconds: 30),
child: const Icon(Icons.help_outline, color: AppColors.buttonColor, size: 20),
);
}
I want to know how to move between pages in flutter introduction screen. To clarify the problem, I want to go back a page when skip button is pressed.
So far I have done this:
class _IntroPageState extends State<IntroPage> {
int currentIndex = 0;
void _onIntroEnd(context) {
getIt<IntroLocalDataSource>().setIntroSeenState(true);
Navigator.of(context).pushReplacementNamed(SignInPage.id);
}
#override
Widget build(BuildContext context) {
final strings = Languages.of(context);
final bodyStyle = Theme.of(context)
.textTheme
.subtitle2
?.copyWith(fontSize: k16TextFontSize);
final titleStyle = Theme.of(context)
.textTheme
.headline1
?.copyWith(fontSize: k20TextFontSize);
return Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Flexible(
child: Container(
child: IntroductionScreen(
onChange: (index) {
setState(() {
currentIndex = index;
});
},
rtl: true,
globalBackgroundColor: Colors.transparent,
showNextButton: false,
rawPages: strings.introScreenTitles.asMap().entries.map((entry) {
int idx = entry.key;
String val = entry.value;
return Center(
child: IntroCardWidget(
index: idx,
title: val,
bodyStyle: bodyStyle,
titleStyle: titleStyle,
image: Assets.introImages[idx],
description: strings.introScreenDescriptions[idx],
));
}).toList(),
showDoneButton: false,
curve: Curves.fastLinearToSlowEaseIn,
showSkipButton: currentIndex != 0,
skip: ElevatedButton(
style: ElevatedButton.styleFrom(
elevation: 0,
primary: kLightTextColor,
shape: CircleBorder(),
),
onPressed: () {
setState(() {
currentIndex--; // <<--------- This does not work
});
},
child: Icon(
Icons.keyboard_arrow_left_rounded,
color: Theme.of(context).primaryColor,
)),
dotsDecorator: DotsDecorator(
color: kLightTextColor.withOpacity(.15),
activeSize: Size(20, 10),
activeShape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25.0)),
activeColor: kLightTextColor),
controlsPadding: kIsWeb
? const EdgeInsets.all(12.0)
: const EdgeInsets.symmetric(
vertical: Spacings.paddingSm,
horizontal: Spacings.paddingXs),
),
),
),
Container(
constraints: BoxConstraints(
maxHeight: Spacings.margin5Xl, minHeight: Spacings.margin5Xl),
margin: EdgeInsets.only(bottom: Spacings.margin5Xl),
child: currentIndex != 3
? Container()
: ElevatedButton(
onPressed: () => _onIntroEnd(context),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: Spacings.padding5Xl,
vertical: Spacings.paddingSm),
child: Text(
strings.goToVerificationPageBtnText,
style: TextStyle(
fontSize: k16TextFontSize, color: kDarkTextColor),
),
),
style: ElevatedButton.styleFrom(
elevation: 1,
primary: kLightTextColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(Spacings.radiusLg),
),
),
),
),
],
);
}
But the page does not change. It seems to make sense, as the index is not passed to the IntroductionScreen widget. So I was wondering how to navigate in these pages as will.
I found a way to do what I wanted.
It could be done with using keys & calling IntroductionScreenState's methods.
After going through the source code of library, it seems it is changing pages using this public method:
Future<void> animateScroll(int page) async {
setState(() => _isScrolling = true);
await _pageController.animateToPage(
max(min(page, getPagesLength() - 1), 0),
duration: Duration(milliseconds: widget.animationDuration),
curve: widget.curve,
);
if (mounted) {
setState(() => _isScrolling = false);
}
}
and also has these methods for going forward & backward:
void next() => animateScroll(_currentPage.round() + 1);
void previous() => animateScroll(_currentPage.round() - 1);
From this point, it was just a matter of calling the methods of this state when needed. This could be done using keys:
GlobalKey<IntroductionScreenState> _introScreenKey =
GlobalKey<IntroductionScreenState>();
IntroductionScreen(
key: _introScreenKey,
skip: ElevatedButton(
style: ElevatedButton.styleFrom(
elevation: 0,
primary: kLightTextColor,
shape: CircleBorder(),
),
onPressed: () {
_introScreenKey.currentState?.previous(); // <<----- This here
},
child: Icon(
Icons.keyboard_arrow_left_rounded,
color: Theme.of(context).primaryColor,
)),
)
And ofcourse it is pretty easy to navigate directly to any page using the animateScroll().
Since you're using navigator, you should give a try to Navigator.pop()
onPressed: () { Navigator.pop(context); }
here you can find some examples
I am trying to show an CircularProgressIndicator whenever user presses on register button, here is my code:
onPressed: () async{
if (_email.isNotEmpty && _password.isNotEmpty) {
startProgressIndicator();
FirebaseAuth mAuth = FirebaseAuth.instance;
UserCredential credential = await mAuth.createUserWithEmailAndPassword(email: _email, password: _password);
print(credential.user!.email);
//stopProgressIndicator();
} else {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(
"Please enter all information!",
style: TextStyle(
color: Colors.white,
fontSize: 15,
fontWeight: FontWeight.bold
),
),
backgroundColor: Colors.black,
elevation: 5,
duration: Duration(
seconds: 3
),
action: SnackBarAction(
label: "close",
onPressed: (){
ScaffoldMessenger.of(context).hideCurrentSnackBar();
},
),
));
}
startProgressIndicator():
CircularProgressIndicator startProgressIndicator() {
return CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.orange),
backgroundColor: Colors.black,
strokeWidth: 5,
);
}
stopProgressIndicator():
CircularProgressIndicator stopProgressIndicator() {
return CircularProgressIndicator(
value: 0,
);
}
The loading icon doesn't appear at all.
All colors are correct(i.e. background color and progress bar color are different)
What is the issue here?
EDIT: I added the following code but it still isn't working:
Column(
children: [
<Other widgets>
Visibility(
visible: _isProgressVisible,
child: CircularProgressIndicator(),
)
]
)
and I set _isProgressVisible to true and false:
if (_email.isNotEmpty && _password.isNotEmpty) {
setState(() {
_isProgressVisible = true;
});
FirebaseAuth mAuth = FirebaseAuth.instance;
UserCredential credential = await mAuth.createUserWithEmailAndPassword(email: _email, password: _password);
print(credential.user!.email);
setState(() {
_isProgressVisible = false;
});
}
You are not showing the returned widget anywhere, startProgressIndicator() returns the widget but you're just calling not rendering it,
Either use like this
showCupertinoDialog(
useRootNavigator: true,
barrierDismissible: false,
context: context,
builder: (context) {
return startProgressIndicator();
},
);
If you want to show that somewhere else you can do that like this
Container(
margin: const EdgeInsets.all(16),
child: Column(children: [
Visibility(
visible: showIndicator,
child: startProgressIndicator()),
const SizedBox(height: 10),
RaisedButton(
child: const Text('Here'),
onPressed: () => setState(() => showIndicator = !showIndicator),
)
]),
);
return startProgressIndicator();
That's just simple mistake
You have to return widget;
Questions:
1-) I have a data lists coming from sqlite database and I want to show them in UI. Also when user dismiss a card I want to delete it from database but if user taps undo then I want to bring it back. The problem is when I dismiss a card it's giving error:
A dismissed Dismissible widget is still part of the tree.
I searched solution for this problem but none of them fit my case because I use Bloc for these operations and other solutions were about setState
You can see in here:
GIF
2-) Also when I swipe card card's background color clipping:
Photo
How to fix these issues?
return Dismissible(
key: Key(widget.task.id.toString()),
background: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: Colors.red,
),
),
onDismissed: (direction) async {
Task copied = widget.task;
taskBloc.deleteTask(widget.task.id);
changeValue(widget.task.categoryId, false);
Flushbar(
messageText: Text('Task deleted', style: bodyText.copyWith(
color: Colors.white
)),
duration: Duration(seconds: 10),
margin: EdgeInsets.all(8),
borderRadius: 8,
icon: Icon(FontAwesomeIcons.infoCircle, color: widget.color),
flushbarStyle: FlushbarStyle.FLOATING,
dismissDirection: FlushbarDismissDirection.HORIZONTAL,
mainButton: FlatButton(
onPressed: () async {
taskBloc.addTask(copied);
changeValue(widget.task.categoryId, true);
},
child: Text('Undo', style: bodyText.copyWith(color: widget.color)),
),
)..show(context);
}),
You can achieve this passing confirmDismiss in the Dismissible widget as given below which should return either true else false;
confirmDismiss: (val) async {
return await AlertDialog(
title: Text('Delete'),
content: Text('Are you sure to delete?'),
actions:[
FlatButton(
child:Text("Yes"),
onPressed:()=>Navigator.pop(context,true)
),
FlatButton(
child:Text("No"),
onPressed:()=>Navigator.pop(context,false)
),
],
)??false;
}
After that the onDismissed is called only when the Yes button is clicked . after the dismissed is called remove the item from the current list
void _onDismissed(BuildContext context, index) => setState(
() {
FavouriteSong favouriteSong = favouriteSongs[index];
favouriteSongs.removeAt(index);
BlocProvider.of<FavouriteSongBloc>(context)
.add(DeleteFavouriteSong(favouriteSong: favouriteSong));
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content:
AutoSizeText("${favouriteSong.title} ကိုဖျက်လိုက်ပါပြီ။"),
duration: const Duration(seconds: 3),
action: SnackBarAction(
label: 'မဖျက်တော့ပါ',
onPressed: () {
favouriteSongs.insert(index, favouriteSong);
BlocProvider.of<FavouriteSongBloc>(context).add(
CreateFavouriteSong(favouriteSong: favouriteSong),
);
},
),
),
);
},
);
You just forget to remove element to current list and refresh with setState(() {})
return Dismissible(
key: Key(widget.task.id.toString()),
background: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: Colors.red,
),
),
onDismissed: (direction) async {
Task copied = widget.task;
taskBloc.deleteTask(widget.task.id);
changeValue(widget.task.categoryId, false);
setState(() {})
Flushbar(
messageText: Text('Task deleted', style: bodyText.copyWith(
color: Colors.white
)),
duration: Duration(seconds: 10),
margin: EdgeInsets.all(8),
borderRadius: 8,
icon: Icon(FontAwesomeIcons.infoCircle, color: widget.color),
flushbarStyle: FlushbarStyle.FLOATING,
dismissDirection: FlushbarDismissDirection.HORIZONTAL,
mainButton: FlatButton(
onPressed: () async {
// to success rollback you must change id because of (Key(widget.task.id.toString())),
// otherwise you will get the same error
taskBloc.addTask(copied);
changeValue(widget.task.categoryId, true);
},
child: Text('Undo', style: bodyText.copyWith(color: widget.color)),
),
)..show(context);
}),