How to pass image from toggle button to next page in flutter? - flutter

I am new to flutter and i am trying out new things.my question is how to pass image from toggle button to next page in flutter?
This is the code for toggle button which have image and text in it,I want to pass selected image to next page
Container(
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: ToggleButtons(
borderWidth: 1,
children:<Widget> [
Padding(padding: EdgeInsets.only(left:10),
child:
CustomIcon(
text:Text("TATA ACE",style: TextStyle(color: Colors.white,fontWeight: FontWeight.bold,fontSize: 12),),
image: Image.asset("images/delivery.png",scale: 9,),
isSelected: isSelected[0],
bgColor:const Color(0x000000),
),),
Padding(padding: EdgeInsets.only(left:10),
child:
CustomIcon(
text: Text("TATA APE",style: TextStyle(color: Colors.white,fontWeight: FontWeight.bold,fontSize: 12),),
image: Image.asset("images/delivery.png",scale: 9,),
isSelected: isSelected[1],
bgColor: const Color(0x000000),
),),
CustomItem class is also defined below
class CustomIcon extends StatefulWidget {
final Image image;
final Text text;
final bool isSelected;
final Color bgColor;
const CustomIcon(
{Key? key,
required this.text,
required this.image,
this.isSelected = false,
this.bgColor = Colors.black, value1})
: super(key: key);
#override
_CustomIconState createState() => _CustomIconState();
}
class _CustomIconState extends State<CustomIcon> {
#override
Widget build(BuildContext context) {
return Container(
width: 105,
height: 105,
decoration: BoxDecoration(
color: widget.isSelected
? Colors.black : Colors.grey,shape: BoxShape.rectangle,
borderRadius: const BorderRadius.all(
Radius.circular(100),
),
),
child: Center(
child: Container(
padding: EdgeInsets.all(15),
height: 105,
width: 105,
decoration: BoxDecoration(
color: widget.bgColor,
borderRadius: const BorderRadius.all(
Radius.circular(100),
),
),
child:Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
widget.image,
widget.text,
],
),
),
),
);
}
}
I need to pass this text and image to the next page or just image to next screen.

Related

how to display input value from text field to other pages?

I'm trying to display the input value below onto another page that contains radio buttons . my aim is that every time i write or change a value in a textfield it gets updated and displays onto a different page with the radio options . The snippet of code below is for the textfield - i used riverpod to connect it to firestore:
class AddMealPage extends ConsumerWidget {
const AddMealPage({Key? key}) : super(key: key);
static const String route = "/addMeal";
#override
Widget build(BuildContext context, WidgetRef ref) {
final model = ref.read(addMealProvider);
return LoadingLayer(
child: Scaffold(
appBar: AppBar(
elevation: 0,
iconTheme: const IconThemeData(
color: Colors.black,
),
title: const Text(
"Create Meal",
style: TextStyle(color: Colors.black, fontWeight: FontWeight.bold),
),
backgroundColor: Colors.white,
),
bottomNavigationBar: Padding(
padding: const EdgeInsets.fromLTRB(24, 0, 24, 24),
child: MaterialButton(
padding: const EdgeInsets.all(16),
color: Colors.black,
onPressed: model.enabled
? () async {
try {
await model.writeMeal();
Navigator.pop(context);
} catch (e) {
AppSnackbar(context).error(e);
}
}
: null,
child: const Text(
"Add meal",
style: TextStyle(color: Color.fromARGB(255, 247, 245, 245)),
),
),
),
body: SingleChildScrollView(
child: Container(
padding:
const EdgeInsets.symmetric(vertical: 60.0, horizontal: 10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
GestureDetector(
onTap: () async {
final picked = await ImagePicker()
.pickImage(source: ImageSource.gallery);
if (picked != null) {
model.file = File(picked.path);
}
},
child: Container(
margin: const EdgeInsets.only(),
width: MediaQuery.of(context).size.width,
height: 210.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
image: (model.mealUrl != null || model.file != null)
? DecorationImage(
image: model.file != null
? FileImage(model.file!)
: NetworkImage(model.mealUrl!)
as ImageProvider,
fit: BoxFit.cover,
)
: null),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
if (model.mealUrl == null && model.file == null)
const Expanded(
child: Center(
child: Icon(
Icons.photo,
),
),
),
const Material(
color: Colors.transparent,
child: Padding(
padding: EdgeInsets.all(8.0),
),
),
],
),
),
),
const SizedBox(
height: 10,
),
const Padding(
padding: EdgeInsets.only(left: 15.0),
child: Text(
"Meal Name",
style: TextStyle(fontSize: 17, fontWeight: FontWeight.w500),
),
),
Container(
height: 50,
padding: const EdgeInsets.only(top: 10),
width: MediaQuery.of(context).size.width,
margin: const EdgeInsets.symmetric(horizontal: 20),
child: TextFormField(
textInputAction: TextInputAction.done,
initialValue: model.mealName,
maxLines: 1,
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(color: Colors.grey),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: const BorderSide(color: Colors.grey),
),
),
onChanged: (v) => model.mealName = v,
),
),
I want to display the input value i get from the textfield above in the format of a radioButton on a seperate page :
enum Variant { mealName }
class RadioOption extends StatefulWidget {
const RadioOption({Key? key}) : super(key: key);
#override
State<RadioOption> createState() => _RadioOptionState();
}
class _RadioOptionState extends State<RadioOption> {
Variant? _character = Variant.mealName;
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
RadioListTile<Variant>(
title: const Text('$mealName'),
value: Variant.MealName,
groupValue: _character,
onChanged: (Variant? value) {
setState(() {
_character = value;
});
},
),
I don't see the whole architecture of the app. But if you want to transfer model.mealName, you can make String value (mealName) in your RadioOption, and pass it through the constructor:
final mealName;
RadioOption({required this.mealName});
And then access it in _RadioOptionState by:
title: const Text(widget.mealName);
You can use TextEditingController and add this controller to your TextFormField which have controller properties but you can't use initialValue and controller both so avoid initialValue. To put value you can use controller.text = your_value;
You value will be filled in text field.
To get value from TextFormField Use var newValue = controller.text; and send this newValue to another page in constructor.

flutter - PageView Builder & Card - displaying different info on each card

I am trying to use PageView and Card. My objective is to display different information on the fourth cards that the user can see.
To be more precise, on one card, I could display a title for example. On the second card, I will display dates, on the third card, it could be some random text...
I hope this is clear.
To give you more color on this, the information will come from FireBase.
I do not know how to do this easily. I have considered to create 4 widget myCard, with different info on it and to use them. But I would like to do something more professional and efficient. Thank you
About FireBase, I do not use json. I have a simple document in FireBase. In this document, I have several fields, like 'price' 'quantity' 'reference'...
I just want that each card to display two or three fields from this FireBase document.
class MyBodyWindMill extends StatefulWidget {
const MyBodyWindMill({Key key}) : super(key: key);
#override
_MyBodyWindMillState createState() => _MyBodyWindMillState();
}
class _MyBodyWindMillState extends State<MyBodyWindMill> {
#override
Widget build(BuildContext context) {
return
Container(
height: 260,
child: PageView.builder(controller: PageController(viewportFraction: 0.88),
itemCount: 4,
itemBuilder: ( _, i){
return GestureDetector(
child: Container(
padding: const EdgeInsets.only(left:20, top:20),
height: 220,
width: MediaQuery.of(context).size.width-20,
margin: const EdgeInsets.only(right:10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
),
child:Column(
children: [
MyCard(),
],
))
);
},
));
}}
class MyCard extends StatefulWidget {
const MyCard( {Key key} ) : super(key: key);
#override
_MyCardState createState() => _MyCardState();
}
class _MyCardState extends State<MyCard> {
//String monText;
#override
Widget build(BuildContext context) {
return Container(
height: 230,
child: Stack(
children: [
Positioned(
top: 35,
left: 20,
child: Card(
elevation: 6.0,
shadowColor: Colors.grey,
child: Container(
height: 180,
width: 0.9,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(0.0),
boxShadow: [BoxShadow(
color: Colors.black.withOpacity(0.3),
offset: Offset(-10.0, 10.0),
blurRadius: 20.0,
spreadRadius: 4.0,
),
])
),
),
),
Positioned(
top: 0.0,
left: 30.0,
child:Card(
elevation: 10.0,
shadowColor: Colors.grey.withOpacity(0.5),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
child: Container(
height: 200,
width: 150,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.0),
image: DecorationImage(
fit: BoxFit.fill,
image:AssetImage('assets/header.jpg'),
),
),
))),
Positioned(
top:40,
left:200,
child:
Container(
height: 150,
width: 170,
child:Column(
crossAxisAlignment: CrossAxisAlignment.start,
children:[
Text('Title: ', style: TextStyle(fontSize:16,
color:Colors.red),),
Divider(color:Colors.black),
Text('Info 1: ', style: TextStyle(fontSize:16,
color:Colors.red),),
Text('Info 2'),
])
))
],
),
);
}
}
Based on what you're trying to do it looks like what you need is something like this widget:
class InfoBlock {
final String title;
final String description;
InfoBlock({
required this.title,
required this.description,
});
}
class MyCard extends StatefulWidget {
String title;
List<InfoBlock> infoBlocks;
MyCard({
Key? key,
required this.title,
required this.infoBlocks,
}) : super(key: key);
#override
_MyCardState createState() => _MyCardState();
}
class _MyCardState extends State<MyCard> {
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 200,
width: 200,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.0),
image: const DecorationImage(
fit: BoxFit.fill,
image: AssetImage('header.jpeg'),
))),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
widget.title,
style: const TextStyle(fontSize: 30),
),
...widget.infoBlocks.map((block) {
return Text(
'${block.title}: ${block.description}',
style: const TextStyle(fontSize: 16),
);
}),
],
)
],
),
);
}
}
And then you can use it like-so:
Column(
children: [
MyCard(
title: 'Quantity',
infoBlocks: [
InfoBlock(title: 'Price', description: '100'),
],
),
MyCard(
title: 'Status',
infoBlocks: [
InfoBlock(title: 'Txt1', description: 'value1'),
InfoBlock(title: 'Txt2', description: 'value2'),
InfoBlock(title: 'Txt3', description: 'value3'),
],
),
],
));
And here's what the output would look like:
Here's a a link to Flutlab with the above code fully functional: https://flutlab.io/ide/6d8762de-50b1-4cfe-a509-a301edaacebf

