Flutter Renderboxoverflow - flutter

import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:provider/provider.dart';
import '../../Data/Globalvariable.dart' as global;
// import './customexpansionpanel.dart' as ex;
class Districtslayout extends StatefulWidget {
#override
_DistrictslayoutState createState() => _DistrictslayoutState();
}
class _DistrictslayoutState extends State<Districtslayout> {
#override
Widget build(BuildContext context) {
return Consumer(
builder: (context, global.DistrictModel districtModel, child) {
return _totalwig(districtModel.district);
});
}
_totalwig(districts) {
return SingleChildScrollView(
child: Column(children: [
...(districts).map(
(answer) {
return answer['district_id'] == 1000
? Text('Select_Text')
: ElevatedButton(
style: ButtonStyle(
elevation: MaterialStateProperty.all(24),
fixedSize: MaterialStateProperty.all(
Size(MediaQuery.of(context).size.width, 60))),
child: Text(
answer['district_name'],
style: TextStyle(fontSize: 20),
),
onPressed: () => print(answer['district_id'].toString()),
);
},
).toList(),
]),
);
}
// _createwig(districts) {
// List<Widget> columnContent = [];
// for (dynamic dis in districts) {
// columnContent.add(
// ListTile(
// title: dis['district_id']==1000?Text('Select State'):ElevatedButton(
// onPressed: ()=>print(dis['district_id']),
// child: Text(
// dis['district_name'],
// style: TextStyle(fontSize: 18.0),
// ),
// ),
// ),
// );
// }
// return columnContent;
// }
}
Here I am getting an error of renderbox overflow even though i have wrapped column into SingleChildScrollView in my widget tree i have a sizedbox then a custom widget then a sizedbox then a singlechildscrollview then column
I hope this is sufficient if you want any code you can just comment and i will update the code
import 'package:cowin_slot_tracker/Data/styles/expansionbutton.dart';
import '../../src/By_District/states.dart';
import 'package:flutter/material.dart';
import './districts.dart';
import 'package:provider/provider.dart';
import '../../Data/Globalvariable.dart' as global;
class DistrictHome extends StatefulWidget {
#override
State<StatefulWidget> createState() => DistrictHomeState();
}
class DistrictHomeState extends State<DistrictHome> {
#override
Widget build(BuildContext context) {
return Stack(
children: [
Column(
children: [
Padding(padding: EdgeInsets.only(top: 120)
// color: Colors.white.withOpacity(1),
),
Divider(
thickness: 2,
),
Text("hey"),
],
),
ChangeNotifierProvider(
create: (_) => global.DistrictModel(),
child: Consumer(
builder: (context, global.DistrictModel pinModel, child) {
return Column(
children: [
SizedBox(height: 60, child: StateMenu()),
SizedBox(
child: ExpnButton(
wiget: Districtslayout(),
hint: 'Select Districts',
)),
],
);
}),
),
],
);
}
}

