I have a bottom navigation bar in a StatefulWidget, and a dialog with 3 options open camera, gallery or cancel.
Here is my code:
navigation bar
Widget build(BuildContext context) {
return new Scaffold(
body: PageView(
children: [
Container(
color: Colors.white,child: HomePage(),),
Container(
color: Colors.white,child: AddPost(),),
],
controller: pageController,
physics: NeverScrollableScrollPhysics(),
onPageChanged: onPageChanged,
),
bottomNavigationBar: CupertinoTabBar(
backgroundColor: Colors.white,
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home,
title: Container(height: 0.0),
backgroundColor: Colors.white),
BottomNavigationBarItem(
icon: Icon(Icons.add_circle,
title: Container(height: 0.0),
)
],
onTap: navigationTapped,
currentIndex: _page,
),
);
}
dialog
File file;
_selectImage( ) async {
return showDialog<Null>(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return SimpleDialog(
title: const Text('Create a Post'),
children: <Widget>[
SimpleDialogOption(
child: const Text('Take a photo'),
onPressed: () async {
Navigator.pop(context);
File imageFile =
await ImagePicker.pickImage(source: ImageSource.camera, maxWidth: 1920, maxHeight: 1200, imageQuality: 80);
setState(() {
file = imageFile;
});
}),
SimpleDialogOption(
child: const Text('Choose from Gallery'),
onPressed: () async {
Navigator.of(context).pop();
File imageFile =
await ImagePicker.pickImage(source: ImageSource.gallery, maxWidth: 1920, maxHeight: 1200, imageQuality: 80);
setState(() {
file = imageFile;
});
}),
SimpleDialogOption(
child: const Text("Cancel"),
onPressed: () {
Navigator.pop(context);
},
)
],
);
},
);
}
I want to do something like this, i can open the dialog but it didn't wait til option is selected
void navigationTapped(int page) async{
if(page != 1){
pageController.jumpToPage(page);
}else{
await _selectImage(); //opens dialog
}
//Handle button tap
}
How can i do to await until option is select by the user on tap the navigation bar?
Thanks in advance!
In your _selectImage function, you can wait the dialog to be closed to do some code like this :
await showDialog(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return SimpleDialog(
title: const Text('Create a Post'),
children: <Widget>[
SimpleDialogOption(
child: const Text('Take a photo'),
onPressed: () async {
Navigator.pop(context);
File imageFile = await ImagePicker.pickImage(source: ImageSource.camera, maxWidth: 1920, maxHeight: 1200, imageQuality: 80);
setState(() {
file = imageFile;
});
}),
SimpleDialogOption(
child: const Text('Choose from Gallery'),
onPressed: () async {
Navigator.of(context).pop();
File imageFile = await ImagePicker.pickImage(source: ImageSource.gallery, maxWidth: 1920, maxHeight: 1200, imageQuality: 80);
setState(() {
file = imageFile;
});
}),
SimpleDialogOption(
child: const Text("Cancel"),
onPressed: () {
Navigator.pop(context);
},
)
],
);
},
).then((onValue) {
if (onValue != null) {
/// Code you want to do
}
});
The onValue can be set using this function :
Navigator.pop(context, valueYouWantToReturn);
If you want to do some code even if onValue is null (Navigator.pop(context)), delete the condition
Related
So I am facing this problem that my alert Dialog isn't displaying. I had tried every possible solution and searching here and there but nothing works. When I click on the edit button from the pop up menu nothing is displayed everything remains the same.
Calling alert Dialog
trailing: PopupMenuButton(
icon: Icon(Icons.more_vert),
itemBuilder: (context)=>[
PopupMenuItem(
value:1,
onTap: (){
//debugPrint('popup');
Navigator.pop(context);
_showMyDialog();
},
child: ListTile(
leading: Icon(Icons.edit),
title: Text('Edit'),
)),
PopupMenuItem(
value:1,
// onTap: (){
// Navigator.pop(context);
// showDialogBox();
// },
child: ListTile(
leading: Icon(Icons.delete),
title: Text('Delete'),
)),
]),
Alert Dialog Code
Future<void> showDialogBox(String title)async{
editController.text=title;
debugPrint('dialog');
return showDialog<void>(
context: context,
barrierDismissible: false,
builder: (BuildContext context){
debugPrint('alert');
return AlertDialog(
title: Text('Update'),
content: Container(
child: TextFormField(
controller: editController,
),
),
actions: [
TextButton(onPressed: (){
Navigator.pop(context);
}, child: Text('Update')),
TextButton(onPressed: (){
Navigator.pop(context);
}, child: Text('Cancel')),
],
);
}
);
}
Complete Class Code
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_database/ui/firebase_animated_list.dart';
import 'package:firebase_tutorial/utils/routes/routes_names.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:firebase_database/firebase_database.dart';
import '../../utils/utils.dart';
class PostScreen extends StatefulWidget {
const PostScreen({Key? key}) : super(key: key);
#override
State<PostScreen> createState() => _PostScreenState();
}
class _PostScreenState extends State<PostScreen> {
final ref=FirebaseDatabase.instance.ref('Post');
FirebaseAuth _auth=FirebaseAuth.instance;
final searchController=TextEditingController();
final editController=TextEditingController();
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: ()async{
SystemNavigator.pop();
return true;
},
child: Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
title: Text('Post Screen'),
actions: [
GestureDetector(
onTap: (){
_auth.signOut().then((value){
Navigator.pushNamed(context, RoutesNames.loginScreen);
}).onError((error, stackTrace){
Utils().toastMessage(error.toString());
});
},
child: Icon(Icons.logout_outlined)),
SizedBox(width: 10,),
],
),
floatingActionButton: FloatingActionButton(
onPressed:(){
Navigator.pushNamed(context, RoutesNames.newPost);
},
child: Icon(Icons.add),),
body: Column(
children: [
// Expanded(
// child:FirebaseAnimatedList(
// query: ref,
// itemBuilder: (context,snapshot,animation,index){
// return ListTile(
// title: Text(snapshot.child('post').value.toString()),
// );
// }
// ),
// ),
Padding(
padding: const EdgeInsets.all(10.0),
child: TextFormField(
onChanged: (String value){
setState(() {
});
},
controller: searchController,
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: "Search",
),
),
),
Expanded(child: StreamBuilder(
stream: ref.onValue,
builder: (context,AsyncSnapshot<DatabaseEvent> snapshot){
if(!snapshot.hasData){
return CircularProgressIndicator();
}
else{
return ListView.builder(
itemCount: snapshot.data!.snapshot.children.length,
itemBuilder: (context,index){
Map<dynamic,dynamic> map=snapshot.data!.snapshot.value as dynamic;
List<dynamic> list=[];
list.clear();
list=map.values.toList();
final title=list[index]['post'].toString();
if(searchController.text.isEmpty){
return ListTile(
title: Text(list[index]['post']),
subtitle: Text(list[index]['id'].toString()),
trailing: PopupMenuButton(
icon: Icon(Icons.more_vert),
itemBuilder: (context)=>[
PopupMenuItem(
value:1,
onTap: (){
//debugPrint('popup');
Navigator.pop(context);
_showMyDialog();
},
child: ListTile(
leading: Icon(Icons.edit),
title: Text('Edit'),
)),
PopupMenuItem(
value:1,
// onTap: (){
// Navigator.pop(context);
// showDialogBox();
// },
child: ListTile(
leading: Icon(Icons.delete),
title: Text('Delete'),
)),
]),
);
}
else if(title.toLowerCase().contains(searchController.text.toLowerCase())){
return ListTile(
title: Text(list[index]['post']),
subtitle: Text(list[index]['id'].toString()),
);
}
else{
return Container();
}
});
}
}))
],
),
),
);
}
Future<void> showDialogBox(String title)async{
editController.text=title;
debugPrint('dialog');
return showDialog<void>(
context: context,
barrierDismissible: false,
builder: (BuildContext context){
debugPrint('alert');
return AlertDialog(
title: Text('Update'),
content: Container(
child: TextFormField(
controller: editController,
),
),
actions: [
TextButton(onPressed: (){
Navigator.pop(context);
}, child: Text('Update')),
TextButton(onPressed: (){
Navigator.pop(context);
}, child: Text('Cancel')),
],
);
}
);
}
}
try adding a delay before calling showDialog like this:
await Future.delayed(const Duration(milliseconds: 10));
Your dialog isnt displayed because when you select a menu item the pop() method is automatically called to close the popup menu; so if you open a dialog immediately, the dialog will get automatically popped.
hope this fixes your issue
I am getting the following error while expecting the method buildSplashScreen() to return image:
D/MediaScannerConnection(10257): Scanned /storage/emulated/0/Android/data/com.fluttershare.fluutershare/files/Pictures/e1c7909c-9c92-42c1-a7b4-1155b56931267294677592146716356.jpg to null
════════ Exception caught by widgets library ═══════════════════════════════════
The following assertion was thrown building Upload(dirty, dependencies: [_LocalizationsScope-[GlobalKey#50363]], state: _UploadState#dc89a):
A build function returned null. >
This is my code below:
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:image_picker/image_picker.dart';
class Upload extends StatefulWidget {
#override
_UploadState createState() => _UploadState();
}
class _UploadState extends State<Upload> {
final ImagePicker _picker = ImagePicker();
PickedFile file;
handleTakePhoto() async {
Navigator.pop(context);
PickedFile file = await _picker.getImage(
source: ImageSource.camera, maxHeight: 675, maxWidth: 900);
setState(() {
this.file = file;
});
return file;
}
handleChooseFromGallery() async {
Navigator.pop(context);
file = await _picker.getImage(source: ImageSource.gallery);
setState(() {
this.file = file;
});
return file;
}
selectImage(parentContext) {
return showDialog(
context: parentContext,
builder: (context) {
return SimpleDialog(
title: Text('Create Post'),
children: <Widget>[
SimpleDialogOption(
child: Text('Photo with Camera'),
onPressed: handleTakePhoto,
),
SimpleDialogOption(
child: Text('Photo from Gallery'),
onPressed: handleChooseFromGallery,
),
SimpleDialogOption(
child: Text('Cancel'),
onPressed: () => Navigator.pop(context),
),
],
);
});
}
Container buildSplashScreen() {
return Container(
color: Colors.indigo,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SvgPicture.asset(
'assets/images/upload.svg',
height: 260.0,
),
Padding(
padding: EdgeInsets.only(top: 20.0),
child: ElevatedButton(
child: Text(
"Upload Imgae",
style: TextStyle(
color: Colors.white,
fontSize: 20.0,
),
),
onPressed: () => selectImage(context)),
),
]),
);
}
buildUploadForm() {
Text('File loaded');
}
#override
Widget build(BuildContext context) {
return file == null ? buildSplashScreen() : buildUploadForm();
}
}
Add return to buildUploadForm method:
Widget buildUploadForm() {
return Text('File loaded');
}
I'm trying to use a SimpleDialog to select an image from Gallery or Camera but I'm getting the run error type 'SimpleDialog' is not a subtype of type '(() => void)?'
This is my function to call the dialog box
selectImage(context) {
{
return SimpleDialog(
title: Text("Upload Image"),
children: [
SimpleDialogOption(
child: Text("Take Photo"),
onPressed: handleTakePhoto,
),
SimpleDialogOption(
child: Text("Upload From Gallery"),
onPressed: handleChooseFromGallery,
),
SimpleDialogOption(
onPressed: () => Navigator.pop(context),
child: Center(
child: Text("Cancel"),
),
),
],
);
}
}
My handleTakePhoto and handleChooseFromGallery functions are as
handleTakePhoto() async {
Navigator.pop(context);
File file = (await ImagePicker().getImage(
source: ImageSource.camera,
maxHeight: 675.0,
maxWidth: 960,
// imageQuality: 50, //TODO: Look into this
)) as File;
setState(() {
this.file = file;
});
}
handleChooseFromGallery() async {
Navigator.pop(context);
File file = (await ImagePicker().getImage(
source: ImageSource.gallery,
maxWidth: 960,
maxHeight: 675,
preferredCameraDevice: CameraDevice.rear)) as File;
setState(() {
this.file = file;
});
}
Where have I gone wrong?
try to this way implement third dialog
SimpleDialogOption(
onPressed: () { Navigator.pop(context) },
child: Center(
child: Text("Cancel"),
),
),
SimpleDialog needs to be wrap inside showDialog, to get it displayed
Future<void> selectImage() async {
await showDialog(
context: context,
builder: (BuildContext context) {
return SimpleDialog(
title: Text("Upload Image"),
children: [
SimpleDialogOption(
child: Text("Take Photo"),
onPressed: handleTakePhoto,
),
SimpleDialogOption(
child: Text("Upload From Gallery"),
onPressed: handleChooseFromGallery,
),
SimpleDialogOption(
onPressed: () => Navigator.pop(context),
child: Center(
child: Text("Cancel"),
),
),
],
);
});
}
Output:
While I am trying to upload a picture using uploadcare. Once I upload an image I do not receive a further response. Maybe I am missing something, but I have been following uploadcare's documentations.
Initialization of uploadcare auth.
#override
void initState() {
super.initState();
_uploadcareClient = UploadcareClient.withSimpleAuth(
publicKey: DotEnv().env['UPLOADCARE_PUBLIC_KEY'],
privateKey: DotEnv().env['UPLOADCARE_PRIVATE_KEY'],
apiVersion: 'v0.5',
);
}
I followed the steps to upload image as shown bellow
Future _onUpload() async {
final file = await showModalBottomSheet<File>(
context: context,
builder: (context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ListTile(
title: Text('Pick image from gallery'),
onTap: () async => Navigator.pop(
context,
await ImagePicker.pickImage(
source: ImageSource.gallery,
),
),
),
ListTile(
title: Text('Pick image from camera'),
onTap: () async => Navigator.pop(
context,
await ImagePicker.pickImage(
source: ImageSource.camera,
),
),
),
ListTile(
title: Text('Pick video from gallery'),
onTap: () async => Navigator.pop(
context,
await ImagePicker.pickVideo(
source: ImageSource.gallery,
),
),
),
ListTile(
title: Text('Pick video from camera'),
onTap: () async => Navigator.pop(
context,
await ImagePicker.pickVideo(
source: ImageSource.camera,
),
),
),
],
);
});
if (file != null) {
Navigator.push(
context,
MaterialPageRoute(
fullscreenDialog: true,
builder: (context) => UploadScreen(
file: file,
uploadcareClient: _uploadcareClient,
),
));
}
}
Upload process:
child: RaisedButton(
color: const Color(0xFF5867DD),
onPressed: (){
updateProfilePic();
},
Widget updateProfilePic(){
return SimpleDialog(
title: const Text('Select any option'),
children: <Widget>[
SimpleDialogOption(
onPressed: () { profileImg = ImagePicker.pickImage(source: ImageSource.gallery)
.whenComplete(() {
setState(() {});
}); },
child: const Text('open gallery'),
),
SimpleDialogOption(
onPressed: () { profileImg = ImagePicker.pickImage(source: ImageSource.camera)
.whenComplete(() {
setState(() {});
}); },
child: const Text('open camera'),
),
],
);
}
I am trying to implement Dialog when the button is pressed.I want to select image from gallery and camera so that i created a dialog to select any option to upload the picture.The issue is when i click the button dialog is not visible.
You need to call showDialog
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text(title),
content: Text(message),
);
});
As mentioned by Figen Güngör You need to call showDialog.
Just want to clarify that it is a Future (function) not a Widget, therefore your code would be like this:
Future updateProfilePic(BuildContext context){
return showDialog(
context: context,
builder : (BuildContext context){
return SimpleDialog(
title: const Text('Select any option'),
children: <Widget>[
SimpleDialogOption(
onPressed: () { profileImg = ImagePicker.pickImage(source: ImageSource.gallery)
.whenComplete(() {
setState(() {});
}); },
child: const Text('open gallery'),
),
SimpleDialogOption(
onPressed: () { profileImg = ImagePicker.pickImage(source: ImageSource.camera)
.whenComplete(() {
setState(() {});
}); },
child: const Text('open camera'),
),
],
);
},
);
}