I need to rebuild my listview because it is only maintaining the first build, unless I reset the app. I have a bottom sheet pop up that lets me select times and navigate me to a new page where the listview.builder builds. If I back out of the page, select new options, and go back into the page, it does not update. Here is an example:
Relevant Code:
final selectTimesTextStyle = TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
);
final List classBools = [
checkedPreBallet,
checkedBeginningBallet,
checkedIntermediateBallet,
checkedAdvancedBallet,
checkedJazz,
checkedPC,
];
final List<String> preballetItems = [
'Wednesday 3:00-4:00',
'Friday 3:00-3:35',
];
final List<String> privateClassesItems = [
'Mondays, Schedule Via Email',
];
final List<String> intermediateBalletItems = [
'Tuesday 5:00-6:00',
'Thursday 5:00-6:00',
'Saturday 10:00-11:00',
];
final List<String> advancedBalletItems = [
'Tuesday 6:00-7:00',
'Thursday 6:00-7:00',
];
final List<String> beginningBalletItems = [
'Wednesday 3:45-4:45',
'Friday 3:45-4:45',
];
final List<String> jazzItems = [
'Thursday 4:00-5:00',
];
final List<List> listOfLists = [
preballetItems,
beginningBalletItems,
intermediateBalletItems,
advancedBalletItems,
jazzItems,
privateClassesItems,
];
List<String> valueChoose = [
'Wednesday 3:00-4:00',
'Wednesday 3:45-4:45',
'Tuesday 5:00-6:00',
'Tuesday 6:00-7:00',
'Thursday 4:00-5:00',
'Mondays, Schedule Via Email',
];
class TimeSelection extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: InkWell(
onTap: () => {
Navigator.of(context).pop(),
currentIndex = 2,
checkedPreBallet = false,
checkedBeginningBallet = false,
checkedIntermediateBallet = false,
checkedAdvancedBallet = false,
checkedJazz = false,
checkedPC = false,
},
child: Container(
child: Icon(Icons.arrow_back),
),
),
title: Text('Select Times'),
centerTitle: true,
),
body: StatefulBuilder(
builder: (context, setState) => Column(
children: [
Expanded(
child: ListView.builder(
itemCount: 6,
itemBuilder: (context, index) => Visibility(
maintainState: false,
visible: classBools[index],
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Container(
child: Text(
buttonTitles[index],
style: selectTimesTextStyle,
),
width: MediaQuery.of(context).size.width * 0.50,
),
Container(
width: MediaQuery.of(context).size.width * 0.40,
child: DropdownButton(
isExpanded: true,
underline: SizedBox(),
dropdownColor: Colors.white,
value: valueChoose[index],
onChanged: (newValue) => {
setState(() {
valueChoose[index] = newValue;
})
},
items: listOfLists[index]
.map((e) => DropdownMenuItem(
onTap: () => {
classBools[index] = true,
},
child: Text(e),
value: e,
))
.toList(),
),
),
],
),
),
),
),
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 120,
vertical: 15,
),
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
stops: [
0.00005,
1,
],
colors: [
Theme.of(context).secondaryHeaderColor,
Theme.of(context).primaryColor,
]),
boxShadow: [
BoxShadow(color: Colors.black54, offset: Offset(3, 3)),
],
color: Colors.purpleAccent,
borderRadius: BorderRadius.circular(15),
),
child: InkWell(
onTap: () => {},
child: Padding(
padding: EdgeInsets.all(16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text('PayPal'),
],
),
),
),
),
),
],
),
),
);
}
}
bool checkedPreBallet = false;
bool checkedBeginningBallet = false;
bool checkedIntermediateBallet = false;
bool checkedAdvancedBallet = false;
bool checkedJazz = false;
bool checkedPC = false;
final List<String> buttonTitles = [
'Pre-Ballet',
'Beginning Ballet',
'Intermediate Ballet',
'Advanced Ballet',
'Jazz',
'Private Classes',
];
class RegisterPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Divider(),
Text('hello'),
Divider(),
RegisterCards(),
],
),
);
}
}
class RegisterCards extends StatefulWidget {
#override
_RegisterCardsState createState() => _RegisterCardsState();
}
class _RegisterCardsState extends State<RegisterCards> {
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(
horizontal: 30,
),
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
stops: [
0.00005,
1,
],
colors: [
Theme.of(context).secondaryHeaderColor,
Theme.of(context).primaryColor,
]),
boxShadow: [
BoxShadow(color: Colors.black54, offset: Offset(3, 3)),
],
color: Colors.purpleAccent,
borderRadius: BorderRadius.circular(15),
),
child: InkWell(
onTap: () => onButtonPressed(context),
child: Padding(
padding: EdgeInsets.all(16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text('Register Here'),
],
),
),
),
),
);
}
}
class ClassListWidget extends StatefulWidget {
#override
_ClassListWidgetState createState() => _ClassListWidgetState();
}
class _ClassListWidgetState extends State<ClassListWidget> {
#override
Widget build(BuildContext context) {
return StatefulBuilder(
builder: (context, setState) => Column(
children: [
CheckboxListTile(
value: checkedPreBallet,
onChanged: (value) => {
setState(() {
checkedPreBallet = value;
})
},
title: Text('Pre-Ballet'),
checkColor: Theme.of(context).scaffoldBackgroundColor,
activeColor: Theme.of(context).primaryColor,
secondary: Icon(PokemonIcons.i004_charmander),
controlAffinity: ListTileControlAffinity.leading,
tristate: false,
),
CheckboxListTile(
value: checkedBeginningBallet,
onChanged: (value) => {
setState(() {
checkedBeginningBallet = value;
})
},
title: Text('Beginning Ballet'),
checkColor: Theme.of(context).scaffoldBackgroundColor,
activeColor: Theme.of(context).primaryColor,
secondary: Icon(PokemonIcons.i004_charmander),
controlAffinity: ListTileControlAffinity.leading,
tristate: false,
),
CheckboxListTile(
value: checkedIntermediateBallet,
onChanged: (value) => {
setState(() {
checkedIntermediateBallet = value;
})
},
title: Text('Intermediate Ballet'),
checkColor: Theme.of(context).scaffoldBackgroundColor,
activeColor: Theme.of(context).primaryColor,
secondary: Icon(PokemonIcons.i004_charmander),
controlAffinity: ListTileControlAffinity.leading,
tristate: false,
),
CheckboxListTile(
value: checkedAdvancedBallet,
onChanged: (value) => {
setState(() {
checkedAdvancedBallet = value;
})
},
title: Text('Advanced Ballet'),
checkColor: Theme.of(context).scaffoldBackgroundColor,
activeColor: Theme.of(context).primaryColor,
secondary: Icon(PokemonIcons.i004_charmander),
controlAffinity: ListTileControlAffinity.leading,
tristate: false,
),
CheckboxListTile(
value: checkedJazz,
onChanged: (value) => {
setState(() {
checkedJazz = value;
})
},
title: Text('Jazz'),
checkColor: Theme.of(context).scaffoldBackgroundColor,
activeColor: Theme.of(context).primaryColor,
secondary: Icon(PokemonIcons.i004_charmander),
controlAffinity: ListTileControlAffinity.leading,
tristate: false,
),
CheckboxListTile(
value: checkedPC,
onChanged: (value) => {
setState(() {
checkedPC = value;
})
},
title: Text('Private Classes'),
checkColor: Theme.of(context).scaffoldBackgroundColor,
activeColor: Theme.of(context).primaryColor,
secondary: Icon(PokemonIcons.i004_charmander),
controlAffinity: ListTileControlAffinity.leading,
tristate: false,
),
],
),
);
}
}
void onButtonPressed(context) {
showModalBottomSheet(
isScrollControlled: false,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(15),
topRight: Radius.circular(15),
),
),
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
context: context,
builder: (context) => StatefulBuilder(
builder: (BuildContext context, setState) => Container(
child: Column(
children: [
ClassListWidget(),
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 15,
),
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
stops: [
0.00005,
1,
],
colors: [
Theme.of(context).secondaryHeaderColor,
Theme.of(context).primaryColor,
]),
boxShadow: [
BoxShadow(color: Colors.black54, offset: Offset(3, 3)),
],
color: Colors.purpleAccent,
borderRadius: BorderRadius.circular(15),
),
child: InkWell(
onTap: () => {
Navigator.push(context, MaterialPageRoute(
builder: (context) => TimeSelection(),
)),
},
child: Padding(
padding: EdgeInsets.all(14),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text('Select Times'),
],
),
),
),
),
),
],
),
),
),
);
}
check this out whether it fits your need.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
),
home: TimeSelection(),
);
}
}
// model class for your ballet
class Ballet {
final String balletName;
final List<String> timeSchedules;
final String description;
String selectedTime;
bool isSelected = false;
Ballet({
this.balletName,
this.timeSchedules,
isSelected,
this.description = '',
this.selectedTime
}) {selectedTime ??= this.timeSchedules[0];}
}
List<Ballet> balletItems = <Ballet>[
Ballet(
balletName: "Pre-Ballet",
timeSchedules: [
'Wednesday 3:00-4:00',
'Friday 3:00-3:35',
],
),
Ballet(
balletName: "Private Classes",
timeSchedules: [
'Mondays',
],
description: 'Scheduled Via Email'
),
Ballet(
balletName: "Intermediate Ballet",
timeSchedules: [
'Tuesday 5:00-6:00',
'Thursday 5:00-6:00',
'Saturday 10:00-11:00',
],
),
Ballet(
balletName: "Advance Ballet",
timeSchedules: [
'Tuesday 6:00-7:00',
'Thursday 6:00-7:00',
],
),
Ballet(
balletName: "Beginning Ballet",
timeSchedules: [
'Wednesday 3:45-4:45',
'Friday 3:45-4:45',
],
),
Ballet(
balletName: "Jazz Ballet",
timeSchedules: [
'Thursday 4:00-5:00',
],
)
];
class TimeSelection extends StatefulWidget {
#override
_TimeSelectionState createState() => _TimeSelectionState();
}
class _TimeSelectionState extends State<TimeSelection> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Center(
child: Column(
children: [
Text('hello there', style: Theme.of(context).textTheme.headline4),
ElevatedButton(child: Text('Register Here',), onPressed: () {},),
],
),
),
Expanded(
child: ListView.builder(
itemCount: balletItems.length+1 ,
itemBuilder: (context, index){
if (index < balletItems.length) {
Ballet balletItem = balletItems[index];
return ListTile(leading: Checkbox(
value: balletItem.isSelected,
onChanged: (value) {
setState((){
balletItem.isSelected = value;
});
},),
title: Text(balletItem.balletName),
trailing: Icon(Icons.auto_awesome),
);}
else{
return Container(
margin: const EdgeInsets.symmetric(horizontal: 20.0),
child: ElevatedButton(
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(builder: (context) => SelectTimes(),));
},
child: Text('Select Times'),
),
);}
},
),
)
],
),
drawer: Drawer(),
appBar: AppBar(title: Text("Class Registration"),),
);
}
}
class SelectTimes extends StatefulWidget {
#override
_SelectTimesState createState() => _SelectTimesState();
}
class _SelectTimesState extends State<SelectTimes> {
List<Ballet> selectedBalletItems;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Select Times'),),
body: Padding(
padding: const EdgeInsets.all(10.0),
child: Column(
children: [
Expanded(
child: ListView.builder(
itemCount: selectedBalletItems.length,
itemBuilder: (context, index) {
Ballet selectedBalletItem = selectedBalletItems[index];
return _listTile(selectedBalletItem);
},
),
),
ElevatedButton(child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text("PayPal", style: Theme.of(context).textTheme.headline4,
),
),
onPressed: () {},)
],
),
)
);
}
Widget _listTile(Ballet selectedBalletItem) {
return ListTile(
title: Text(selectedBalletItem.balletName),
subtitle: Text(selectedBalletItem.description , style: Theme.of(context).textTheme.bodyText2.copyWith(color: Colors.grey[500])),
trailing: DropdownButton<String>(
value: selectedBalletItem.selectedTime,
items: selectedBalletItem.timeSchedules.map((timeSchedule) {
return DropdownMenuItem(value: timeSchedule, child: Text(timeSchedule));
} ).toList(),
onChanged: (value) {
setState(() {
selectedBalletItem.selectedTime = value;
});
},
)
);
}
#override
void initState() {
super.initState();
selectedBalletItems = balletItems.where((e) => e.isSelected).toList();
}
}
Related
iam new to flutter and i would like to add a text under a button, but i cant seems to do it, so far here's my result
..
i use two Rows for the button and the text,
as you guys can see the text isnt align really well, i tried using ElevatedButton but the text is beside the button not below it.
this is my code so far:
import 'package:flutter/material.dart';
import 'package:get/get_navigation/get_navigation.dart';
import 'package:medreminder/NewsArticle/news_home.dart';
import 'Reminder/ui/home_reminder.dart';
import 'Reminder/ui/widgets/button.dart';
import 'package:medreminder/main_reminder.dart';
import 'package:medreminder/home_page.dart';
void main() {
// debugPaintSizeEnabled = true;
runApp(const HomePage());
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: const Text('Medicine Reminder App'),
),
body: Column(
children: [
Stack(
children: [
Image.asset(
'images/MenuImg.jpg',
width: 600,
height: 170,
fit: BoxFit.cover,
),
],
),
const SizedBox(height: 10.0),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
IconButton(
icon: Image.asset('images/reminder.png'),
iconSize: 50,
onPressed: () {
Navigator.of(context, rootNavigator: true).push(
MaterialPageRoute(builder: (context) => const ReminderHomePage()),
);
},
),
IconButton(
icon: Image.asset('images/news.png'),
iconSize: 50,
onPressed: () {},
),
IconButton(
icon: Image.asset('images/recipe.png'),
iconSize: 50,
onPressed: () {},
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Text("Reminder"),
Text("News"),
Text("Recipe")
],
)
],
),
),
);
}
}
if anyone know how to do it, please help. it will mean so much to me. thank you
try to put each iconButton inside a Column with its Text widget, try this code:
import 'package:flutter/material.dart';
import 'package:get/get_navigation/get_navigation.dart';
import 'package:medreminder/NewsArticle/news_home.dart';
import 'Reminder/ui/home_reminder.dart';
import 'Reminder/ui/widgets/button.dart';
import 'package:medreminder/main_reminder.dart';
import 'package:medreminder/home_page.dart';
void main() {
// debugPaintSizeEnabled = true;
runApp(const HomePage());
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: const Text('Medicine Reminder App'),
),
body: Column(
children: [
Stack(
children: [
Image.asset(
'images/MenuImg.jpg',
width: 600,
height: 170,
fit: BoxFit.cover,
),
],
),
const SizedBox(height: 10.0),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Column(
children: [
IconButton(
icon: Image.asset('images/reminder.png'),
iconSize: 50,
onPressed: () {
Navigator.of(context, rootNavigator: true).push(
MaterialPageRoute(builder: (context) => const ReminderHomePage()),
);
},
),
Text("Reminder")
],
),
Column(
children: [
IconButton(
icon: Image.asset('images/news.png'),
iconSize: 50,
onPressed: () {},
),
Text("News")
],
),
Column(
children: [
IconButton(
icon: Image.asset('images/recipe.png'),
iconSize: 50,
onPressed: () {},
),
Text("Recipe")
],
),
],
),
// Row(
// mainAxisAlignment: MainAxisAlignment.,
// children: [, , ],
// )
],
),
),
);
}
}
You can adjust Layout by using Row and Column
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Column(
children: [
const SizedBox(height: 10.0),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_showButton('assets/images/image1.jpg', 'Reminder'),
_showButton('assets/images/image2.jpg', 'News'),
_showButton('assets/images/image2.jpg', 'Recipe'),
],
),
],
),
),
);
}
_showButton(String imagePath, String text) {
return Column(
children: [
IconButton(
icon: Image.asset(imagePath),
iconSize: 50,
onPressed: () {
// Navigator.of(context, rootNavigator: true).push(
// MaterialPageRoute(builder: (context) => const ReminderHomePage()),
// );
},
),
Text(
text,
textAlign: TextAlign.center,
)
],
);
}
if u want to change the colour of the text button u can, its just commented out for you
import 'package:flutter/material.dart';
void main() {
// debugPaintSizeEnabled = true;
runApp(const HomePage());
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: const Text('Medicine Reminder App'),
),
body: Column(
children: [
Stack(
children: [
Image.asset(
'images/MenuImg.jpg',
width: 600,
height: 170,
fit: BoxFit.cover,
),
],
),
const SizedBox(height: 10.0),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Column(
children: [
IconButton(
icon: Image.asset('images/reminder.png'),
iconSize: 50,
onPressed: () {
// Navigator.of(context, rootNavigator: true).push(
// MaterialPageRoute(
// builder: (context) => const ReminderHomePage()),
// );
},
),
TextButton(
onPressed: () => print('reminder'),
child: Text(
'Reminder',
//style: TextStyle(color: Colors.black),
))
],
),
Column(
children: [
IconButton(
icon: Image.asset('images/news.png'),
iconSize: 50,
onPressed: () {},
),
TextButton(
onPressed: () => print('News'),
child: Text(
'News',
// style: TextStyle(color: Colors.black),
))
],
),
Column(
children: [
IconButton(
icon: Image.asset('images/recipe.png'),
iconSize: 50,
onPressed: () {},
),
TextButton(
onPressed: () => print('Recipe'),
child: Text(
'Recipe',
style: TextStyle(color: Colors.black),
))
],
),
],
),
// Row(
// mainAxisAlignment: MainAxisAlignment.spaceAround,
// children: [Text("Reminder"), Text("News"), Text("Recipe")],
// )
],
),
),
);
}
}
Try below code hope its helpful to you, I have try it two ways Using Column Widget and Gridview.builder(). Just replace my images with your image
1. Using Column Widget
Padding(
padding: const EdgeInsets.all(10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: const [
ImageRow(
imageUrl:
'https://cdn.iconscout.com/icon/free/png-256/reminder-1605670-1361019.png',
imageName: 'Reminder',
),
ImageRow(
imageUrl: 'https://cdn-icons-png.flaticon.com/512/21/21601.png',
imageName: 'News',
),
ImageRow(
imageUrl:
'https://cdn-icons-png.flaticon.com/512/1041/1041373.png',
imageName: 'Recipe',
),
],
),
),
ImageRow Class:
class ImageRow extends StatelessWidget {
const ImageRow({
Key? key,
required this.imageName,
required this.imageUrl,
}) : super(key: key);
final String imageUrl;
final String imageName;
#override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Image.network(
imageUrl,
height: 50,
),
const SizedBox(
height: 5,
),
Text(imageName),
],
);
}
}
2. Using Gridview.builder()
Declare List on your imageName and imageUrl
List medicineInfo = [
{
'imageUrl':
'https://cdn.iconscout.com/icon/free/png-256/reminder-1605670-1361019.png',
'imageName': 'Reminder',
},
{
'imageUrl': 'https://cdn-icons-png.flaticon.com/512/21/21601.png',
'imageName': 'News',
},
{
'imageUrl': 'https://cdn-icons-png.flaticon.com/512/1041/1041373.png',
'imageName': 'Recipe',
},
];
GridView Widget:
Padding(
padding: const EdgeInsets.all(20),
child: GridView.builder(
shrinkWrap: true,
itemCount: medicineInfo.length,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 20,
),
itemBuilder: (context, index) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Image.network(
medicineInfo[index]['imageUrl'],
height: 50,
),
const SizedBox(
height: 5,
),
Text(
medicineInfo[index]['imageName'],
),
],
);
},
),
),
Result Screen->
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!'),
),
),
],
),
);
}
}
how can I make tabs behind actions in appBar ?like this ! photo
, my code look like this and I've tried to put tabs on leading
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
actions: [
IconButton(onPressed: () {}, icon: Icon(Icons.home)),
IconButton(onPressed: () {}, icon: Icon(Icons.search)),
IconButton(onPressed: () {}, icon: Icon(Icons.archive)),
],
leadingWidth: double.maxFinite,
leading: TabBar(
indicatorSize: TabBarIndicatorSize.tab,
tabs: [
Tab(text: "Pending"),
Tab(text: "Delivered"),
],
),
),
body: TabBarView(
children: [
Tab(text: "Pending"),
Tab(text: "Delivered"),
],
),
),
);
}
}
and here how it's the output look like =>
what if you put the tab in title instead of leading:
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
actions: [
IconButton(onPressed: () {}, icon: Icon(Icons.home)),
IconButton(onPressed: () {}, icon: Icon(Icons.search)),
IconButton(onPressed: () {}, icon: Icon(Icons.archive)),
],
title: TabBar(
indicatorSize: TabBarIndicatorSize.tab,
tabs: [
Tab(text: "Pending"),
Tab(text: "Delivered"),
],
),
),
body: TabBarView(
children: [
Tab(text: "Pending"),
Tab(text: "Delivered"),
],
),
),
);
}
}
You can add the carousel_slider dependency. To get it you can visit pub.dev and search for carousel_slider or here's a link https://pub.dev/packages/carousel_slider. I hope this helps )
//example image
final List<String> imgList = [
'https://images.unsplash.com/photo-1520342868574-5fa3804e551c?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=6ff92caffcdd63681a35134a6770ed3b&auto=format&fit=crop&w=1951&q=80',
'https://images.unsplash.com/photo-1522205408450-add114ad53fe?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=368f45b0888aeb0b7b08e3a1084d3ede&auto=format&fit=crop&w=1950&q=80',
'https://images.unsplash.com/photo-1519125323398-675f0ddb6308?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=94a1e718d89ca60a6337a6008341ca50&auto=format&fit=crop&w=1950&q=80',
'https://images.unsplash.com/photo-1523205771623-e0faa4d2813d?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=89719a0d55dd05e2deae4120227e6efc&auto=format&fit=crop&w=1953&q=80',
'https://images.unsplash.com/photo-1508704019882-f9cf40e475b4?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=8c6e5e3aba713b17aa1fe71ab4f0ae5b&auto=format&fit=crop&w=1352&q=80',
'https://images.unsplash.com/photo-1519985176271-adb1088fa94c?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=a0c8d632e977f94e5d312d9893258f59&auto=format&fit=crop&w=1355&q=80'
];
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHome(),
);
}
}
class MyHome extends StatefulWidget {
const MyHome({Key? key}) : super(key: key);
#override
State<MyHome> createState() => _MyHomeState();
}
class _MyHomeState extends State<MyHome> {
final List<Widget> imageSliders = imgList
.map((item) => Container(
child: Container(
margin: EdgeInsets.all(5.0),
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(5.0)),
child: Stack(
children: <Widget>[
Image.network(item, fit: BoxFit.cover, width: 1000.0),
Positioned(
bottom: 0.0,
left: 0.0,
right: 0.0,
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Color.fromARGB(200, 0, 0, 0),
Color.fromARGB(0, 0, 0, 0)
],
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
),
),
padding: EdgeInsets.symmetric(
vertical: 10.0, horizontal: 20.0),
// child: Text(
// 'No. ${imgList.indexOf(item)} image',
// style: TextStyle(
// color: Colors.white,
// fontSize: 20.0,
// fontWeight: FontWeight.bold,
// ),
// ),
),
),
],
)),
),
))
.toList();
#override
Widget build(BuildContext context) {
int _current = 0;
final CarouselController _controller = CarouselController();
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
actions: [
IconButton(onPressed: () {}, icon: Icon(Icons.home)),
IconButton(onPressed: () {}, icon: Icon(Icons.search)),
IconButton(onPressed: () {}, icon: Icon(Icons.archive)),
],
leadingWidth: double.maxFinite,
leading: TabBar(
indicatorSize: TabBarIndicatorSize.tab,
tabs: [
Tab(text: "Pending"),
Tab(text: "Delivered"),
],
),
),
body:Container(
child: Column(
mainAxisAlignment:MainAxisAlignment.start,
children: [
CarouselSlider(
items: imageSliders,
carouselController: _controller,
options: CarouselOptions(
height: 200,
scrollDirection: Axis.horizontal,
autoPlay: true,
enlargeCenterPage: true,
aspectRatio: 2.0,
viewportFraction: 1,
onPageChanged: (index, reason) {
setState(() {
_current = index;
});
}),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: imgList.asMap().entries.map((entry) {
return GestureDetector(
onTap: () => _controller.animateToPage(entry.key),
child: Container(
width: 12.0,
height: 12.0,
margin: EdgeInsets.symmetric(vertical: 1.0, horizontal: 4.0),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: (Theme.of(context).brightness == Brightness.dark
? Colors.white
: Colors.black)
.withOpacity(_current == entry.key ? 0.9 : 0.4)),
),
);
}).toList(),
),
]),
),
),
);
}
}
I am completely new to Flutter and I have this screen that uses bottomSheet and I want to go to a new screen when I click on a project, while staying inside this parent screen that has the bottomSheet in it. Here is the source code for the parent screen and the Projects screen inside it.
Parent Main Menu screen
import 'package:flutter/material.dart';
import 'projects.dart';
import 'app-bar.dart';
class MainMenu extends StatefulWidget {
#override
_MainMenuState createState() => _MainMenuState();
}
class _MainMenuState extends State<MainMenu> {
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
int _selectedIndex = 0;
static List<TabItem> _widgetOptions = <TabItem>[
TabItem(
text: new Text('Projects'),
className: Projects(),
),
TabItem(
text: new Text('Organization'),
className: null,
),
TabItem(
text: new Text('Profile'),
className: null,
),
];
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: SafeArea(
child: new DefaultTabController(
length: 3,
child: new Scaffold(
key: _scaffoldKey,
appBar: appBar(_widgetOptions.elementAt(_selectedIndex).text),
body: _widgetOptions.elementAt(_selectedIndex).className,
bottomNavigationBar: BottomNavigationBar(
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.view_column),
label: 'Projects'
),
BottomNavigationBarItem(
icon: Icon(Icons.people),
label: 'Organization'
),
BottomNavigationBarItem(
icon: Icon(Icons.person),
label: 'Profile'
)
],
currentIndex: _selectedIndex,
onTap: _onItemTapped,
),
),
)
),
);
}
}
class TabItem {
Widget text;
dynamic className;
TabItem({ #required this.text, #required this.className });
}
Projects
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:pmtool/project-page.dart';
import './interfaces/iprojects.dart';
import './constants/route-names.dart';
class Projects extends StatefulWidget {
#override
_ProjectsState createState() => _ProjectsState();
}
class _ProjectsState extends State<Projects> {
final GlobalKey<ScaffoldState> _scaffoldState = new GlobalKey<ScaffoldState>();
static const List<Text> sortOptions = [
Text('Project Name'),
Text('Project Number'),
Text('Client Name'),
Text('Percent Completed'),
Text('Date Added'),
Text('Project Type'),
];
static const List<String> sortOrder = [
'Descending',
'Ascending',
];
static const List<String> filters = [
'Ongoing',
'All',
'Completed',
];
List<bool> isSelected = [
true, false, false, false, false, false,
];
String selectedSort = 'Descending';
static List<ProjectsMock> projects = [
ProjectsMock(projectId: '1', projectNumber: '1', projectName: 'Project 1', clientName: 'asd', projectStatus: 'Ongoing'),
ProjectsMock(projectId: '2', projectNumber: '2', projectName: 'Project 2', clientName: 'qwe', projectStatus: 'Completed'),
];
String selectedFilter = 'Ongoing';
void selectItem(int index) {
setState(() {
for (int i = 0; i < isSelected.length; i++) {
if (i != index) {
isSelected[i] = false;
return;
}
isSelected[i] = true;
}
});
}
void navigateToProject(BuildContext context, ProjectsMock project) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ProjectPage(),
settings: RouteSettings(
arguments: project,
)
)
);
}
void setBottomSheet(context) {
showModalBottomSheet(
context: context,
builder: (BuildContext buildContext) {
return Padding(
padding: const EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Text('Filters', style: TextStyle(fontWeight: FontWeight.bold),),
new Wrap(
spacing: 5.0,
children: List.generate(filters.length, (index) {
if (selectedFilter == filters.elementAt(index)) {
return new ActionChip(
label: new Text(filters.elementAt(index)),
backgroundColor: Colors.blue,
labelStyle: TextStyle(color: Colors.white),
onPressed: () {
return;
},
);
}
return new ActionChip(
label: new Text(filters.elementAt(index)),
backgroundColor: Colors.white,
labelStyle: TextStyle(color: Colors.blue),
onPressed: () {
return;
},
);
}),
),
new Text('Sort by', style: TextStyle(fontWeight: FontWeight.bold),),
new Wrap(
spacing: 5.0,
children: List.generate(sortOptions.length, (index) {
if (isSelected[index]) {
return new ActionChip(
label: sortOptions.elementAt(index),
backgroundColor: Colors.blue,
labelStyle: TextStyle(color: Colors.white),
onPressed: () {
return;
},
);
}
return new ActionChip(
label: sortOptions.elementAt(index),
backgroundColor: Colors.white,
labelStyle: TextStyle(color: Colors.blue),
onPressed: () {
return;
},
);
}),
),
new Container(
margin: const EdgeInsets.only(top: 10.0),
child: new Text('Sort Order', style: TextStyle(fontWeight: FontWeight.bold),),
),
new Wrap(
spacing: 5.0,
children: List.generate(sortOrder.length, (index) {
if (selectedSort == sortOrder[index]) {
return new ActionChip(
label: Text(sortOrder.elementAt(index)),
backgroundColor: Colors.blue,
labelStyle: TextStyle(color: Colors.white),
onPressed: () {
return;
},
);
}
return new ActionChip(
label: Text(sortOrder.elementAt(index)),
backgroundColor: Colors.white,
labelStyle: TextStyle(color: Colors.blue),
onPressed: () {
return;
},
);
}),
),
],
),
);
}
);
}
#override
Widget build(BuildContext context) {
return new Scaffold(
floatingActionButton: new FloatingActionButton(child: new Icon(Icons.filter_alt), onPressed: () => setBottomSheet(context), mini: true),
key: _scaffoldState,
body: new Column(
children: <Widget>[
new Expanded(
child: new Column(
children: <Widget>[
// Search header
new Container(
padding: const EdgeInsets.all(10.0),
child: new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Expanded(
child: new TextField(
decoration: new InputDecoration(
hintText: 'Search',
labelText: 'Search',
suffixIcon: new IconButton(icon: Icon(Icons.search), onPressed: () {
return;
}),
contentPadding: const EdgeInsets.only(left: 5.0, right: 5.0)
),
)
),
],
),
],
),
),
new Padding(
padding: const EdgeInsets.only(left: 10.0, right: 10.0),
child: new Column(
children: List.generate(projects.length, (index) {
return new Container(
margin: const EdgeInsets.only(bottom: 10.0),
child: new RaisedButton(
onPressed: () => navigateToProject(context, projects.elementAt(index)),
color: Colors.white,
textColor: Colors.black,
child: new Padding(
padding: const EdgeInsets.all(10.0),
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
new Expanded(
child: new Column(
children: <Widget>[
new Text(projects.elementAt(index)?.projectName, style: TextStyle(fontWeight: FontWeight.bold)),
new Text(projects.elementAt(index)?.projectNumber),
]
),
),
new Expanded(
child: new Column(
children: <Widget>[
new Text(projects.elementAt(index)?.clientName, style: TextStyle(fontWeight: FontWeight.bold)),
new Text(projects.elementAt(index)?.projectStatus),
]
),
)
],
),
),
),
);
}),
),
)
],
),
)
],
),
);
}
}
Here is a snapshot of the page.
How do I do it? I tried using Navigator but it goes to a completely new screen. Let me know if you need more information.
You create another inside your main.dart file and use Navigator to move to that screen without actually moving to another screen instead replacing the current one
this is how the code goes
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DisplayPictureScreen(string1: string),//passing a parameter
),
);
and this how the class goes
class DisplayPictureScreen extends StatelessWidget {
final String string1;
const DisplayPictureScreen({Key key, this.string1}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(value[0]["label"],style: TextStyle(color: Colors.black,fontSize: 20),
)),
body: Column(
children: [
Text("lsfnklsnlvfdngvlirs")
],
),
);
}
}
I have created a starter kit in flutter for a personal project.
Everything is working fine but I have an iisue where I'm unable to highlight the current selected item in the drawer.
I'm abit lost on where I chould be put the code that determins the current selected item.
Below is my code!
class _MdDrawerState extends State<MdDrawer>
with SingleTickerProviderStateMixin<MdDrawer> {
final _animationDuration = const Duration(milliseconds: 350);
AnimationController _animationController;
Stream<bool> isDrawerOpenStream;
StreamController<bool> isDrawerOpenStreamController;
StreamSink<bool> isDrawerOpenSink;
.....
#override
void dispose() {
_animationController.dispose();
isDrawerOpenStreamController.close();
isDrawerOpenSink.close();
super.dispose();
}
void onIconPressed() {
final animationStatus = _animationController.status;
final isAnimationCompleted = animationStatus == AnimationStatus.completed;
.....
}
#override
Widget build(BuildContext context) {
final screenWidth = MediaQuery.of(context).size.width;
return StreamBuilder<bool>(
initialData: false,
stream: isDrawerOpenStream,
builder: (context, isLeftDrawerOpenedAsync) {
return AnimatedPositioned(
duration: _animationDuration,
top: 0,
bottom: 0,
left: isLeftDrawerOpenedAsync.data ? 0 : -screenWidth,
right: isLeftDrawerOpenedAsync.data ? 0 : screenWidth - 45,
child: Row(
children: <Widget>[
Expanded(
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 20),
color: Theme.of(context).backgroundColor,
child: ListView(
children: <Widget>[
Column(
children: <Widget>[
SizedBox(
height: 30,
),
ListTile(
title: Text('First - Last',
style: Theme.of(context).textTheme.headline),
subtitle: Text('something#gmail.com',
style: Theme.of(context).textTheme.subhead),
leading: CircleAvatar(
child: Icon(
Icons.perm_identity,
color: Theme.of(context).iconTheme.color,
),
radius: 40,
),
),
Divider(
height: 30,
),
MdNavItem(
icon: Icons.home,
title: 'Home',
onTap: () {
onIconPressed();
BlocProvider.of<MdNavBloc>(context)
.add(NavigationEvents.HomeClickedEvent);
},
),
MdNavItem(
icon: Icons.account_box,
title: 'Account',
onTap: () {
onIconPressed();
BlocProvider.of<MdNavBloc>(context)
.add(NavigationEvents.AccountClickedEvent);
},
),
MdNavItem(
icon: Icons.shopping_basket,
title: 'Orders',
onTap: () {
onIconPressed();
BlocProvider.of<MdNavBloc>(context)
.add(NavigationEvents.OrderClickedEvent);
},
),
MdNavItem(
icon: Icons.card_giftcard,
title: 'Wishlist',
onTap: () {
onIconPressed();
BlocProvider.of<MdNavBloc>(context)
.add(NavigationEvents.WishlistClickedEvent);
},
),
Divider(
height: 30,
),
MdNavItem(
icon: Icons.settings,
title: 'Settings',
onTap: () {
onIconPressed();
BlocProvider.of<MdNavBloc>(context)
.add(NavigationEvents.SettingsClickedEvent);
},
),
MdNavItem(
icon: Icons.exit_to_app,
title: 'Logout',
),
Divider(
height: 45,
),
],
),
],
),
),
),
......
],
),
);
},
);
}
}
And the MdNavItem class
class MdNavItem extends StatelessWidget {
final IconData icon;
final String title;
final Function onTap;
const MdNavItem({this.icon, this.title, this.onTap});
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onTap,
child: Padding(
padding: const EdgeInsets.all(16),
child: Container(
color: Theme.of(context).backgroundColor,
child: Row(
children: <Widget>[
Icon(
icon,
size: 25,
color: Theme.of(context).iconTheme.color,
),
SizedBox(
width: 20,
),
Text(
title,
style: Theme.of(context).textTheme.headline,
),
],
),
),
),
);
}
}
Edit:
First Way to do:
Add this code to your Drawer:
class _MdDrawerState extends State<MdDrawer>
with SingleTickerProviderStateMixin<MdDrawer> {
final _animationDuration = const Duration(milliseconds: 350);
AnimationController _animationController;
Stream<bool> isDrawerOpenStream;
StreamController<bool> isDrawerOpenStreamController;
StreamSink<bool> isDrawerOpenSink;
final List<bool> isTaped = [true, false, false, false, false]; // the first is true because when the app
//launch the home needs to be in red(or the
//color you choose)
void changeHighlight(int index){
for(int indexTap = 0; indexTap < isTaped.length; indexTap++) {
if (indexTap == index) {
isTaped[index] = true; //used to change the value of the bool list
} else {
isTaped[indexTap] = false;
}
}
}
.....
#override
void dispose() {
_animationController.dispose();
isDrawerOpenStreamController.close();
isDrawerOpenSink.close();
super.dispose();
}
void onIconPressed() {
final animationStatus = _animationController.status;
final isAnimationCompleted = animationStatus == AnimationStatus.completed;
.....
}
#override
Widget build(BuildContext context) {
final screenWidth = MediaQuery.of(context).size.width;
return StreamBuilder<bool>(
initialData: false,
stream: isDrawerOpenStream,
builder: (context, isLeftDrawerOpenedAsync) {
return AnimatedPositioned(
duration: _animationDuration,
top: 0,
bottom: 0,
left: isLeftDrawerOpenedAsync.data ? 0 : -screenWidth,
right: isLeftDrawerOpenedAsync.data ? 0 : screenWidth - 45,
child: Row(
children: <Widget>[
Expanded(
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 20),
color: Theme.of(context).backgroundColor,
child: ListView(
children: <Widget>[
Column(
children: <Widget>[
SizedBox(
height: 30,
),
ListTile(
title: Text('First - Last',
style: Theme.of(context).textTheme.headline),
subtitle: Text('something#gmail.com',
style: Theme.of(context).textTheme.subhead),
leading: CircleAvatar(
child: Icon(
Icons.perm_identity,
color: Theme.of(context).iconTheme.color,
),
radius: 40,
),
),
Divider(
height: 30,
),
MdNavItem(
wasTaped: isTaped[0],
icon: Icons.home,
title: 'Home',
onTap: () {
onIconPressed();
BlocProvider.of<MdNavBloc>(context)
.add(NavigationEvents.HomeClickedEvent);
changeHighlight(0);
},
),
MdNavItem(
wasTaped: isTaped[1],
icon: Icons.account_box,
title: 'Account',
onTap: () {
onIconPressed();
BlocProvider.of<MdNavBloc>(context)
.add(NavigationEvents.AccountClickedEvent);
changeHighlight(1);
},
),
MdNavItem(
wasTaped: isTaped[2],
icon: Icons.shopping_basket,
title: 'Orders',
onTap: () {
onIconPressed();
BlocProvider.of<MdNavBloc>(context)
.add(NavigationEvents.OrderClickedEvent);
changeHighlight(2);
},
),
MdNavItem(
wasTaped: isTaped[3],
icon: Icons.card_giftcard,
title: 'Wishlist',
onTap: () {
onIconPressed();
BlocProvider.of<MdNavBloc>(context)
.add(NavigationEvents.WishlistClickedEvent);
changeHighlight(3);
},
),
Divider(
height: 30,
),
MdNavItem(
wasTaped: isTaped[4],
icon: Icons.settings,
title: 'Settings',
onTap: () {
onIconPressed();
BlocProvider.of<MdNavBloc>(context)
.add(NavigationEvents.SettingsClickedEvent);
changeHighlight(4);
},
),
MdNavItem(
icon: Icons.exit_to_app,
title: 'Logout',
),
Divider(
height: 45,
),
],
),
],
),
),
),
......
],
),
);
},
);
}
}
And this to your MdNavItem:
class MdNavItem extends StatelessWidget {
final IconData icon;
final String title;
final Function onTap;
final bool wasTaped; //receiving the bool value (if was taped or not)
const MdNavItem({this.icon, this.title, this.onTap, this.wasTaped});
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onTap,
child: Padding(
padding: const EdgeInsets.all(16),
child: Container(
color: Theme.of(context).backgroundColor,
child: Row(
children: <Widget>[
Icon(
icon,
size: 25,
color: wasTaped ? Colors.red : Theme.of(context).iconTheme.color, //the condition to change the color
),
SizedBox(
width: 20,
),
Text(
title,
style: wasTaped ? TextStyle(
color: Colors.red,
) : Theme.of(context).textTheme.headline,
),
],
),
),
),
);
}
}
Old answer, Second way:
First Screen, where PageView is placed:
class FirstScreen extends StatelessWidget {
final PageController pageController = PageController(initialPage: 0);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Kit App'),
),
drawer: CustomDrawer(
pageController: pageController,
),
body: PageView(
controller: pageController,
physics: NeverScrollableScrollPhysics(), //to prevent scroll
children: <Widget>[
HomeScreen(),
AccountScreen(), //your pages
OrdersScreen(),
WishListScreen(),
],
),
);
}
}
The CustomDrawer:
class CustomDrawer extends StatelessWidget {
CustomDrawer({#required this.pageController});
final PageController pageController;
#override
Widget build(BuildContext context) {
return Drawer(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 20),
child: Column(
children: <Widget>[
DrawerItem(
onTap: (){
Navigator.pop(context); //to close the drawer
pageController.jumpToPage(0);
},
leading: Icons.home,
title: 'Home',
index: 0,
controller: pageController,
),
DrawerItem(
onTap: (){
Navigator.pop(context);
pageController.jumpToPage(1);
},
leading: Icons.account_box,
title: 'Account',
index: 1,
controller: pageController,
),
DrawerItem(
onTap: (){
Navigator.pop(context);
pageController.jumpToPage(2);
},
leading: Icons.shopping_cart,
title: 'Orders',
index: 2,
controller: pageController,
),
DrawerItem(
onTap: (){
Navigator.pop(context);
pageController.jumpToPage(3);
},
leading: Icons.card_travel,
title: 'Wishlist',
index: 3,
controller: pageController,
),
],
),
),
);
}
}
and the DrawerItem, where the condition to change the color of the items is placed:
class DrawerItem extends StatelessWidget {
DrawerItem({
#required this.onTap,
#required this.leading,
#required this.title,
#required this.index,
#required this.controller,
});
final VoidCallback onTap;
final IconData leading;
final String title;
final int index;
final PageController controller;
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onTap,
child: ListTile(
leading: Icon(
leading,
color: controller.page.round() == index ? Colors.red : Colors.grey,
),
title: Text(
title,
style: TextStyle(
color: controller.page.round() == index ? Colors.red : Colors.grey,
),
),
),
);
}
}
Result:
Now you just need to implement this on your code.