How can I fix the renderflex overflow of a card in Flutter? - flutter

How can I fix the RenderFlex overflowed pixel in my card Flutter? I cant seem to find a tutorial regarding this kind of problem. All of the tutorials in StackOverflow teach you to use the listview and SingleChildScrollView but that is not the case for me. The error shows in the card itself and I don't want the card to be using a singlechildscrollview.
I already tried fixing it by lowering the height and width but I will still need a proper tutorial that can help me fix this kind of issues.
This is the card.dart for the application
import 'package:flutter/material.dart';
class ListViewCard extends StatelessWidget {
final String title;
final void Function()? onTap;
final String imageOfPlant; //Change to String
const ListViewCard({
super.key,
required this.title,
required this.onTap,
required this.imageOfPlant,
});
#override
Widget build(BuildContext context) {
return Card(
color: const Color.fromARGB(255, 75, 175, 78),
elevation: 1,
margin: const EdgeInsets.all(8),
semanticContainer: true,
clipBehavior: Clip.antiAliasWithSaveLayer,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
child: InkWell(
splashColor: Colors.lightGreenAccent.withAlpha(30),
onTap: onTap,
//sizedBox of the card
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
//image of the card
Image.asset(
imageOfPlant,
height: 200,
width: 150,
fit: BoxFit.cover,
),
SizedBox(
height: 50,
width: 150,
child: Center(
child: Text(
title,
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 19,
fontFamily: 'RobotoMedium',
color: Color(0xffeeeeee)), // textstyle
),
),
), //text //SizedBox
], // <widget>[]
), // column
), //inkwell
); // card
}
}
This is the home.dart where the card will be called.
import 'package:flutter/material.dart';
import 'package:picleaf/nav_pages/plant.dart';
import '../widgets/card.dart';
class homePage extends StatefulWidget {
const homePage({super.key});
#override
State<homePage> createState() => _HomePageState();
}
List<String> plants = [
"Bell Pepper",
"Cassava",
"Grape",
"Potato",
"Strawberry",
"Tomato",
];
class CustomSearchDelegate extends SearchDelegate {
// Demo list to show querying
CustomSearchDelegate({String hinttext = "Search plants here"})
: super(searchFieldLabel: hinttext);
// first overwrite to
// clear the search text
#override
List<Widget>? buildActions(BuildContext context) {
return [
IconButton(
onPressed: () {
query = '';
},
icon: const Icon(Icons.clear),
),
];
}
// second overwrite to pop out of search menu
#override
Widget? buildLeading(BuildContext context) {
return IconButton(
onPressed: () {
close(context, null);
},
icon: const Icon(Icons.arrow_back),
);
}
// third overwrite to show query result
#override
Widget buildResults(BuildContext context) {
List<String> matchQuery = [];
for (var fruit in plants) {
if (fruit.toLowerCase().contains(query.toLowerCase())) {
matchQuery.add(fruit);
}
}
return ListView.builder(
itemCount: matchQuery.length,
itemBuilder: (context, index) {
var result = matchQuery[index];
return ListTile(
title: Text(
result,
style: const TextStyle(fontFamily: 'RobotoMedium'),
),
);
},
);
}
// last overwrite to show the
// querying process at the runtime
#override
Widget buildSuggestions(BuildContext context) {
List<String> matchQuery = [];
for (var fruit in plants) {
if (fruit.toLowerCase().contains(query.toLowerCase())) {
matchQuery.add(fruit);
}
}
return ListView.builder(
itemCount: matchQuery.length,
itemBuilder: (context, index) {
var result = matchQuery[index];
return ListTile(
title: Text(
result,
style: const TextStyle(fontFamily: 'RobotoMedium'),
),
);
},
);
}
}
class _HomePageState extends State<homePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: const Text(
"PicLeaf",
style: TextStyle(
color: Color.fromRGBO(102, 204, 102, 1.0),
fontWeight: FontWeight.bold),
),
backgroundColor: Colors.white,
shadowColor: const Color.fromARGB(255, 95, 94, 94),
actions: [
IconButton(
onPressed: () {
// method to show the search bar
showSearch(
context: context,
// delegate to customize the search bar
delegate: CustomSearchDelegate());
},
icon: const Icon(Icons.search, color: Colors.black),
)
],
),
backgroundColor: const Color(0xffeeeeee),
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
const SizedBox(
height: 10,
),
Container(
padding: const EdgeInsets.fromLTRB(20, 20, 20, 10),
child: const Text(
'Take a pic!',
style: TextStyle(
fontSize: 35,
fontFamily: 'RobotoBold',
color: Colors.black),
textAlign: TextAlign.left,
),
),
Container(
padding: const EdgeInsets.fromLTRB(20, 0, 20, 10),
child: const Text('Find out what is wrong with your plant!',
style: TextStyle(
fontSize: 18,
fontFamily: 'RobotoMedium',
color: Color.fromRGBO(102, 124, 138, 1.0)),
textAlign: TextAlign.left),
),
const SizedBox(
height: 10,
),
Container(
color: const Color.fromRGBO(102, 204, 102, 1.0),
child: Column(
children: <Widget>[
Container(
padding: const EdgeInsets.fromLTRB(20, 10, 20, 0),
margin: const EdgeInsets.symmetric(horizontal: 0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: const <Widget>[
Expanded(
child: Text('List of Plants',
style: TextStyle(
fontSize: 30,
fontFamily: 'RobotoBold',
color: Color(0xffeeeeee)),
textAlign: TextAlign.center),
),
],
),
),
GridView.count(
physics: const ScrollPhysics(),
shrinkWrap: true,
crossAxisSpacing: 20,
mainAxisSpacing: 20,
crossAxisCount: 2,
children: <Widget>[
ListViewCard(
title: "Bell Pepper",
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) =>
const SecondPage(plantname: 'Bell Pepper')));
},
imageOfPlant:
"assets/Images_of_Plant/BellPeper_Image.jpg",
),
ListViewCard(
title: "Bell Pepper",
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) =>
const SecondPage(plantname: 'Bell Pepper')));
},
imageOfPlant:
"assets/Images_of_Plant/BellPeper_Image.jpg",
),
ListViewCard(
title: "Bell Pepper",
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) =>
const SecondPage(plantname: 'Bell Pepper')));
},
imageOfPlant:
"assets/Images_of_Plant/BellPeper_Image.jpg",
),
ListViewCard(
title: "Bell Pepper",
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) =>
const SecondPage(plantname: 'Bell Pepper')));
},
imageOfPlant:
"assets/Images_of_Plant/BellPeper_Image.jpg",
),
ListViewCard(
title: "Bell Pepper",
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) =>
const SecondPage(plantname: 'Bell Pepper')));
},
imageOfPlant:
"assets/Images_of_Plant/BellPeper_Image.jpg",
),
ListViewCard(
title: "Bell Pepper",
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) =>
const SecondPage(plantname: 'Bell Pepper')));
},
imageOfPlant:
"assets/Images_of_Plant/BellPeper_Image.jpg",
),
],
),
],
),
),
],
),
),
);
}
}

