Can anyone advise me how to design a very specific Side menu in flutter.
It has 2 states
Collapsed (Small but icons are visible.)
Expanded (Big, Icons and text)
When collapsed it is like a Navigation rail. Only icons visible.
But when expanded, it should behave like Navigation drawer. It should blur the rest of the screen, and on click outside of it it should collapse back.
I would appreciate any help.
Thank you
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
#override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
bool is_expanded = false;
int selectedPage = 1;
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.transparent,
body: Row(
children: [
Stack(
children: <Widget>[
Container(
color: Colors.transparent,
margin: EdgeInsets.only(left: 120),
width: MediaQuery.of(context).size.width - 120,
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 1, sigmaY: 1),
child: Opacity(
opacity: is_expanded ? 0.3 : 1,
child: Listener(
onPointerDown: (v) {
if (is_expanded) {
is_expanded = false;
setState(() {});
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Click blocked'),
),
);
}
},
child: AbsorbPointer(
absorbing: is_expanded,
child: Row(
children: [
Expanded(
child: Container(
color: Colors.white,
child: PageHolder(selectedPage),
),
),
],
),
),
),
),
),
),
AnimatedContainer(
duration: Duration(milliseconds: 120),
height: double.infinity,
width: is_expanded ? 240 : 120,
color: Colors.blueGrey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox(height: 20),
Row(
mainAxisSize: MainAxisSize.min,
children: const [
Text(
'Custom drawer',
style: TextStyle(
color: Colors.white,
),
),
],
),
const SizedBox(height: 20),
InkWell(
onTap: () {
setState(() => is_expanded = !is_expanded);
},
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
"App",
style: TextStyle(
color: Colors.white,
),
),
Icon(
is_expanded ? Icons.arrow_right : Icons.arrow_left,
color: Colors.white,
)
],
),
),
const SizedBox(height: 20),
InkWell(
onTap: () {
selectedPage = 1;
is_expanded = false;
setState(() {});
},
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Text(
"Page 1",
style: TextStyle(
color: Colors.white,
),
),
],
),
),
const SizedBox(height: 20),
InkWell(
onTap: () {
selectedPage = 2;
is_expanded = false;
setState(() {});
},
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Text(
"Page 2",
style: TextStyle(
color: Colors.white,
),
),
],
),
),
],
),
),
],
),
],
),
);
}
PageHolder(selectedPage) {
switch (selectedPage) {
case 1:
{
return Page1();
}
case 2:
{
return Page2();
}
default:
{
return Page1();
}
}
}
}
class Page1 extends StatefulWidget {
const Page1({Key? key}) : super(key: key);
#override
State<Page1> createState() => _Page1State();
}
class _Page1State extends State<Page1> {
#override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('Page 1 content',
style: TextStyle(fontSize: 32),),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Test click'),
),
);
},
child: const Text('Test click'))
],
),
);
}
}
class Page2 extends StatefulWidget {
const Page2({Key? key}) : super(key: key);
#override
State<Page2> createState() => _Page2State();
}
class _Page2State extends State<Page2> {
#override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'Page 2 content',
style: TextStyle(fontSize: 32),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Test click'),
),
);
},
child: const Text('Test click'))
],
),
);
}
}```
Solution ^^
include NavigationRail widget in IntrinsicWidth widget
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
#override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
),
drawer: _NavigationRailExample(),
body: Container(),
);
}
}
class _NavigationRailExample extends StatefulWidget {
const _NavigationRailExample({Key? key}) : super(key: key);
_NavigationRailExampleState createState() => _NavigationRailExampleState();
}
class _NavigationRailExampleState extends State<_NavigationRailExample> {
int _selectedIndex = 0;
bool extended =false;
Widget build(BuildContext context) {
return SafeArea(
child: IntrinsicWidth(
child: NavigationRail(
selectedIndex: _selectedIndex,
destinations: _buildDestinations(),
extended: extended,
onDestinationSelected: (int index) {
setState(() {
_selectedIndex = index;
});
},
),
),
);
}
List<NavigationRailDestination> _buildDestinations() {
return [
NavigationRailDestination(
icon: InkWell(
onTap: () {
setState(() =>
extended = !extended);
},
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text("App"),
Icon(extended ? Icons.arrow_right : Icons.arrow_left)
],
),
),
label: Container(width: 0,) ,
),
NavigationRailDestination(
icon: Icon(Icons.home),
label: Text('Home'),
),
NavigationRailDestination(
icon: Icon(Icons.favorite),
label: Text('Favorites'),
),
NavigationRailDestination(
icon: Icon(Icons.logout),
label: Text('Logout'),
),
];
}
}
Related
I am trying to understand how to return to a specific bottomtabindex. As of now I used a hacky way of ading an index to the HomePage as you can see. The issue is I cannot pass the Game object to HomePage too because it feels anti pattern. The Game Object should be passed to the Game Widget/screen
class HomePage extends StatefulWidget {
final int? index;
const HomePage({Key? key, this.index}) : super(key: key);
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
void initState() {
super.initState();
_selectedIndex = widget.index?? 0;
}
int _selectedIndex = 0;
void _navigateBottomBar(int index) {
setState(() {
_selectedIndex = index;
});
}
List<Widget> screens = [
GameHistory(),
Game(),
Statistics(),
Help()
];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Row(
children: <Widget>[
Image.asset("assets/images/logo.png", width: 50, height:50),
const Text("App")
],
),
backgroundColor: Colors.deepPurple,
elevation: 10.0,
actions: [
IconButton(
icon: const Icon(Icons.add_circle_outline),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const CreateGame()),
);
},
)
],
),
body: screens[_selectedIndex],
bottomNavigationBar: Container(
color: Colors.black,
padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 20),
child: GNav(
selectedIndex: _selectedIndex,
onTabChange: _navigateBottomBar,
backgroundColor: Colors.black,
color: Colors.white,
activeColor: Colors.white,
tabBackgroundColor: Colors.deepPurple,
gap: 8,
padding: const EdgeInsets.all(16),
tabs: const [
GButton(icon: Icons.home, text: 'Home'),
GButton(icon: Icons.play_arrow_outlined, text: 'Current Game',),
GButton(icon: Icons.leaderboard_outlined, text: 'Statistics'),
GButton(icon: Icons.help_outline_rounded, text: 'Rules'),
],),
),
);
}
}
//create game widget
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.deepPurple,
elevation: 10.0,
title: const Text('Create Game'),
),
body: Column(
children: [
const Padding(
padding: EdgeInsets.all(12.0),
child: Text("Team names"),
),
Padding(
padding: const EdgeInsets.all(12.0),
child: Row(children: [
Expanded(
child: TextField(
controller: player2,
decoration: const InputDecoration(hintText: "Playername"),
),
)
])
),
const Center(
child: Text("Versus",
style: TextStyle(fontWeight: FontWeight.bold),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(children: [
Expanded(
child: TextField(
controller: player4,
decoration: const InputDecoration(hintText: "Player name"),
),
)
])
),
const Text("Game Type"),
DropdownButton<String>(
value: gameType,
icon: const Icon(Icons.arrow_downward),
elevation: 16,
style: const TextStyle(color: Colors.deepPurple),
underline: Container(
height: 2,
color: Colors.deepPurpleAccent,
),
onChanged: (String? newValue) {
setState(() {
gameType = newValue!;
});
},
items: items
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
),
Center(
child: ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.black),
),
onPressed: () {
// Navigate to game screen and pass information
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => const HomePage(index: 1,)),
(route) =>false,
);
},
child: const Text('Start Game!'),
),
),
],
),
);
}
}
I tried to create a task app using flutter, So I created a text field in DialogBox and my aim is when I add some text into the text field and when I clicked the OK button, I need to show that text in the list. but I have no idea how to call a method in another class, I've added my two classes.
ListTask Class
import 'package:flutter/material.dart';
class ListTask extends StatefulWidget {
const ListTask({Key? key}) : super(key: key);
#override
State<ListTask> createState() => _ListTaskState();
}
class _ListTaskState extends State<ListTask> {
final List<String> tasks = ['masu', 'adasf', 'wfqf', 'santha'];
final TextEditingController _textFieldController = TextEditingController();
void addItemToList() {
setState(() {
tasks.insert(0, _textFieldController.text);
});
}
#override
Widget build(BuildContext context) {
return Container(
height: 320,
width: double.maxFinite,
child: ListView.builder(
padding: EdgeInsets.only(bottom: 10),
itemCount: tasks.length,
itemBuilder: (context, index) {
return Card(
elevation: 1,
color: Colors.grey[200],
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ExpansionTile(title: Text(tasks[index]), children: <Widget>[
ListTile(
title: Text(tasks[index]),
)
]),
],
),
);
},
),
);
}
Future<void> _displayTextInputDialog(BuildContext context) async {
return showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text('TextField in Dialog'),
content: TextField(
onChanged: (value) {
setState(() {
// valueText = value;
});
},
controller: _textFieldController,
decoration: InputDecoration(hintText: "Text Field in Dialog"),
),
actions: <Widget>[
FlatButton(
color: Colors.red,
textColor: Colors.white,
child: Text('CANCEL'),
onPressed: () {
setState(() {
Navigator.pop(context);
});
},
),
FlatButton(
color: Colors.green,
textColor: Colors.white,
child: Text('OK'),
onPressed: () {
setState(() {
addItemToList();
Navigator.pop(context);
});
},
),
],
);
});
}
}
TaskApp Class
import 'package:flutter/material.dart';
import 'package:task_app/Widgets/listtasks.dart';
import 'package:task_app/Widgets/logo.dart';
import 'package:task_app/Widgets/searchbar.dart';
class TaskApp extends StatefulWidget {
const TaskApp({Key? key}) : super(key: key);
#override
State<TaskApp> createState() => _TaskAppState();
}
class _TaskAppState extends State<TaskApp> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(15.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 10),
Logo(),
SizedBox(height: 0),
SearchBar(),
SizedBox(height: 15),
Column(
children: [
Text(
'All tasks',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 15.0),
)
],
),
SizedBox(height: 15),
ListTask(),
],
),
),
floatingActionButton: FloatingActionButton.extended(
onPressed: () {
_displayTextInputDialog(context);
},
label: const Text('Add Task'),
icon: const Icon(Icons.add),
backgroundColor: Colors.blue[900],
),
);
}
}
Calling point of that method in TaskApp Class:
Method:
You can give this a try, it will call a method defined in ListTask(StatefulWidget) from TaskApp(StatefulWidget) widget.
TaskApp.dart
import 'package:flutter/material.dart';
import 'package:vcare/Screens/tetxing1.dart';
class TaskApp extends StatefulWidget {
final ListTask listTask;
const TaskApp({Key? key,required this.listTask}) : super(key: key);
#override
State<TaskApp> createState() => _TaskAppState();
}
class _TaskAppState extends State<TaskApp> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(15.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 10),
// Logo(),
SizedBox(height: 0),
//SearchBar(),
SizedBox(height: 15),
Column(
children: [
Text(
'All tasks',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 15.0),
)
],
),
SizedBox(height: 15),
ListTask(),
],
),
),
floatingActionButton: FloatingActionButton.extended(
onPressed: () {
ListTask().method1(context);
},
label: const Text('Add Task'),
icon: const Icon(Icons.add),
backgroundColor: Colors.blue[900],
),
);
}
}
ListTask.dart
import 'package:flutter/material.dart';
class ListTask extends StatefulWidget {
method1(context) => createState().displayTextInputDialog(context);
#override
_ListTaskState createState() => _ListTaskState();
}
class _ListTaskState extends State<ListTask> {
final List<String> tasks = ['masu', 'adasf', 'wfqf', 'santha'];
final TextEditingController _textFieldController = TextEditingController();
void addItemToList() {
setState(() {
tasks.insert(0, _textFieldController.text);
});
}
#override
Widget build(BuildContext context) {
return Container(
height: 320,
width: double.maxFinite,
child: ListView.builder(
padding: EdgeInsets.only(bottom: 10),
itemCount: tasks.length,
itemBuilder: (context, index) {
return Card(
elevation: 1,
color: Colors.grey[200],
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ExpansionTile(title: Text(tasks[index]), children: <Widget>[
ListTile(
title: Text(tasks[index]),
)
]),
],
),
);
},
),
);
}
Future<void> displayTextInputDialog(BuildContext context) async {
return showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text('TextField in Dialog'),
content: TextField(
onChanged: (value) {
setState(() {
// valueText = value;
});
},
controller: _textFieldController,
decoration: InputDecoration(hintText: "Text Field in Dialog"),
),
actions: <Widget>[
FlatButton(
color: Colors.red,
textColor: Colors.white,
child: Text('CANCEL'),
onPressed: () {
setState(() {
Navigator.pop(context);
});
},
),
FlatButton(
color: Colors.green,
textColor: Colors.white,
child: Text('OK'),
onPressed: () {
setState(() {
addItemToList();
Navigator.pop(context);
});
},
),
],
);
});
}
}
if you find this solution helpful please mark as accepted answer
import 'dart:html';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
bool switcht1 = false;
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Flutter - tutorialkart.com'),
),
body: Column(
children: [
Container(
width: double.infinity,
height: 50,
color: Colors.amber,
child: Text("Water"),
padding: EdgeInsets.only(top: 15),
),
Switch(
value: switcht1,
onChanged: (value) {
setState(() {
switcht1 = value;
print(switcht1);
});
},
activeTrackColor: Colors.lightGreenAccent,
activeColor: Colors.green,
),
],
),
),
);
}
}
I'm new to flutter.
I'm not quite familiar with the column and row concepts yet, but I'm working on it.
When I want to put the switch in a column, it stays out.
How can I move the switch like in the picture?
in the case you have to use a Row widget like this :
Column(
children: [
Container(
height: 50,
color: Colors.amber,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text("Water"),
Switch(
value: switcht1 ,
onChanged: (bool value) {
setState(() {
switcht1 = value;
print(switcht1);
});
},
activeTrackColor: Colors.lightGreenAccent,
activeColor: Colors.green,
),
]
),
padding: EdgeInsets.only(top: 15),
),
],
),
The result :
or use a ListTile :
Column(
children: [
Container(
height: 50,
color: Colors.amber,
child: ListTile(
leading: Text("Water"),
trailing : Switch(
value: switcht1 ,
onChanged: (bool value) {
setState(() {
switcht1 = value;
print(switcht1);
});
},
activeTrackColor: Colors.lightGreenAccent,
activeColor: Colors.green,
),
),
padding: EdgeInsets.only(top: 15),
),
],
),
The result
As you know the Column() widget is used to arrange multiple widgets vertically and the Row() widget horizontally.
To achieve the layout you would need to wrap your widgets with Row() and to create space between the two widgets you will need the mainAxisAlignment property.
Here's the Example:
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text("Water"),
Switch(),
],
),
I am having a hard time trying to make the pick from gallery button work, I tried so many tutorials and videos, and IDK what I am doing wrong, please help me solve this.
I just started with flutter and this was the one thing that I couldn't solve.
The image of the interface
final formKey = GlobalKey<FormState>(); //key for form
#override
Widget build(BuildContext context) {
final double height= MediaQuery.of(context).size.height;
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
return Scaffold(
appBar: AppBar(
elevation:0,
brightness: Brightness.light,
backgroundColor:Colors.white,
leading: Icon(Icons.arrow_back_outlined,size: 20,color: Colors.black),
title:Text('Enregistrer',style: TextStyle(fontSize: 15,color:Colors.blue),textAlign:TextAlign.right),
),
body: SingleChildScrollView(
padding: EdgeInsets.symmetric(horizontal: 20 ),
child: Form(
key: formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children:<Widget> [
Column(
children: [
if(Image ==null ?(Image.asset("images/emilia.jpeg",height: 150,width: 150))):null,
pickImage != null ? FileImage(pickImage): null,
Row(
children:[
OutlineButton.icon(
icon:Icon(Icons.camera_alt_outlined,color:Colors.black),
onPressed: (){pickImage(ImageSource.camera);},
label: Text('Appareil photo',style: TextStyle(fontSize: 10.0)),
),
OutlineButton.icon(
icon:Icon(Icons.photo_album_rounded,color:Colors.black),
onPressed: (){pickImage(ImageSource.gallery);},
label: Text('ouvrir la Gallerie',style: TextStyle(fontSize: 10.0)),
)
]
),
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children:<Widget> [
Text('nom',
textAlign:TextAlign.left),
SizedBox(width:2.0),
TextFormField(
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'nom',
hintText: 'Entrer votre nom',
),
validator:(value) {
if (value!.isEmpty || !RegExp(r'^[a-z A-Z]+$').hasMatch(value!));
return "entrer votre nom";
}
),
Here you can see a simple example:
class Home extends StatefulWidget {
const Home({Key? key}) : super(key: key);
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
XFile? file;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
file != null
? Center(
child: Image.file(
File(file!.path),
width: 159,
height: 159,
),
)
: const Text('placeholder'),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
onPressed: () async {
file = await ImagePicker().pickImage(
source: ImageSource.camera,
);
setState(() {});
},
icon: const Icon(Icons.camera_alt_outlined),
),
IconButton(
onPressed: () async {
file = await ImagePicker().pickImage(
source: ImageSource.gallery,
);
setState(() {});
},
icon: const Icon(Icons.photo_album),
),
],
)
],
),
),
);
}
}
Result: Make sure to grant camera and storage access
I wanted to send Data/images from one page to another. In the Homepage when I tap on the add Icon button image should be passed to the Cart page and if the icon is tapped again image is removed from the Cart page. But, the cart page should be accessed from bottom navigation bar.
but it is showing an error called 1 positional argument(s) expected, but 0 found.
Try adding the missing arguments.. when it calls the cart page.
HomePage.dart file
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blueGrey,
),
home: NavBar(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<Dish> _dishes = List<Dish>();
List<Dish> _cartList = List<Dish>();
#override
void initState() {
super.initState();
_populateDishes();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
actions: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 16.0, top: 8.0),
child: GestureDetector(
child: Stack(
alignment: Alignment.topCenter,
children: <Widget>[
Icon(
Icons.shopping_cart,
size: 36.0,
),
if (_cartList.length > 0)
Padding(
padding: const EdgeInsets.only(left: 2.0),
child: CircleAvatar(
radius: 8.0,
backgroundColor: Colors.red,
foregroundColor: Colors.white,
child: Text(
_cartList.length.toString(),
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 12.0,
),
),
),
),
],
),
onTap: () {
if (_cartList.isNotEmpty)
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => Cart(_cartList),
),
);
},
),
)
],
),
body: _buildGridView(),
);
}
ListView _buildListView() {
return ListView.builder(
itemCount: _dishes.length,
itemBuilder: (context, index) {
var item = _dishes[index];
return Padding(
padding: const EdgeInsets.symmetric(
horizontal: 8.0,
vertical: 2.0,
),
child: Card(
elevation: 4.0,
child: ListTile(
leading: Icon(
item.icon,
color: item.color,
),
title: Text(item.name),
trailing: GestureDetector(
child: (!_cartList.contains(item))
? Icon(
Icons.add_circle,
color: Colors.green,
)
: Icon(
Icons.remove_circle,
color: Colors.red,
),
onTap: () {
setState(() {
if (!_cartList.contains(item))
_cartList.add(item);
else
_cartList.remove(item);
});
},
),
),
),
);
},
);
}
GridView _buildGridView() {
return GridView.builder(
padding: const EdgeInsets.all(4.0),
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
itemCount: _dishes.length,
itemBuilder: (context, index) {
var item = _dishes[index];
return Card(
elevation: 4.0,
child: Stack(
fit: StackFit.loose,
alignment: Alignment.center,
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
item.icon,
color: (_cartList.contains(item))
? Colors.grey
: item.color,
size: 100.0,
),
Text(
item.name,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.subhead,
)
],
),
Padding(
padding: const EdgeInsets.only(
right: 8.0,
bottom: 8.0,
),
child: Align(
alignment: Alignment.bottomRight,
child: GestureDetector(
child: (!_cartList.contains(item))
? Icon(
Icons.add_circle,
color: Colors.green,
)
: Icon(
Icons.remove_circle,
color: Colors.red,
),
onTap: () {
setState(() {
if (!_cartList.contains(item))
_cartList.add(item);
else
_cartList.remove(item);
});
},
),
),
),
],
));
});
}
void _populateDishes() {
var list = <Dish>[
Dish(
name: 'Chicken Zinger',
icon: Icons.fastfood,
color: Colors.amber,
),
Dish(
name: 'Chicken Zinger without chicken',
icon: Icons.print,
color: Colors.deepOrange,
),
Dish(
name: 'Rice',
icon: Icons.child_care,
color: Colors.brown,
),
Dish(
name: 'Beef burger without beef',
icon: Icons.whatshot,
color: Colors.green,
),
Dish(
name: 'Laptop without OS',
icon: Icons.laptop,
color: Colors.purple,
),
Dish(
name: 'Mac wihout macOS',
icon: Icons.laptop_mac,
color: Colors.blueGrey,
),
];
setState(() {
_dishes = list;
});
}
}
Cart.dart file
import 'package:flutter/material.dart';
import 'dish_object.dart';
class Cart extends StatefulWidget {
final List<Dish> _cart;
Cart(this._cart);
#override
_CartState createState() => _CartState(this._cart);
}
class _CartState extends State<Cart> {
_CartState(this._cart);
List<Dish> _cart;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Cart'),
),
body: ListView.builder(
itemCount: _cart.length,
itemBuilder: (context, index) {
var item = _cart[index];
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 2.0),
child: Card(
elevation: 4.0,
child: ListTile(
leading: Icon(
item.icon,
color: item.color,
),
title: Text(item.name),
trailing: GestureDetector(
child: Icon(
Icons.remove_circle,
color: Colors.red,
),
onTap: () {
setState(() {
_cart.remove(item);
});
},
),
),
),
);
},
),
);
}
}
NavBar.dart file
import 'package:flutter/material.dart';
import 'package:sharewallpaper/cart.dart';
import 'package:sharewallpaper/main.dart';
class NavBar extends StatefulWidget {
#override
_NavBarState createState() => _NavBarState();
}
class _NavBarState extends State<NavBar> {
int _currentIndex = 0;
final List<Widget> _children = [
MyHomePage(),
Cart(), ** This line is throwing an error **
];
void onTappedBar(int index) {
setState(() {
_currentIndex = index;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: _children[_currentIndex],
bottomNavigationBar: BottomNavigationBar(
onTap: onTappedBar,
currentIndex: _currentIndex,
items: [
BottomNavigationBarItem(icon: Icon(Icons.home), title: Text('Home')),
BottomNavigationBarItem(
icon: Icon(Icons.bookmark), title: Text('BookMark')),
],
),
);
}
}
Yep, it will throw an error because the constructor of the Cart class is expecting one parameter to be passed in. You could use a named constructor instead like this:
class Cart extends StatefulWidget {
final List<Dish> _cart;
Cart(this._cart);
That way, you can call it like so:
Cart(cart: _cartList),
But if you actually need the cart list, I would recommend that you write a provider to keep track of the cart data across screens.