I am trying to call a method from navbar, when I call the object the image has been selected not appears in the screen.
My goal is to do this, when I Click in Gallery and select new image, show this like in Screen 2.
The code for this interactions,
File imageFile;
_openGallery(BuildContext context) async{
var picture = await ImagePicker.pickImage(source:ImageSource.gallery);
this.setState((){
imageFile = picture;
});
Navigator.of(context).pop();
}
_openCamera(BuildContext context) async{
var picture = await ImagePicker.pickImage(source:ImageSource.camera);
this.setState((){
imageFile = picture;
});
Navigator.of(context).pop();
}
And the build widget
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
_decideImageView(),
RaisedButton(onPressed: (){
_showChoiceDialog(context);
},child: Text('Select Image'),),
_decideButton(context)
],
),
),
),
bottomNavigationBar: BottomNavigationBar(
type:BottomNavigationBarType.fixed,
onTap: (int index) {
if (index==0)
_openGallery(context);
if (index == 1)
_openCamera(context);
},
items: [
BottomNavigationBarItem(
icon: Icon(Icons.photo_library),
title: Text('Home')
),
BottomNavigationBarItem(
icon: Icon(Icons.camera_alt),
title: Text('Camera')
),
],
),
);
}
The function to decide if you will see a text asking for select a image or return the image on the screen is this one below, the method is called _decideImageView.
Widget _decideImageView(){
if(imageFile == null){
return Text('Kein Bild ausgewählt',
style: TextStyle(
color:Colors.black,
fontFamily: 'Lato',
fontSize: 25,
letterSpacing: 1.0
), );
}
else{
return Image.file(imageFile,width:400,height:400);
}
}
Try to remove this: Navigator.of(context).pop();
on the two ways to pick the picture, that's work for me, but you need to know that's not the best way to create an image picker.
Related
I faced a problem when I use Image Picker for pick Image from gallery
my phone stop
and it told me that "Lost connection to device "-_-..Although it works for pick image from camera
what should I do??
and I try some solutions from the internet and I don't find any thing help me in my problem...
This is a code of function
enter code here
File? _image;
bool isSelected =false;
final imagePicker=ImagePicker();
Future uploadImage(ImageSource src) async{
try{
final selectedImage = await imagePicker.pickImage(source:src);
if (selectedImage == null) return;
final imagetemporary = File(selectedImage.path);
setState(() => _image = imagetemporary);
}on PlatformException catch(e){
print('failed to pick image :$e');
}
}
this is the code I use my function in it :
enter code here
ProfileWidget(
imgPath: user.imgPath,
isEdit:true,
isSelected: _image!=null?true:false,
imageFile: _image!=null?_image:null,
onClicked: (){
var ad =AlertDialog(
title: const Text('Choose Picture from :',),
content: Container(
height: 22.h,
child: Column(
children: [
Divider(color: lbb,),
Container(
height:8.h,
color: gray,
child: ListTile(
leading: const Icon(Icons.camera_alt),
title: const Text('Camera'),
onTap: (){
uploadImage(ImageSource.camera);
Navigator.of(context).pop();
},
),
),
SizedBox(height: 1.h,),
Container(
height: 8.h,
color: gray,
child: ListTile(
leading:const Icon(Icons.image),
title: const Text('Gallery'),
onTap: (){
uploadImage(ImageSource.gallery);
Navigator.of(context).pop();
},
),
),
],
),
),
);
showDialog(context: context, builder:(context)=>ad );
}
),
For instance: I have a main Icon so when you click on it, it opens a pop-up window with smaller icons/images to select from. So if you select one of the pictures from that pop-up it replaces the main Icon to that specific image.
I have spent hours trying to figure out how to replace icon images but nothing seems to work.
I have created an example (I have used flutter_speed_dial to make expandable buttons but it's not necessary). You can adjust it to your needs:
class _TestState extends State<Test> {
var fabIcon = Icons.expand_less;
var button1Icon = Icons.home;
var button2Icon = Icons.shop;
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
floatingActionButton: SpeedDial(
icon: fabIcon,
backgroundColor: Color(0xFF801E48),
visible: true,
curve: Curves.bounceIn,
children: [
// FAB 1
SpeedDialChild(
child: Icon(button1Icon),
backgroundColor: Color(0xFF801E48),
onTap: () {
var temp = fabIcon;
setState(() {
fabIcon = button1Icon;
button1Icon = temp;
});
},
labelStyle: TextStyle(
fontWeight: FontWeight.w500,
color: Colors.white,
fontSize: 16.0),
labelBackgroundColor: Color(0xFF801E48)),
// FAB 2
SpeedDialChild(
child: Icon(button2Icon),
backgroundColor: Color(0xFF801E48),
onTap: () {
var temp = fabIcon;
setState(() {
fabIcon = button2Icon;
button2Icon = temp;
});
},
labelStyle: TextStyle(
fontWeight: FontWeight.w500,
color: Colors.white,
fontSize: 16.0),
labelBackgroundColor: Color(0xFF801E48))
],
),
),
);
}
}
Using showDialog(...) is the solution.
Hope this will help you and others.
you can look at this example:
import 'package:flutter/material.dart';
class IconDialogScreen extends StatefulWidget {
const IconDialogScreen({Key? key}) : super(key: key);
#override
State<IconDialogScreen> createState() => _IconDialogScreenState();
}
class _IconDialogScreenState extends State<IconDialogScreen> {
IconData icon = Icons.abc;
List<IconData> icons = [
Icons.abc,
Icons.person_add,
Icons.person,
Icons.person_remove,
];
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Center(
child: TextButton(
onPressed: onIconClicked,
child: Wrap(
crossAxisAlignment: WrapCrossAlignment.center,
spacing: 20,
children: [Icon(icon, size: 50), const Text("change icon")],
),
),
)
],
),
);
}
void onIconClicked() async {
IconData? _icon = await showDialog<IconData?>(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('Select one icon'),
content: Wrap(
spacing: 10,
runSpacing: 10,
children: icons.map<Widget>((e) {
return ElevatedButton(
onPressed: () {
Navigator.of(context).pop(e);
},
child: Icon(e, size: 50));
}).toList(),
),
);
},
);
if (_icon != null) {
setState(() {
icon = _icon;
});
}
}
}
I am currently able to share the text on top of the image using share package but I want to share the image and text along with it without my icons of refresh and share. Couldn't find any answers for this. Have used multiple share packages but couldn't achieve the expected result.
Widget build(BuildContext context) {
return Scaffold(
body: Stack(children: <Widget>[
Container(
constraints: BoxConstraints.expand(),
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage("${imgUrl}$count"),
fit: BoxFit.fill)
),
),
FutureBuilder<Advice>(
future: advice,
builder: (context, snapshot) {
if (snapshot.hasData) {
return SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
margin: EdgeInsets.only(left: 30.0),
child: FadeTransition(
opacity: _animation,
child: Text(
snapshot.data!.adviceText,
style: TextStyle(
decoration: TextDecoration.none,
fontSize: 30.0,
color: Colors.white,
fontFamily: 'quoteScript'),
),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
IconButton(
icon: Icon(Icons.refresh, color: Colors.white),
onPressed: () async {
setState(() {
_controller.reset();
_controller.forward();
count++;
advice = fetchAdvice();
});
},
),
IconButton(
icon: Icon(Icons.share, color: Colors.white),
onPressed: () {
Share.share("Here's an advice for you: ${snapshot.data!.adviceText}");
},
),
],
),
],
),
);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
// By default, show a loading spinner.
return Center(child: CircularProgressIndicator());
},
),
]),
);
}
This is the text and image widget. Can be shared with the dynamic text.
SHARE: The best way I think is to use screenshot package to capture the widget which contains both image and text that you need to share, then share it as a picture with share_plus package.
For instance:
// Create a controller
ScreenshotController screenshotController = ScreenshotController();
[...]
// Wrap the widget which you want to capture with `Screenshot`
Screenshot<Widget>(
controller: screenshotController,
child: Container(
child: [...]
),
),
[...]
// Create a method to take a screenshot and share it
// This method I get from my project, so you can modify it to fit your purpose
Future<void> shareScreen(String title, String name) async {
final screenShot = await screenshotController.capture();
if (screenShot != null) {
final Directory tempDir = await getTemporaryDirectory();
final File file = await File('${tempDir.path}/$name').create();
await file.writeAsBytes(screenShot);
await Share.shareFiles(<String>[file.path], subject: title, text: name);
file.delete();
}
}
Then replace the Share.share method in the below example with the shareScreen method just created above.
HIDE BUTTON: You can create a new variable like bool isSharing = false; to control the visible state of those 2 buttons. The important part is the Share.share method must be an async method to make the code works because it needs await to know when the share action is done.
For instance:
[...]
if (!isSharing) // <--- Add this line
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
IconButton(
icon: Icon(Icons.refresh, color: Colors.white),
onPressed: () async {
setState(() {
_controller.reset();
_controller.forward();
count++;
advice = fetchAdvice();
});
},
),
IconButton(
icon: Icon(Icons.share, color: Colors.white),
// And modify here <---
onPressed: () async {
setState(() => isSharing = true); // Hide the buttons
await Share.share(
"Here's an advice for you: ${snapshot.data!.adviceText}");
setState(() => isSharing = false); // Show the buttons
},
),
],
),
[...]
I am working on a flutter project which has a navigation drawer with three routes. Whenever i go to a particular route and come back, the navigation drawer gets opened automatically. I want the navigation drawer to remain closed until and unless the user specifically clicks on it. Is there any way to achieve this?
Here's my code:
class NavList extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
UserAccountsDrawerHeader(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('images/orange.png'),
fit: BoxFit.cover,
)),
arrowColor: Colors.deepOrangeAccent[700],
accountName: Text(''),
accountEmail: Text(
'username#gmail.com',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20.0,
),
),
currentAccountPicture: CircleAvatar(
radius: 22.0,
backgroundColor: Colors.deepOrangeAccent[700],
backgroundImage: AssetImage('images/profile.png'),
),
),
ListItems(
listTitle: 'Shops',
listIcon: Icon(Icons.shop),
listFunction: () {
Navigator.pushNamed(context, ShopScreen.id);
},
),
ListItems(
listTitle: 'Orders',
listIcon: Icon(Icons.monetization_on),
listFunction: () {
Navigator.pushNamed(context, OrderScreen.id);
},
),
ListItems(
listTitle: 'Logout',
listIcon: Icon(Icons.logout),
listFunction: () {
Navigator.pushNamed(context, LoginScreen.id);
},
),
],
),
);
}
}
I have refactored ListItems.
class ListItems extends StatelessWidget {
ListItems({this.listTitle, this.listIcon, this.listFunction});
final String listTitle;
final Icon listIcon;
final Function listFunction;
#override
Widget build(BuildContext context) {
return ListTile(
title: Text(listTitle),
leading: IconButton(
icon: listIcon,
onPressed: () {
},
),
onTap: listFunction,
);
}
}
There are some ways to do that like:
onPressed:(){
Navigator.pop(context);
Navigator.pushNamed(context, ShopScreen.id);
}
or use .then of the navigator:
onPressed:(){
Navigator.pushNamed(context, ShopScreen.id).then((val){
Navigator.pop(context);
});
}
additionally, you can check If the drawer currently open or not:
onPressed:(){
Navigator.pushNamed(context, ShopScreen.id).then((val){
if(Scaffold.of(context).isDrawerOpen){
Navigator.pop(context);
}
});
}
I hadn't tested this out. Maybe this might work
onPressed: () async {
await Navigator.pushNamed(
context, "Screen").then((value) =>
Scaffold.of(context).openEndDrawer());
},
This may help you
onPressed: () {
Navigator.pop(context);
Navigator.of(context).pushNamed('/settings');
}
I am trying to add a button on an image on tap position.
I have managed to get position on tap by using onTapUp's detail parameter.
However, I can't add an icon button when user taps on the image.
Below code shows my sample.
class ArticlesShowcase extends StatelessWidget {
final commentWidgets = List<Widget>();
#override
Widget build(BuildContext context) {
return new GestureDetector(
child: new Center(
child: Image.network(
'https://via.placeholder.com/300x500',
),
),
onTapUp: (detail) {
final snackBar = SnackBar(
content: Text(detail.globalPosition.dx.toString() +
" " +
detail.globalPosition.dy.toString()));
Scaffold.of(context).showSnackBar(snackBar);
new Offset(detail.globalPosition.dx, detail.globalPosition.dy);
var btn = new RaisedButton(
onPressed: () => {},
color: Colors.purple,
child: new Text(
"Book",
style: new TextStyle(color: Colors.white),
),
);
commentWidgets.add(btn);
},
);
}
}
I tried to add the button on the list but no chance.
So , there are a couple of things you are missing.
First you can't update a StatelessWidget state , so you need to use a StatefulWidget.
Second, when using a StatefulWidget , you need to call setState to update the State.
You will also need to use a Stack and Positioned widgets to put the buttons on your specific location.
Your code should end and look like this.
class ArticlesShowcaseState extends State<ArticlesShowcase> {
final commentWidgets = List<Widget>();
void addButton(detail) {
{
final snackBar = SnackBar(
content: Text(
"${detail.globalPosition.dx.toString()} ${detail.globalPosition.dy.toString()}"));
Scaffold.of(context).showSnackBar(snackBar);
var btn = new Positioned(
left: detail.globalPosition.dx,
top: detail.globalPosition.dy,
child: RaisedButton(
onPressed: () => {},
color: Colors.purple,
child: new Text(
"Book",
style: new TextStyle(color: Colors.white),
),
));
setState(() {
commentWidgets.add(btn);
});
}
}
#override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
GestureDetector(
child: new Center(
child: Image.network(
'https://via.placeholder.com/300x500',
),
),
onTapUp: (detail) => addButton(detail),
)
] +
commentWidgets,
);
}
}