Your gridView's Item give you a specific size but you are setting more than that for your container and text, I suggest you try this:
child: Stack(
children: <Widget>[
//image of the card
Image.asset(
imageOfPlant,
height: double.infinity,
width: 150,
fit: BoxFit.cover,
),
Positioned(
bottom: 0,
left: 0,
right: 0,
child: SizedBox(
height: 50,
width: 150,
child: Center(
child: Text(
title,
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 19,
fontFamily: 'RobotoMedium',
color: Color(0xffeeeeee)), // textstyle
),
),
),
), //text //SizedBox
], // <widget>[]
),
and If you want to change item's AspectRatio you can do this:
GridView.count(
physics: const ScrollPhysics(),
shrinkWrap: true,
crossAxisSpacing: 20,
mainAxisSpacing: 20,
crossAxisCount: 2,
childAspectRatio: 2 / 3, <--- add this
children: <Widget>[
...
]
)

Related

Flutter - codes not working correctly after putting inside setState

I am trying to add to an array list after user clicked. I am using InkWell, onTap function.
child: InkWell(
onTap: () {
if (tempArray.contains(entries[index].toString())) {
tempArray.remove(entries[index].toString());
print(tempArray.toList().toString());
} else {
tempArray.add(entries[index].toString());
print(tempArray.toList().toString());
}
My debug console is printing these out,
enter image description here
However, when i put the codes inside a setState, this is what got printed
child: InkWell(
onTap: () {
setState(() {
if (tempArray.contains(entries[index].toString())) {
tempArray.remove(entries[index].toString());
print(tempArray.toList().toString());
} else {
tempArray.add(entries[index].toString());
print(tempArray.toList().toString());
}
});
enter image description here
What i am trying to do, is to show/hide the 'trailing' icon in the ListTile, based on whatever user had selected the particular item.
My full codes (without the setState) are as follows,
import 'package:flutter/material.dart';
class Personal1Redo extends StatefulWidget {
#override
_Personal1RedoState createState() => _Personal1RedoState();
}
class _Personal1RedoState extends State<Personal1Redo> {
#override
Widget build(BuildContext context) {
final mediaQuery = MediaQuery.of(context);
List<String> entries = [
'Residental Loan',
'Personal Loan',
'Car Loan',
'Renovation Loan',
'Savings Account',
];
List<String> tempArray = [];
final heading = Column(
children: [
const SizedBox(
height: 40,
),
SizedBox(
height: (mediaQuery.size.height - mediaQuery.padding.top) * 0.1,
child: const Align(
alignment: Alignment.center,
child: Text(
'What do you aspire to do?',
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20,
),
),
),
),
const SizedBox(
height: 20,
),
],
);
return Scaffold(
appBar: AppBar(
title: Text('Borrower redo'),
),
body: SingleChildScrollView(
child: Column(
children: <Widget>[
heading,
ListView.builder(
shrinkWrap: true,
itemCount: entries.length,
itemBuilder: (ctx, index) {
return Container(
width: mediaQuery.size.width * 0.9,
padding: const EdgeInsets.all(15),
child: InkWell(
onTap: () {
if (tempArray.contains(entries[index].toString())) {
tempArray.remove(entries[index].toString());
print(tempArray.toList().toString());
} else {
tempArray.add(entries[index].toString());
print(tempArray.toList().toString());
}
},
child: Card(
margin: const EdgeInsets.all(10),
elevation: 8,
child: ListTile(
title: Text(
entries[index],
style: TextStyle(
color: Colors.grey.shade800,
fontSize: 20,
),
textAlign: TextAlign.center,
),
trailing: tempArray.contains(entries[index])
? Icon(Icons.check_box_outline_blank_outlined)
: null,
),
),
),
);
})
],
),
),
);
}
}
Any helps and guidance is very much appreciated, thanks!!
Define variables and functions outside build method.
As setState method, calls build, every time it is called.
Like this :
import 'package:flutter/material.dart';
class Personal1Redo extends StatefulWidget {
#override
_Personal1RedoState createState() => _Personal1RedoState();
}
class _Personal1RedoState extends State<Personal1Redo> {
List<String> entries = [
'Residental Loan',
'Personal Loan',
'Car Loan',
'Renovation Loan',
'Savings Account',
];
List<String> tempArray = [];
getHeadingWidget(BuildContext context) {
return Column(
children: [
const SizedBox(
height: 40,
),
SizedBox(
height: (mediaQuery!.size.height - mediaQuery.padding.top) * 0.1,
child: const Align(
alignment: Alignment.center,
child: Text(
'What do you aspire to do?',
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20,
),
),
),
),
const SizedBox(
height: 20,
),
],
);
}
#override
Widget build(BuildContext context) {
final mediaQuery = MediaQuery.of(context);
return Scaffold(
appBar: AppBar(
title: Text('Borrower redo'),
),
body: SingleChildScrollView(
child: Column(
children: <Widget>[
getHeadingWidget(context),
ListView.builder(
shrinkWrap: true,
itemCount: entries.length,
itemBuilder: (ctx, index) {
return Container(
width: mediaQuery.size.width * 0.9,
padding: const EdgeInsets.all(15),
child: InkWell(
onTap: () {
if (tempArray.contains(entries[index].toString())) {
tempArray.remove(entries[index].toString());
print(tempArray.toList().toString());
} else {
tempArray.add(entries[index].toString());
print(tempArray.toList().toString());
}
},
child: Card(
margin: const EdgeInsets.all(10),
elevation: 8,
child: ListTile(
title: Text(
entries[index],
style: TextStyle(
color: Colors.grey.shade800,
fontSize: 20,
),
textAlign: TextAlign.center,
),
trailing: tempArray.contains(entries[index])
? Icon(Icons.check_box_outline_blank_outlined)
: null,
),
),
),
);
})
],
),
),
);
}
}

how to store the name of the container in an array

hi i am new to flutter can anyone tell me how to save the preferences in an array
what are the methods used in storing the value
class PrefPage extends StatefulWidget {
#override
_PrefPageState createState() => _PrefPageState();
}
class _PrefPageState extends State<PrefPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: Container(
color: Theme.of(context).backgroundColor,
padding: EdgeInsets.fromLTRB(10, 10, 30, 10),
height: 80,
child: Spring.bubbleButton(
onTap: () {
Navigator.push(
context, MaterialPageRoute(builder: (context) => Home()));
},
child: Text(
"👉",
style: TextStyle(fontSize: 30),
textAlign: TextAlign.end,
),
),
),
backgroundColor: Theme.of(context).backgroundColor,
appBar: AppBar(
centerTitle: false,
leadingWidth: 0,
elevation: 0,
backgroundColor: Theme.of(context).backgroundColor,
title: Text(
"Swoken",
style: GoogleFonts.niconne(
textStyle: TextStyle(
fontSize: 30,
color: Theme.of(context).primaryColor,
),
),
),
),
body: SingleChildScrollView(
physics: BouncingScrollPhysics(),
child: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
" What are your",
style: TextStyle(fontSize: 40, fontWeight: FontWeight.w100),
),
Text(
" Interests ?",
style: TextStyle(fontSize: 40, fontWeight: FontWeight.bold),
),
SizedBox(
height: 20,
),
GridView.count(
scrollDirection: Axis.vertical,
physics: ScrollPhysics(),
childAspectRatio: 2.3,
crossAxisCount: 2,
padding: EdgeInsets.all(5),
shrinkWrap: true,
children: List.generate(
intr.length,
(index) {
return PrefCont(
child: AutoSizeText(
intr[index]["icon"] + " " + intr[index]["title"],
minFontSize: 16,
maxLines: 1,
style: TextStyle(fontSize: 40),
),
);
},
),
),
],
),
),
),
);
}
}
class PrefCont extends StatefulWidget {
PrefCont({this.child});
final child;
#override
_PrefContState createState() => _PrefContState();
}
class _PrefContState extends State<PrefCont> {
List<String> sel = [];
bool isSelected = false;
#override
Widget build(BuildContext context) {
var themeId = DynamicTheme.of(context)!.themeId;
var kContColor = Color(0Xfff6f6f6);
themeId == 0
? kContColor = Color(0Xfff6f6f6)
: kContColor = Color(0xff272727);
return InkWell(
onTap: () {
setState(() {
isSelected = !isSelected;
});
},
child: Container(
alignment: Alignment.center,
decoration: BoxDecoration(
color: isSelected ? kContInactColor : kContColor,
borderRadius: BorderRadius.circular(10),
),
margin: EdgeInsets.all(10),
padding: EdgeInsets.all(10),
child: widget.child,
),
);
}
}
...........................................................................................................................................................................................................................................................................
First you need to modelize your elements as objects then, you need to create a data set containing all of your tiles:
class PreferencesData {
final String name;
final String assetName;
PreferencesData({required this.name, required this.assetName});
}
list _dataSet = [
PreferencesData(name: "Football", assetName: "/assets/icons/football.png"),
PreferencesData(name: "Food", assetName: "/assets/icons/food.png"),
...
];
Now that you have all your objects in a dataset you can use it in your grid to display them correctly:
children: [for (PreferencesData pref in _dataSet)
PrefCont(...) // access your data with pref.name
]