wrapSingleChildScrollView with Expanded, like
Expanded(
child: SingleChildScrollView(
child: Column(
does it solve in your case?

Related

Flutter Custom SideBar Not Taking Full Height

I am working on a custom sidebar for my app since I dont like the default drawer that flutter comes with.
Everything works fine, that is, the sidebar takes the entire height of the mobile phone
until I render the page contents along the sidebar as shown below
Here's the Main contents code:
import 'package:api_example_app/LandingScreen/components/control_button.dart';
import 'package:api_example_app/LandingScreen/components/default_button.dart';
import 'package:api_example_app/SensorScreen/charts/GasChart.dart';
import 'package:api_example_app/SensorScreen/charts/HumChart.dart';
import 'package:api_example_app/SensorScreen/charts/MoisChart.dart';
import 'package:api_example_app/SensorScreen/charts/NurChart.dart';
import 'package:api_example_app/SensorScreen/charts/PhChart.dart';
import 'package:api_example_app/SensorScreen/charts/TemChart.dart';
import 'package:api_example_app/SensorScreen/charts/chartComponents/HumCard.dart';
import 'package:api_example_app/SensorScreen/components/sensor_screen.dart';
import 'package:api_example_app/constants.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
class LandingScreenBody extends StatefulWidget {
#override
_LandingScreenBodyState createState() => _LandingScreenBodyState();
}
class _LandingScreenBodyState extends State<LandingScreenBody> {
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Padding(
padding: EdgeInsets.symmetric(horizontal: size.width * 0.05),
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
SizedBox(height: size.height * 0.1),
Center(
child: Text(
'ngDAQ',
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black,
fontSize: 25,
),
),
),
SizedBox(height: size.height * 0.01),
Center(
child: Text(
'The ngDAQ is a Smart Agriculture solution based on IoT, seeking to increase farm productivity by automation and monitoring.',
textAlign: TextAlign.center,
style: TextStyle(color: kDarkGreyColor, fontSize: 12),
),
),
SizedBox(height: size.height * 0.05),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
CardsParent(
size: size,
icon: FontAwesomeIcons.temperatureHigh,
title: 'Tem',
subtitle: '33C',
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => new TemChart()));
},
),
CardsParent(
size: size,
title: 'Hum ',
subtitle: '75%',
icon: FontAwesomeIcons.cloudShowersHeavy,
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => new HumChart()));
},
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
CardsParent(
size: size,
icon: FontAwesomeIcons.hourglass,
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => new MoisChart()));
},
title: 'Mos',
subtitle: '40',
),
CardsParent(
size: size,
title: 'PH ',
subtitle: '14',
icon: FontAwesomeIcons.meteor,
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => new PhChart()));
},
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
CardsParent(
size: size,
icon: FontAwesomeIcons.leaf,
title: 'Nur',
subtitle: 'Good',
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => new NurChart()));
},
),
CardsParent(
size: size,
title: 'Gas ',
subtitle: 'Good',
icon: FontAwesomeIcons.flask,
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => new GasChart()));
},
),
],
),
SizedBox(height: size.height * 0.05),
// DefaultButton(
// size: size,
// title: "Next",
// press: () {
// Navigator.push(
// context,
// CupertinoPageRoute(
// builder: (context) => SensorScreen(),
// ),
// );
// },
// ),
],
),
),
);
}
}
Heres' the Sidebar Code:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:rxdart/rxdart.dart';
// import 'package:rxdart/rxdart.dart';
import '../../constants.dart';
class SideBar extends StatefulWidget {
// const SideBar({Key ? key}) : super(key: key);
#override
_SideBarState createState() => _SideBarState();
}
class _SideBarState extends State<SideBar>
with SingleTickerProviderStateMixin<SideBar> {
AnimationController _animationController;
StreamController<bool> isSidebarOpenedStreamController;
Stream<bool> isSidebarOpenedStream;
StreamSink<bool> isSidebarOpenedSink;
// final bool isSidebarOpened = true;
final _animationDuration = const Duration(milliseconds: 500);
#override
void initState() {
super.initState();
_animationController =
AnimationController(vsync: this, duration: _animationDuration);
isSidebarOpenedStreamController = PublishSubject<bool>();
isSidebarOpenedStream = isSidebarOpenedStreamController.stream;
isSidebarOpenedSink = isSidebarOpenedStreamController.sink;
}
#override
void dispose() {
_animationController.dispose();
isSidebarOpenedStreamController.close();
isSidebarOpenedSink.close();
super.dispose();
}
void onIconPressed() {
final animationStatus = _animationController.status;
final isAnimationCompleted = animationStatus == AnimationStatus.completed;
if (isAnimationCompleted) {
isSidebarOpenedSink.add(false);
_animationController.reverse();
} else {
isSidebarOpenedSink.add(true);
_animationController.forward();
}
}
#override
Widget build(BuildContext context) {
final screenWidth = MediaQuery.of(context).size.width;
return StreamBuilder<bool>(
initialData: false,
stream: isSidebarOpenedStream,
builder: (context, isSideBarOpenedAsync) {
return AnimatedPositioned(
duration: _animationDuration,
top: 0,
bottom: 0,
left: isSideBarOpenedAsync.data ? 0 : 0,
right: isSideBarOpenedAsync.data ? 0 : screenWidth - 45,
child: Row(
children: <Widget>[
Expanded(
child: Container(
color: kOrangeColor,
child: Column(
children: <Widget>[],
),
),
),
Align(
alignment: Alignment(0, -0.9),
child: GestureDetector(
onTap: () {
onIconPressed();
},
child: Container(
width: 35,
height: 80,
color: kOrangeColor,
alignment: Alignment.centerLeft,
child: AnimatedIcon(
progress: _animationController.view,
icon: AnimatedIcons.menu_close,
color: Colors.white,
size: 30,
),
),
),
),
],
),
);
},
);
}
}
The Layout Where the render is done:
import 'package:api_example_app/LandingScreen/components/body.dart';
import 'package:flutter/material.dart';
import '../../constants.dart';
import 'sidebar.dart';
class SideBarLayout extends StatelessWidget {
// const SideBarLayout({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
LandingScreenBody(),
SideBar(),
],
),
);
}
}
I dont know what I did wrong.
Inside SideBar, you need to surround it with Container widget, and set its height to double.infinity;
//Inside SideBar
return Container(
width: 200,
height: double.infinity,
child: StreamBuilder<bool> (
...
);
);
I solved it, thanks to #eyoeldefare.
From the main home, where I returned padding, I [return container instead, then, add:
return Container(
height: double.infinity,
(
...
),
);

The method 'data' was called on null. Receiver: null Tried calling: data()

When I try to put the value added to Firebase into the Droppdown button, I get the following error
The method 'data' was called on null.Receiver: nullTried calling: data ()
I think the cause of the error is that I can't call the value from Todo.dart to post_page.dart.
Using debag, todolist is null in post_page.dart.
I would appreciate it if you could answer.
post_page.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import "package:flutter/material.dart";
import 'package:habit_boddy/component/post/task_add_button.dart';
import 'package:habit_boddy/utils/constants.dart';
import 'package:habit_boddy/view/common/components/drop_text.dart';
import 'package:habit_boddy/view/common/components/post_caption_part.dart';
import 'package:habit_boddy/view/post/page/Todo.dart';
import 'package:habit_boddy/view/post/page/detail_page.dart';
import 'package:habit_boddy/view/post/page/picture_page.dart';
import 'package:habit_boddy/view/post/page/task_setting.dart';
import 'package:habit_boddy/view_models/post_view_model.dart';
import 'package:habit_boddy/view_models/todo_view_model.dart';
import 'package:provider/provider.dart';
import 'confirm_dialog.dart';
class PostPage extends StatefulWidget {
#override
_PostPageState createState() => _PostPageState();
}
class _PostPageState extends State<PostPage> {
final _captionController = TextEditingController();
#override
void initState() {
_captionController.addListener(_onCaptionUpdated);
super.initState();
}
#override
void dispose() {
_captionController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return ChangeNotifierProvider<ToDoViewModel>(
create:(_) => ToDoViewModel()..getRealtime(),
child: Scaffold(
appBar: AppBar(
backgroundColor: Colors.amber,
actions: [
ElevatedButton(
child: Text('Post'),
style: ElevatedButton.styleFrom(
primary: Colors.orange,
onPrimary: Colors.white,
),
onPressed: () => showConfirmedDialog(
context: context,
title: "Post",
content: "May I post?",
onConfirmed: (isConfirmed) {
if (isConfirmed) {
_post(context);
}
}))
],
),
body: Consumer<ToDoViewModel>(builder: (context, model, child) {
final todoList = model.todoList;
return DropdownButton<Todo>(
items: todoList.map((todo) =>
DropdownMenuItem<Todo>(
value: Todo(title: todo.title),
child: Text(todo.title),
)
).toList(),
);
}),
floatingActionButton:
Consumer<ToDoViewModel>(builder: (context, model, child) {
return FloatingActionButton(
onPressed: () async {
await Navigator.push(
context,
MaterialPageRoute(builder: (context) => TaskSetting()),
);
},
child: Icon(Icons.add),
);
}),
),
);
}
_onCaptionUpdated() {
final viewModel = Provider.of<PostViewModel>(context, listen: false);
viewModel.caption = _captionController.text;
print("caption: ${viewModel.caption}");
}
void _post(BuildContext context) {
final postViewModel = Provider.of<PostViewModel>(context, listen: false);
}
}
Widget build(BuildContext context) {
final postViewModel = Provider.of<PostViewModel>(context);
return Container(
child: Padding(
padding: const EdgeInsets.all(40.0),
child: SingleChildScrollView(
child: Column(
children: [
Row(
children: [
Expanded(
flex: 3,
child: Container(
child: Padding(
padding: const EdgeInsets.only(left: 10.0),
child: DropText(),
),
height: 230),
),
Expanded(
flex: 1,
child: Padding(
padding: const EdgeInsets.only(bottom: 155.0),
child: TaskAdd(),
)),
],
),
Container(
child: Padding(
padding: const EdgeInsets.only(top: 20.0),
child: DetailPost(),
),
height: 270),
Row(
children: [
PicturePage(),
postViewModel.imageFile == null
? Container()
: Container(
height: 60,
width: 60,
child: SingleChildScrollView(
child: PostCaptionPart(
from: PostCaptionOpenMode.FROM_POST,
),
),
)
],
),
],
),
),
),
);
}
Todo.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:habit_boddy/view_models/todo_view_model.dart';
class Todo {
final ToDoViewModel model;
String title = "";
DateTime createdAt;
Todo({DocumentSnapshot doc, this.title, this.model, this.createdAt}){
this.title = doc.data()["title"];
final Timestamp timestamp = doc.data()['createdAt'];
this.createdAt = timestamp.toDate();
}
}
I believe this line is causing the error.
DropdownMenuItem<Todo>(
value: Todo(title: todo.title),
You're calling doc.data() in the Todo constructor without passing the doc variable, hence calling .data() on a null variable. You should instead get the title first, then pass it to the constructor when instantiating the Todo object.
If you really need to pass the doc variable, say if you need it for something else, make it required in the constructor and assert that it is not null.
Todo({#required DocumentSnapshot doc, this.title, this.model, this.createdAt}) : assert(doc != null){
...
}
You should look into Dart null safety as well, which would help to avoid this type of issue.

How to Show the Json api data in the dynamic Bar Charts in flutter/

**im trying development Covid 19 app in a flutter.And trying to render a dynamic bar chart in the dashboard of the application. I try to write some codes but this is not going to work to fetching data from API show into it bar dynamic bar charts.
Here are some codes which I tried my best but showing error.
here is my testing application screenshot
enter image description here
enter code here
import 'dart:convert';
import 'dart:convert';
import 'package:NavigationBar/userModel.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'dart:math';
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter_sparkline/flutter_sparkline.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:NavigationBar/userModel.dart';
import 'package:http/http.dart'as http;
class Dashboard extends StatelessWidget {
#override
Widget build(BuildContext context) {
// TODO: implement build
throw UnimplementedError();
}
}
#override
Widget build(BuildContext context)
{
return MaterialApp(
debugShowCheckedModeBanner: false,
home: HomePage(
),
);
}
class HomePage extends StatefulWidget
{
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage>
{
Map mapResponce;
static List<charts.Series< addcharts, String>> get series => null;
Future fetchdata() async{
http.Response response;
response = await http.get("https://disease.sh/v3/covid-19/all");
if(response.statusCode==200){
setState(() {
mapResponce =json.decode(response.body);
});
}
}
//static var chartdisplay;
//get _getUser => null;
#override
void initState() {
// TODO: implement initState
fetchdata();
super.initState();
}
Widget databody() {
var data =
[
addcharts("val1", mapResponce['v1']),
addcharts("val2", 20),
addcharts("val3", 30),
addcharts("val4", 40),
addcharts("val5", 50),
addcharts("val6", 60),
addcharts("val7", 70),
];
var series = [charts.Series(
domainFn: (addcharts addcharts, _) => addcharts.label,
measureFn: (addcharts addcharts, _) => addcharts.value,
id: 'addcharts',
data: data,
),
];
}
var chartdisplay = charts.BarChart(series,
animationDuration: Duration(microseconds: 2000),
);
Material myItems(IconData icon,String heading,int color){
return Material(
color: Colors.white,
elevation: 14.0,
shadowColor: Colors.grey,
borderRadius: BorderRadius.circular(24.0),
child: Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Center(
child:
//Text part
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(heading,
style: TextStyle(
color: new Color(color),
fontSize: 20.0
),
),
),
),
Material(
color: new Color(color),
borderRadius: BorderRadius.circular(24.0),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Icon(
icon,
color: Colors.white,
size: 30.0,
),
),
),
],
)
],
),
),
),
);
}
#override
Widget build(BuildContext context)
{
var chartdisplay;
return Scaffold(
appBar: AppBar(
title: Text("Dashboard",
style: TextStyle(
color: Colors.white,
)),
centerTitle:true,
leading: IconButton(icon: Icon(Icons.arrow_back),
onPressed: (){
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => HomePage(),
));
}
),
),
body:StaggeredGridView.count(
crossAxisCount: 2,
crossAxisSpacing: 12.0,
mainAxisSpacing: 12.0,
padding: EdgeInsets.symmetric(horizontal: 16.0,vertical: 8.0),
children: <Widget>[
myItems(Icons.add_alert,"ALERT",0xfff44336),
myItems(Icons.ad_units,"22.13",0xffed622b),
myItems(Icons.ad_units,"0",0xffed622b),
myItems(Icons.read_more_outlined,"22.13",0xffed622b),
myItems(Icons.date_range,"2/2/2021",0xffed622b),
// FutureBuilder(
// future: _getUser,
// builder: (context,snapshot) {
// if (snapshot.hasData) {
//
// }
//
// else {
// return CircularProgressIndicator();
// }
// },),
databody(),
Expanded(
flex: 3,
child:Container(
padding: EdgeInsets.all(40.0),
height: MediaQuery.of(context).size.height*0.30,
color: Colors.white,
child: chartdisplay,
),
),
Expanded(
flex: 3,
child:Container(
padding: EdgeInsets.all(40.0),
height: MediaQuery.of(context).size.height*0.30,
color: Colors.white,
child: chartdisplay,
),
),
],
staggeredTiles: [
StaggeredTile.extent(2, 130.0),
StaggeredTile.extent(1, 150.0),
StaggeredTile.extent(1, 150.0),
StaggeredTile.extent(1, 150.0),
StaggeredTile.extent(1, 150.0),
StaggeredTile.extent(2, 250.0),
StaggeredTile.extent(2, 250.0),
],
),
);
}
}
// class dashboard extends StatelessWidget {
// #override
// Widget build(BuildContext context) {
// return Container();
// }
//
// }
class addcharts
{
final String label;
final int value;
addcharts(this.label,this.value);
}
Remove this line from this code
Widget build(BuildContext context) {
// TODO: implement build
//throw UnimplementedError(); //this line
}