Tabs RenderFlex overflowed by 20 pixels on the bottom

I'm new in flutter and I'm trying to resolve this issue.
Updated My Code
After setting width and height of container, I'm getting this output now
Desirable output
TabsContainer.dart
class TabsContainer extends StatelessWidget {
final String image, tittle;
const TabsContainer({Key? key, required this.image, required this.tittle})
: super(key: key);
#override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
ClipRRect(
borderRadius: BorderRadius.circular(10.0),
child: Image.asset(
image,
fit: BoxFit.cover,
height: 46,
width: 46,
),
),
const SizedBox(
height: 10,
),
Text(
tittle,
textAlign: TextAlign.center,
style: const TextStyle(color: Colors.black),
)
],
);
}
}
categorypage.dart
List<Tab> tabs = [
const Tab(
height: 50,
child: TabsContainer(
image: 'assets/images/g.png', tittle: 'Social Media'),
),
const Tab(
height: 50,
child: TabsContainer(
image: 'assets/images/g.png', tittle: 'Interior Design')),
];
List<Widget> tabsContent = [
const SocialMedia(),
];
#override
Widget build(BuildContext context) {
return SafeArea(
child: DefaultTabController(
length: tabs.length,
child: Scaffold(
appBar: AppBar(
leading: IconButton(
onPressed: () {},
icon: const Icon(Icons.arrow_back_ios_rounded,
size: 30, color: AppColors.fIconsAndTextColor),
),
actions: [
IconButton(
onPressed: () {},
icon: const Icon(Icons.notifications,
size: 30, color: AppColors.fIconsAndTextColor),
)
],
elevation: 0.0,
backgroundColor: Colors.transparent),
backgroundColor: AppColors.fBackgroundColor,
body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 15.0),
child: Column(
children: [
const Align(
alignment: Alignment.centerLeft,
child: Text(
'Category',
style: TextStyle(fontFamily: "ROCK"),
)),
const SizedBox(height: 10),
TabBar(
automaticIndicatorColorAdjustment: false,
indicatorColor: Colors.transparent,
isScrollable: true,
tabs: tabs),
const SizedBox(height: 10),
Expanded(
child: TabBarView(
physics: const NeverScrollableScrollPhysics(),
children: tabsContent),
),
],
),
),
),
),
);
}
}
try this :
class TabsContainer extends StatelessWidget {
final String image, tittle;
const TabsContainer({Key? key, required this.image, required this.tittle})
: super(key: key);
#override
Widget build(BuildContext context) {
return Column(
children: [
Container(
height: 70,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.0),
color: Colors.white,
),
child: Image.asset(image),
),
Text(
tittle,
textAlign: TextAlign.center,
style: const TextStyle(color: Colors.black),
)
],
);
}
}
Tab: the default height is 72.0 pixels. Without an icon, the height is 46.0 pixels.
We need to provide our custom height in this case. And for decoration, use ClipRRect for on image.
class TabsContainer extends StatelessWidget {
final String image, tittle;
const TabsContainer({Key? key, required this.image, required this.tittle})
: super(key: key);
#override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
ClipRRect(
borderRadius: BorderRadius.circular(10.0),
child: Image.asset(
image,
fit: BoxFit.cover,
// as for Desirable output, both height and width will be same
height: 50,
width: 50,
),
),
const SizedBox(
height: 10,
), // you can use padding here
Text(
tittle,
textAlign: TextAlign.center,
style: const TextStyle(color: Colors.black),
)
],
);
}
}
And tabs will be like
List<Tab> tabs = [
const Tab(
height: 50 +
10 +
24, // image height + padding/space + 24 for font, better will be getting text size from theme
child: TabsContainer(
image: ...
),
I will also encourage you to check icon and text property for this case. The image size is ok up to 46, if you increase the size, you need to provide Tab(height:) to fix the overflow. You can use unselectedLabelStyle and labelStyle for text on TabBar.
In this case tabs will be
List<Tab> tabs = [
Tab(
text: 'Social Media',
icon: ClipRRect(
borderRadius: BorderRadius.circular(10.0),
child: Image.asset(
'assets/images/image01.png',
fit: BoxFit.cover,
// as for Desirable output, both height and width will be same
height: 46,
width: 46,
),
),
),
Tab(
text: 'Interior Design',
icon: ClipRRect(
borderRadius: BorderRadius.circular(10.0),
child: Image.asset(
'assets/images/image02.png',
fit: BoxFit.fitHeight,
// as for Desirable output, both height and width will be same
height: 46,
width: 46,
),
),
),
];

IconData not being passed into class instantiation as argument

I have the following class defined:
import 'package:flutter/material.dart';
class ItemHiddenMenu extends StatelessWidget {
/// name of the menu item
final String name;
/// callback to recibe action click in item
final Function onTap;
final Color colorLineSelected;
/// Base style of the text-item.
final TextStyle baseStyle;
/// style to apply to text when item is selected
final TextStyle selectedStyle;
final bool selected;
final IconData icon;
ItemHiddenMenu({
Key key,
this.name,
this.selected = false,
this.onTap,
this.colorLineSelected = Colors.blue,
this.baseStyle,
this.selectedStyle,
this.icon,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
margin: EdgeInsets.only(bottom: 15.0),
child: InkWell(
onTap: onTap,
child: Row(
children: <Widget>[
ClipRRect(
borderRadius: BorderRadius.only(
topRight: Radius.circular(4.0),
bottomRight: Radius.circular(4.0)),
child: Container(
height: 40.0,
color: selected ? colorLineSelected : Colors.transparent,
width: 5.0,
),
),
Expanded(
child: Container(
margin: EdgeInsets.only(left: 20.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Icon(icon),
SizedBox(
width: 15,
),
Text(
name,
style: (this.baseStyle ??
TextStyle(color: Colors.grey, fontSize: 25.0))
.merge(this.selected
? this.selectedStyle ??
TextStyle(color: Colors.white)
: null),
),
],
),
),
),
],
),
),
);
}
}
I'm trying to pass IconData as a named argument icon, like so:
new ItemHiddenMenu(
icon: Icons.dashboard,
name: "Investments by category",
baseStyle:
TextStyle(color: Colors.white.withOpacity(0.8), fontSize: 20.0),
colorLineSelected: Colors.teal,
)
The code runs fine, but the icon doesn't show. For testing purposes I tried to define icon inside of the class itself and it works, but then all my instances would have the same icon of course, which is not what I want.
What am I missing here?
I tried your code by passing IconData It works, icon is visible.
You might try Passing and Icon widget rather than IconData

Adding a image to an expansion tile

I want to add an image as a leading widget to my expansion tile. Every entry of my List has a different image. I added the image path to every entry of my list but the image is not displayed.
This is my List:
class Entry{
final String title;
final String imageUrl;
final List<Entry> children;
Entry(this.title, this.imageUrl, [this.children = const <Entry>[]]);
}
final List<Entry> data = <Entry>[
Entry(
'title', "/assets/images/picture.png",
<Entry>[
Entry(
'subtitle', '/assets/images/picture.jpg',
<Entry>[
Entry('subtitle', '/assets/images/example.jpg' ),
Entry('subtitle', '/assets/images/example.jpg' ),
Entry('subtitle', '/assets/images/example.jpg' ),
],
),
],
),
];
this is the code of the expansion tile:
import 'package:flutter/material.dart';
import '../models/entry.dart';
class EntryItem extends StatelessWidget {
const EntryItem(this.entry);
final Entry entry;
Widget _buildTiles(Entry root) {
if (root.children.isEmpty) {
return Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
border: Border.all(
width: 2,
color: Color.fromRGBO(3, 120, 163, 1),
),
),
child: ListTile(
leading: Image.asset(root.imageUrl),
title: Text(
root.title,
),
),
),
);
}
return Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
border: Border.all(
width: 3,
color: Color.fromRGBO(3, 120, 163, 1),
),
),
child: ExpansionTile(
key: PageStorageKey<Entry>(root),
leading: Image.asset(root.imageUrl),
title: Text(root.title, style: TextStyle(color: Colors.black)),
children: root.children.map<Widget>(_buildTiles).toList(),
),
),
);
}
#override
Widget build(BuildContext context) {
return _buildTiles(entry);
}
}
adding the image path directly to the leading widget works but displays the same image for all tiles.
Thank you in advance.