confused about setState inside onTap Flutter

I've been trying to learn Flutter and this part got me really confused. Thanks a million for your help.
I wanted to return data (an object) to the first screen from the second screen. I did successfully thanks to posts I read from the internet but haven't managed to fully understand. Specifically: Why do I need to assign categoryData to the returned object then again assign it to categoryCard? Why can't I do it directly by assigning categoryCard to the returned Object? This is code that works:
First screen:
SizedBox(
height: 95,
child: GestureDetector(
onTap: () async {
final categoryData =
await Navigator.pushNamed(context, '/EditCategory');
setState(() => categoryCard = categoryData);
},
child: categoryCard),
),
Second screen:
return Card(
child: ListTile(
title: Text('${myText[index]}'),
leading: myIcon[index],
trailing: Icon(Icons.arrow_forward_ios),
onTap: () {
Navigator.pop(
context,
CategoryCard(
categoryIcon: myIcon[index],
categoryText: Text(
'${myText[index]}',
style: TextStyle(fontSize: 20),
)));
},
),
);
Code I think should work but doesn't
First screen:
SizedBox(
height: 95,
child: GestureDetector(
onTap: () {
setState(() async {
CategoryCard categoryCard =
await Navigator.pushNamed(context, '/EditCategory');
});
},
child: categoryCard),
),
Second screen is the same
This is the entire code of the first and second screen in case you'd like to know:
First:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'MyApp.dart';
class Input extends StatefulWidget {
#override
_InputState createState() => _InputState();
}
class _InputState extends State<Input> {
CategoryCard categoryCard = CategoryCard();
final _formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color.fromRGBO(210, 234, 251, 1),
appBar: appBarInEx(),
body: TabBarView(
children: [
ListView(
children: [
Form(
key: _formKey,
child: Column(
children: [
TextFormField(
validator: (value) {
if (value.isEmpty) {
return 'Please enter the value';
}
return null;
},
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: ElevatedButton(
onPressed: () {
if (_formKey.currentState.validate()) {
Scaffold.of(context).showSnackBar(
SnackBar(content: Text('Processing Data')));
}
},
child: Text('Submit'),
),
),
],
),
),
SizedBox(
height: 150,
child: Card(
color: Color.fromRGBO(254, 228, 194, 1),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
SizedBox(
height: 20,
),
Text(
'Amount',
style: TextStyle(fontSize: 30),
),
SizedBox(
height: 15,
),
Text(r'0$',
style: TextStyle(
fontSize: 30,
)),
Text('_____________________________________',
style: TextStyle(
fontSize: 15,
))
],
),
),
),
),
SizedBox(
height: 95,
child: GestureDetector(
onTap: () async {
final categoryData =
await Navigator.pushNamed(context, '/EditCategory');
setState(() => categoryCard = categoryData);
},
child: categoryCard),
),
SizedBox(
height: 95,
child: Card(
color: Color.fromRGBO(254, 228, 194, 1),
child: ListTile(
contentPadding:
EdgeInsets.symmetric(vertical: 18, horizontal: 16),
title: Text(
'Note',
style: TextStyle(fontSize: 20),
),
leading: Icon(Icons.description_outlined, size: 40),
trailing: Icon(
Icons.arrow_forward_ios_outlined,
size: 30,
),
),
),
),
SizedBox(
height: 95,
child: Card(
color: Color.fromRGBO(254, 228, 194, 1),
child: ListTile(
contentPadding:
EdgeInsets.symmetric(vertical: 18, horizontal: 16),
title: Text(
'Date',
style: TextStyle(fontSize: 20),
),
leading: Icon(Icons.event, size: 40),
trailing: Icon(
Icons.arrow_forward_ios_outlined,
size: 30,
),
),
),
),
Container(
margin: EdgeInsets.fromLTRB(30, 70, 30, 0),
child: Padding(
padding: const EdgeInsets.all(18.0),
child: RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
side: BorderSide(color: Colors.red)),
elevation: 10,
color: Colors.lime,
onPressed: () {
Navigator.pushNamed(context, '/');
},
textColor: Colors.white,
child: Text(
'Save',
style: TextStyle(fontSize: 40),
),
),
),
)
],
),
Container()
],
),
);
}
}
class CategoryCard extends StatelessWidget {
final Text categoryText;
final Icon categoryIcon;
CategoryCard(
{Key key,
this.categoryText = const Text(
'Category',
style: TextStyle(fontSize: 20),
),
this.categoryIcon = const Icon(
Icons.category_outlined,
size: 40,
)})
: super(key: key);
#override
Widget build(BuildContext context) {
return Card(
color: Color.fromRGBO(254, 228, 194, 1),
child: ListTile(
contentPadding: EdgeInsets.symmetric(vertical: 18, horizontal: 16),
title: categoryText,
leading: categoryIcon,
trailing: Icon(
Icons.arrow_forward_ios_outlined,
size: 30,
),
),
);
}
}
Second:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:material_floating_search_bar/material_floating_search_bar.dart';
import 'Input.dart';
import 'MyApp.dart';
class EditCategory extends StatefulWidget {
#override
_EditCategoryState createState() => _EditCategoryState();
}
class _EditCategoryState extends State<EditCategory> {
List<String> myText = [
'Add Category',
'Cosmetic',
'Education',
'Clothes',
'Food',
'Cosmetic',
'Education',
'Clothes',
'Food'
];
List<Widget> myIcon = [
Icon(Icons.add_circle_outline),
Icon(Icons.no_food_outlined),
Icon(Icons.face),
Icon(Icons.book_outlined),
Icon(Icons.g_translate),
Icon(Icons.no_food_outlined),
Icon(Icons.face),
Icon(Icons.book_outlined),
Icon(Icons.g_translate),
];
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
backgroundColor: Color.fromRGBO(210, 234, 251, 1),
appBar: appBarInEx(),
body: TabBarView(
children: [
Column(
children: [
FloatingSearchAppBar(
title: const Text('Enter Category Name'),
transitionDuration: const Duration(milliseconds: 800),
color: Colors.orangeAccent.shade100,
colorOnScroll: Colors.greenAccent.shade200,
height: 55,
),
Expanded(
child: ListView.builder(
itemCount: myText.length,
itemBuilder: (context, index) {
if (index == 0) {
return SizedBox(
height: 90,
child: Card(
child: ListTile(
title: Text('${myText[index]}'),
leading: myIcon[index],
trailing: Icon(Icons.arrow_forward_ios),
),
));
}
return Card(
child: ListTile(
title: Text('${myText[index]}'),
leading: myIcon[index],
trailing: Icon(Icons.arrow_forward_ios),
onTap: () {
Navigator.pop(
context,
CategoryCard(
categoryIcon: myIcon[index],
categoryText: Text(
'${myText[index]}',
style: TextStyle(fontSize: 20),
)));
},
),
);
},
)),
],
),
Container()
],
),
),
);
}
}
The good code waits for the onTap and assign the result into a local variable. Then it uses setState to assign the local variable into the instance field.
Why do I need to assign categoryData to the returned object then again assign it to categoryCard? Why can't I do it directly by assigning categoryCard to the returned Object?
You can do that actually, this will work:
GestureDetector(
onTap: () async {
categoryData = await Navigator.push(...);
setState(() {});
},
),
Basically setState tells Flutter to rebuild your widget, it's not strictly required to perform state setting within the callback.
Regarding bad code: you use setState with an async callback so Flutter will just rebuild your widget immediately at that moment, it doesn't wait for your async operation to complete. At the time of rebuild, categoryData has the old value so nothing changes on the screen. When user triggers onTap on the second screen and pops back to the first, categoryData is updated with the new value but your widget is not rebuilt so it still shows outdated data.