Flutter Error : Could not find the correct Provider<Cart> above this ProductLandingPage Widget

I am creating an e-commerce app where homepage is kind of page where all fields like categories and other info is given.
here is my flow of screens ...
HomeScreen -> CategoryPage -> ProductByCategory -> ProductLandingPage
I am getting error. New to Coding and learning Providers for 1st time, Not able to resolve this issue.
Error: Could not find the correct Provider above this ProductLandingPage Widget
To fix, please:
Ensure the Provider is an ancestor to this ProductLandingPage Widget
Provide types to Provider
Provide types to Consumer
void main() {
runApp(MaterialApp(
home: MultiProvider(
providers: [
ChangeNotifierProvider.value(
value: Cart(),
)
],
child: HomeScreen(),
),
debugShowCheckedModeBanner: false,
));
}
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.redAccent,
title: Text('Factory2Homes'),
actions: <Widget>[
IconButton(icon: Icon(Icons.search), onPressed: () {}),
Consumer<Cart>(
builder: (_, cart, ch) => Badge(
child: ch,
value: cart.itemCount.toString(),
),
child: IconButton(
icon: Icon(
Icons.shopping_cart,
),
onPressed: () {
},
),
),
],
),
body: SingleChildScrollView(
child: Column(
children: <Widget>[
Container(height: 500, child: CategoryPage()),
],
),
),
);
}
}
class CategoryPage extends StatefulWidget {
#override
_CategoryPageState createState() => _CategoryPageState();
}
class _CategoryPageState extends State<CategoryPage> {
#override
Widget build(BuildContext context) {
return FutureBuilder<List<AllCategory>>(
future: getCategoryList(http.Client()),
builder: (context, snapshot) {
if (snapshot.hasError) print(snapshot.error);
return snapshot.hasData
? ListOfCategories(
categories: snapshot.data,
)
: Center(
child: CircularProgressIndicator(
backgroundColor: Colors.red,
));
},
);
}
}
class ListOfCategories extends StatelessWidget {
final List<AllCategory> categories;
ListOfCategories({this.categories});
#override
Widget build(BuildContext context) {
return GridView.builder(
physics: NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
),
itemCount: categories.length,
itemBuilder: (context, index) {
return InkWell(
onTap: (){
Navigator.push(context, MaterialPageRoute(builder: (context) => ProductByCategory(category: categories[index],)));
},
child: Image.network(categories[index].categoryIcon));
},
);
}
}
class ProductByCategory extends StatefulWidget {
final AllCategory category;
final CarouselSlider carouselslider;
ProductByCategory({this.category, this.carouselslider});
#override
_ProductByCategoryState createState() => _ProductByCategoryState();
}
class _ProductByCategoryState extends State<ProductByCategory> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: <Widget>[
Consumer<Cart>(
builder: (_, cart, ch) => Badge(
child: ch,
value: cart.itemCount.toString(),
),
child: IconButton(
icon: Icon(
Icons.shopping_cart,
),
onPressed: () {
},
),
),
IconButton(icon: Icon(Icons.search), onPressed: () {}),
],
),
body: FutureBuilder<List<Product>>(
future: getCategoryByProduct(http.Client(), widget.category.id),
builder: (context, snapshot) {
if (snapshot.hasError) print(snapshot.error);
if (snapshot.hasData) {
return ProductByCategoryScreen(
product: snapshot.data,
);
} else {
return Center(child: CircularProgressIndicator());
}
},
),
);
}
}
class ProductByCategoryScreen extends StatefulWidget {
final List<Product> product;
ProductByCategoryScreen({this.product});
#override
_ProductByCategoryScreenState createState() =>
_ProductByCategoryScreenState();
}
class _ProductByCategoryScreenState extends State<ProductByCategoryScreen> {
#override
Widget build(BuildContext context) {
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
),
itemCount: widget.product.length,
itemBuilder: (context, index) {
return InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
ProductLandingPage(widget.product[index])));
},
child:
Card(child: Image.network(widget.product[index].productPhoto)));
},
);
}
}
class ProductLandingPage extends StatefulWidget {
final Product product;
ProductLandingPage(this.product);
#override
_ProductLandingPageState createState() => _ProductLandingPageState();
}
class _ProductLandingPageState extends State<ProductLandingPage> {
#override
Widget build(BuildContext context) {
final cart = Provider.of<Cart>(context, listen: false);
return Scaffold(
appBar: AppBar(
actions: <Widget>[
],
),
body: SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
color: Colors.green,
height: MediaQuery.of(context).size.height / 2,
child: Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Image.network(widget.product.productPhoto),
),
),
Divider(
thickness: 1,
),
Container(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(this.widget.product.productName),
),
),
Divider(),
Container(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(left: 10.0),
child: Text(
'₹' + '${this.widget.product.productSalePrice}',
style: TextStyle(
fontSize: 30, fontWeight: FontWeight.w500),
),
),
],
),
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Center(
child: Text(
'MRP:' + '${this.widget.product.productListPrice}'),
),
),
],
),
),
Divider(),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(left: 10.0),
child: Text(
'Description',
style:
TextStyle(fontSize: 18, fontWeight: FontWeight.w500),
),
),
],
),
Container(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Text(this.widget.product.productDescription),
),
),
],
),
),
bottomNavigationBar: Container(
width: MediaQuery.of(context).size.width,
height: 45.0,
child: RaisedButton(
onPressed: () {
cart.addItem(
'${widget.product.productId}',
widget.product.productListPrice,
widget.product.productName,
);
},
color: Colors.redAccent,
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
Icons.card_travel,
color: Colors.white,
),
SizedBox(
width: 4.0,
),
Text(
"ADD TO CART",
style: TextStyle(color: Colors.white),
),
],
),
),
),
));
}
}
class CartItem {
final String id;
final String title;
final int quantity;
final int price;
CartItem({
this.id,
this.title,
this.quantity,
this.price,
});
}
class Cart with ChangeNotifier {
Map<String, CartItem> _items;
Map<String, CartItem> get items {
return {..._items};
}
int get itemCount{
return _items==null ?0 :_items.length;
}
void addItem(
String productId,
int productListPrice,
String productName,
) {
if (_items.containsKey(productId)) {
_items.update(
productId,
(existingCartItem) => CartItem(
id: existingCartItem.id,
title: existingCartItem.title,
price: existingCartItem.price,
quantity: existingCartItem.quantity + 1,
));
} else {
_items.putIfAbsent(
productId,
() => CartItem(
id: DateTime.now().toString(),
title: productName,
price: productListPrice,
quantity: 1,
));
}
}
}
The idea of Provider is to lift the state management above the widgets so different children can easily access its state. So it would be helpful if you moved the HTTP request from the widget tree (where it will be called every time the UI updates, so users use more bandwidth than needed) to a provider that is created above the tree. Therefore the state doesn't need to passed around from widget to widget.
Try watching this amazing talk from the flutter team to get a better understanding of how to use provider: https://youtu.be/d_m5csmrf7I
Bdw read this StackOverflow answer about why .value isn't what you desire: How to deal with unwanted widget build?
So you should make the app like this
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context) => Cart(),
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Factory2Homes',
home: HomeScreen(),
),
);
}
}
i got it working by changing main.dart code to below code:
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ChangeNotifierProvider.value(value: Cart(),
child:MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Factory2Homes',
home: HomeScreen(),
),);
}
}