Ripple effect appears under custem listview item on click in Flutter

I have tried many solutions from this platform and others too but my problem remains the same. I have done this before and successfully ripple the listview item in another custom listview. But this time i am not getting any clue where i am lacking. The previous solution make things more messy if try this time. Ripple is appearing under listview item what i want is to only listview item do ripples.
class Dashboard extends StatefulWidget {
#override
_DashboardState createState() => _DashboardState();
}
class _DashboardState extends State<Dashboard> {
// Map<String, dynamic> args;
List<DashboardItem> lst = [
DashboardItem(
img: 'assets/sales.png', name: 'Sales', subtitle: 'Your daily sales'),
DashboardItem(
img: 'assets/order.png', name: 'Orders', subtitle: 'Your new orders'),
DashboardItem(
img: 'assets/report.png',
name: 'Reports',
subtitle: 'Your daily reports'),
DashboardItem(
img: 'assets/setting.png',
name: 'Setting',
subtitle: 'Application setting'),
DashboardItem(
img: 'assets/register.png',
name: 'Register',
subtitle: 'Close your register'),
DashboardItem(
img: 'assets/logout.png', name: 'Logout', subtitle: 'You can rest')
];
#override
Widget build(BuildContext context) {
// args = ModalRoute.of(context).settings.arguments;
// print('Dashboard : ${args['regId']}');
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.red,
elevation: 0.0,
title: Text('My Dashboard'),
centerTitle: true,
),
body: LayoutBuilder(
builder: (context, constraints){
if(constraints.maxWidth < 600){
return ListView.builder(
itemCount: lst.length,
shrinkWrap: true,
itemBuilder: (context, position){
return Container(
padding: position == lst.length ? const EdgeInsets.only(top:16.0) : const EdgeInsets.only(top:16.0, bottom: 16.0),
child: InkWell(
child: DashboardCard(lst[position]),
onTap: (){
Toast.show('In List', context);
},
),
);
},
);
}
else{
return GridView.builder(
itemCount: lst.length,
shrinkWrap: true,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
itemBuilder: (context, position){
return InkWell(
child: DashboardCard(lst[position]),
onTap: (){
Toast.show('In Grid', context);
},
);
},
);
}
},
),
);
}
}
DashboardCard Class
class DashboardCard extends StatelessWidget {
final DashboardItem _dashboardItem;
const DashboardCard(this._dashboardItem);
#override
Widget build(BuildContext context) {
return Center(
child: Container(
height: 230,
width: 280,
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
elevation: 10.0,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image(
image: AssetImage(_dashboardItem.img),
fit: BoxFit.contain,
width: 80,
height: 80,
),
SizedBox(height: 20,),
Text(
_dashboardItem.name,
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
fontFamily: 'Ubuntu',
letterSpacing: 2.0,
color: Colors.redAccent,
),
),
Padding(
padding: const EdgeInsets.all(3.0),
child: Text(
_dashboardItem.subtitle,
maxLines: 2,
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 10,
fontWeight: FontWeight.normal,
letterSpacing: 2.0,
color: Colors.grey,
),
),
),
],
),
),
),
),
);
}
}
The issue is with the Center widget in your DashboardCard:
You can fix it wrapping your DashboardCard Container widget in an InkWell widget and pass a onTap parameter to the DashboardCard constructor:
class DashboardCard extends StatelessWidget {
final DashboardItem _dashboardItem;
final VoidCallback onTap;
const DashboardCard(
this._dashboardItem, {
this.onTap,
});
#override
Widget build(BuildContext context) {
return Center(
child: InkWell(
onTap: onTap,
child: Container(
height: 230,
width: 280,
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
elevation: 10.0,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image(
image: AssetImage(_dashboardItem.img),
fit: BoxFit.contain,
width: 80,
height: 80,
),
SizedBox(
height: 20,
),
Text(
_dashboardItem.name,
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
fontFamily: 'Ubuntu',
letterSpacing: 2.0,
color: Colors.redAccent,
),
),
Padding(
padding: const EdgeInsets.all(3.0),
child: Text(
_dashboardItem.subtitle,
maxLines: 2,
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 10,
fontWeight: FontWeight.normal,
letterSpacing: 2.0,
color: Colors.grey,
),
),
),
],
),
),
),
),
),
);
}
}
The use it in other places like:
DashboardCard(
lst[position],
onTap: () {
Toast.show('In List', context);
},
),