Scoped Model initialized when Key Board is popped up for TextField

I have two tabs with a Default Tab bar. I have used Scoped-model for passing data between two tabs. When I insert data in one tab and press text Field again so that keyboard pops up but whole model gets reinitialized.
I have tried AutomaticKeepAliveClientMixin but no result. I have found out that every time I press the Text Field, keyBoard pops up and the Scoped model gets initialized. I have checked that by printing string in Scoped-Model constructor.
Here is my TabView
import 'package:flutter/material.dart';
import 'package:flutter/material.dart';
import 'package:basicflutter/tabs/FirstScreen.dart';
import 'package:basicflutter/tabs/SecondScreen.dart';
import 'package:basicflutter/models/product.dart';
import 'package:basicflutter/scopedModel/addproduct.dart';
import 'package:scoped_model/scoped_model.dart';
class MyTabs extends StatelessWidget {
static String tag = 'tab-page';
#override
Widget build(BuildContext context) {
return ScopedModel<ProductsModel>(
model: ProductsModel(),
child: MaterialApp(
home: DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
bottom: TabBar(
tabs: [
Tab(icon: Icon(Icons.directions_car)),
Tab(icon: Icon(Icons.directions_transit)),
],
),
title: Text('Flutter Tabs Example'),
),
body: TabBarView(
children: [
FirstScreen(),
SecondScreen(),
],
),
),
),
),
);
}
}
Here is my FirstScreen which takes Name and Image as input and then inserts them in an ArrayList
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:basicflutter/tabs/SecondScreen.dart';
import 'package:basicflutter/models/product.dart';
import 'package:basicflutter/scopedModel/addproduct.dart';
import 'package:scoped_model/scoped_model.dart';
class FirstScreen extends StatefulWidget {
#override
State<StatefulWidget> createState() => _FirstScreenState();
}
class _FirstScreenState extends State<FirstScreen>
with AutomaticKeepAliveClientMixin<FirstScreen> {
File _image;
final NameController = TextEditingController();
#override
void initState() {
super.initState();
print("InitState called") ;
}
#override
// TODO: implement wantKeepAlive
bool get wantKeepAlive => true;
#override
Widget build(BuildContext context) {
final ProductName = TextFormField(
controller: NameController,
autofocus: false,
obscureText: false,
decoration: InputDecoration(
hintText: 'Prodcut Name',
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(borderRadius: BorderRadius.circular(32.0)),
),
);
final AddProduct = Padding(
padding: EdgeInsets.symmetric(vertical: 16.0),
child: Column(
children: <Widget>[
ScopedModelDescendant<ProductsModel>(
rebuildOnChange: false,
builder: (context, child, model) => Padding(
padding: EdgeInsets.symmetric(vertical: 16.0),
child: RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(24),
),
onPressed: (){
ModelProduct newProduct = ModelProduct(NameController.text,_image);
model.AddNewProduct(newProduct) ;
setState(() {
NameController.clear();
_image = null ;
});
},
padding: EdgeInsets.all(12),
color: Colors.lightBlueAccent,
child: Text('Add product', style: TextStyle(color: Colors.white)),
),
)
)
],
),
);
Future getImage() async {
var taken_image = await ImagePicker.pickImage(source: ImageSource.camera);
setState(() {
_image = taken_image;
});
}
return Scaffold(
body: GestureDetector(
onTap: (){FocusScope.of(context).requestFocus(new FocusNode());},
child: Container(
padding: EdgeInsets.all(20),
child: new ListView(
children: [
SizedBox(height: 20.0),
Text(
'Add your product here',
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
),
SizedBox(height: 20.0),
ProductName,
SizedBox(height: 20.0),
_image == null
? Center(
child: new Container(
padding: EdgeInsets.all(20),
child: Text('No image selected.')))
: Image.file(_image),
SizedBox(
height: 20.0,
),
AddProduct,
],
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: getImage,
child: Icon(Icons.camera),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
Here is my SecondScreen which show the data in ListView
import 'package:flutter/material.dart';
import 'package:basicflutter/tabs/FirstScreen.dart';
import 'package:basicflutter/models/product.dart';
import 'package:basicflutter/scopedModel/addproduct.dart';
import 'package:scoped_model/scoped_model.dart';
class SecondScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Scaffold(
body: new ScopedModelDescendant<ProductsModel>(
builder: (context, child, model) => Container(
child: new ListView.builder(
itemCount: model.count,
itemBuilder: (BuildContext context, int index) {
return new Card(
child: Column(
children: <Widget>[
Text(model.GetAllProducts[index].name),
Container(
width: 250.0,
height: 250.0,
alignment: Alignment.center,
child:
model.GetAllProducts[index].image == null
? Center(
child: new Container(
padding: EdgeInsets.all(20),
child: Text('No image selected.')))
: Image.file(model.GetAllProducts[index].image ),
),
],
),
);
},
),
)));
}
}
Here is my PODO which
import 'dart:io' ;
class ModelProduct {
String name ;
File image ;
ModelProduct(this.name,this.image);
}
And lastly here is my Scoped-Model
import 'package:flutter/material.dart';
import 'package:basicflutter/tabs/FirstScreen.dart';
import 'package:basicflutter/tabs/SecondScreen.dart';
import 'package:basicflutter/models/product.dart';
import 'package:basicflutter/scopedModel/addproduct.dart';
import 'package:scoped_model/scoped_model.dart';
import 'dart:io';
class ProductsModel extends Model {
final List<ModelProduct> productList = List<ModelProduct>();
ProductsModel(){
print("ProductsModel init") ;
}
void AddNewProduct(ModelProduct p) {
productList.add(p);
notifyListeners() ;
print(this.count);
}
int get count => productList.length ;
List<ModelProduct> get GetAllProducts => productList ;
}
Widget build(BuildContext context) {
return ScopedModel<ProductsModel>(
model: ProductsModel(),
You've likely solved this by now but... this is your problem. You're initializing your model in the build method. It needs to be initialized outside of that.
For instance :
ProductsModel productsModel = ProductsModel();
Widget build(BuildContext context) {
return ScopedModel<ProductsModel>(
model: productsModel,