How to go to a specific page using the button? Flutter

I create Welcome Page, when clicking the button I would like the user to be redirected to the home page, but when I click it gives several errors. I don't know how to program very well in flutter, can someone help me?
I tried in many ways, and they all fail. If you have to press the button to restart the APP it would also work, but I don't know how to solve it in any way
WELCOME PAGE (I would like to be redirected to HOME by clicking the button)
import 'package:flutter/material.dart';
import '../../main.dart';
import '../models/items.dart';
import '../helpers/helper.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter/cupertino.dart';
void main() => runApp(Welcome());
Future<void> Return() async {
runApp(MyApp());
}
class Welcome extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: WelcomeScreen(),
);
}
}
class WelcomeScreen extends StatefulWidget {
final GlobalKey<ScaffoldState> parentScaffoldKey;
WelcomeScreen({Key key, this.parentScaffoldKey}) : super(key: key);
#override
_WelcomeScreenState createState() => _WelcomeScreenState();
}
class _WelcomeScreenState extends State<WelcomeScreen> {
List<Widget> slides = items
.map((item) => Container(
padding: EdgeInsets.symmetric(horizontal: 18.0),
child: Column(
children: <Widget>[
Flexible(
flex: 1,
fit: FlexFit.tight,
child: Image.asset(
item['image'],
fit: BoxFit.fitWidth,
width: 220.0,
alignment: Alignment.bottomCenter,
),
),
Flexible(
flex: 1,
fit: FlexFit.tight,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 30.0),
child: Column(
children: <Widget>[
Text(item['header'],
style: TextStyle(
fontSize: 50.0,
fontWeight: FontWeight.w300,
color: Color(0XFF3F3D56),
height: 2.0)),
Text(
item['description'],
style: TextStyle(
color: Colors.grey,
letterSpacing: 1.2,
fontSize: 16.0,
height: 1.3),
textAlign: TextAlign.center,
)
],
),
),
)
],
)))
.toList();
double currentPage = 0.0;
final _pageViewController = new PageController();
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: Helper.of(context).onWillPop,
child: Scaffold(
body: Stack(
alignment: AlignmentDirectional.topCenter,
children: <Widget>[
PageView.builder(
controller: _pageViewController,
itemCount: slides.length,
itemBuilder: (BuildContext context, int index) {
_pageViewController.addListener(() {
setState(() {
currentPage = _pageViewController.page;
});
});
return slides[index];
},
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
margin: EdgeInsets.only(top: 70.0),
padding: EdgeInsets.symmetric(vertical: 40.0),
)
),
Positioned(
bottom: 10,
child: RaisedButton(
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (context){
return HomeWidget();
},
highlightElevation: 2,
splashColor: Color(0xFF2F4565),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10)
),
padding: EdgeInsets.symmetric(horizontal: 40),
color: Color(0XFFEA5C44),
child: Text(
"Permitir",
style: TextStyle(color: Colors.white),
),
),
)
],
),
),
);
}
}
HOMEPAGE (I would like to be redirected to that page by clicking the button on the WELCOME page)
import 'package:flutter/material.dart';
import 'package:mvc_pattern/mvc_pattern.dart';
import '../../generated/l10n.dart';
import '../controllers/home_controller.dart';
import '../elements/CardsCarouselWidget.dart';
import '../elements/CaregoriesCarouselWidget.dart';
import '../elements/DeliveryAddressBottomSheetWidget.dart';
import '../elements/GridWidget.dart';
import '../elements/ProductsCarouselWidget.dart';
import '../elements/ReviewsListWidget.dart';
import '../elements/SearchBarWidget.dart';
import '../elements/ShoppingCartButtonWidget.dart';
import '../repository/settings_repository.dart' as settingsRepo;
import '../repository/user_repository.dart';
class HomeWidget extends StatefulWidget {
final GlobalKey<ScaffoldState> parentScaffoldKey;
HomeWidget({Key key, this.parentScaffoldKey}) : super(key: key);
#override
_HomeWidgetState createState() => _HomeWidgetState();
}
class _HomeWidgetState extends StateMVC<HomeWidget> {
HomeController _con;
#override
_HomeWidgetState() : super(HomeController()) {
_con = controller;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: new IconButton(
icon: new Icon(Icons.sort, color: Theme.of(context).hintColor),
onPressed: () => widget.parentScaffoldKey.currentState.openDrawer(),
),
automaticallyImplyLeading: false,
backgroundColor: Colors.transparent,
elevation: 0,
centerTitle: true,
title: ValueListenableBuilder(
valueListenable: settingsRepo.setting,
builder: (context, value, child) {
return Text(
value.appName ?? S.of(context).home,
style: Theme.of(context).textTheme.headline6.merge(TextStyle(letterSpacing: 1.3)),
);
},
),
actions: <Widget>[
new ShoppingCartButtonWidget(iconColor: Theme.of(context).hintColor, labelColor: Theme.of(context).accentColor),
],
),
body: RefreshIndicator(
onRefresh: _con.refreshHome,
child: SingleChildScrollView(
padding: EdgeInsets.symmetric(horizontal: 0, vertical: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: SearchBarWidget(
onClickFilter: (event) {
widget.parentScaffoldKey.currentState.openEndDrawer();
},
),
),
Padding(
padding: const EdgeInsets.only(top: 15, left: 20, right: 20),
child: ListTile(
dense: true,
contentPadding: EdgeInsets.symmetric(vertical: 0),
leading: Icon(
Icons.stars,
color: Theme.of(context).hintColor,
),
trailing: IconButton(
onPressed: () {
if (currentUser.value.apiToken == null) {
_con.requestForCurrentLocation(context);
} else {
var bottomSheetController = widget.parentScaffoldKey.currentState.showBottomSheet(
(context) => DeliveryAddressBottomSheetWidget(scaffoldKey: widget.parentScaffoldKey),
shape: RoundedRectangleBorder(
borderRadius: new BorderRadius.only(topLeft: Radius.circular(10), topRight: Radius.circular(10)),
),
);
bottomSheetController.closed.then((value) {
_con.refreshHome();
});
}
},
icon: Icon(
Icons.my_location,
color: Theme.of(context).hintColor,
),
),
title: Text(
S.of(context).top_markets,
style: Theme.of(context).textTheme.headline4,
),
subtitle: Text(
S.of(context).near_to + " " + (settingsRepo.deliveryAddress.value?.address ?? S.of(context).unknown),
style: Theme.of(context).textTheme.caption,
),
),
),
CardsCarouselWidget(marketsList: _con.topMarkets, heroTag: 'home_top_markets'),
ListTile(
dense: true,
contentPadding: EdgeInsets.symmetric(horizontal: 20),
leading: Icon(
Icons.trending_up,
color: Theme.of(context).hintColor,
),
title: Text(
S.of(context).trending_this_week,
style: Theme.of(context).textTheme.headline4,
),
subtitle: Text(
S.of(context).clickOnTheProductToGetMoreDetailsAboutIt,
maxLines: 2,
style: Theme.of(context).textTheme.caption,
),
),
ProductsCarouselWidget(productsList: _con.trendingProducts, heroTag: 'home_product_carousel'),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: ListTile(
dense: true,
contentPadding: EdgeInsets.symmetric(vertical: 0),
leading: Icon(
Icons.category,
color: Theme.of(context).hintColor,
),
title: Text(
S.of(context).product_categories,
style: Theme.of(context).textTheme.headline4,
),
),
),
CategoriesCarouselWidget(
categories: _con.categories,
),
Padding(
padding: const EdgeInsets.only(left: 20, right: 20, bottom: 20),
child: ListTile(
dense: true,
contentPadding: EdgeInsets.symmetric(vertical: 0),
leading: Icon(
Icons.trending_up,
color: Theme.of(context).hintColor,
),
title: Text(
S.of(context).most_popular,
style: Theme.of(context).textTheme.headline4,
),
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: GridWidget(
marketsList: _con.popularMarkets,
heroTag: 'home_markets',
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: ListTile(
dense: true,
contentPadding: EdgeInsets.symmetric(vertical: 20),
leading: Icon(
Icons.recent_actors,
color: Theme.of(context).hintColor,
),
title: Text(
S.of(context).recent_reviews,
style: Theme.of(context).textTheme.headline4,
),
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: ReviewsListWidget(reviewsList: _con.recentReviews),
),
],
),
),
),
);
}
}
First you need to set up the route:
MaterialApp(
// Start the app with the "/" named route. In this case, the app starts
// on the FirstScreen widget.
initialRoute: '/',
routes: {
// When navigating to the "/" route, build the FirstScreen widget.
'/': (context) => FirstScreen(), //NOTE: Change the FirstScreen() to your own screen's class name (ex: WelcomeScreen())
// When navigating to the "/second" route, build the SecondScreen widget.
'/second': (context) => SecondScreen(), //NOTE: Change the SecondScreen() to your own screen's class name (ex: HomeWidget())
'/third': (context) => ThirdScreen(),
},
);
And then, inside your button, navigate to the page:
// Within the `FirstScreen` widget
onPressed: () {
// Navigate to the second screen using a named route.
Navigator.pushNamed(context, '/second');
}
NOTE: One of your pages must be named as / to prevent error, for the full tutorial please visit this link